mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Implement JSManaged for DOM objects.
This commit is contained in:
parent
061269f963
commit
625325434b
137 changed files with 3644 additions and 2778 deletions
|
@ -4,12 +4,15 @@
|
|||
|
||||
use dom::bindings::utils::Reflectable;
|
||||
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JSVal, JS_ObjectIsCallable};
|
||||
use js::jsapi::JS_GetProperty;
|
||||
use js::{JSVAL_IS_OBJECT, JSVAL_TO_OBJECT};
|
||||
use js::jsapi::{JS_GetProperty, JSTracer, JS_CallTracer};
|
||||
use js::{JSVAL_IS_OBJECT, JSVAL_TO_OBJECT, JSTRACE_OBJECT};
|
||||
|
||||
use std::cast;
|
||||
use std::libc;
|
||||
use std::ptr;
|
||||
|
||||
use extra::serialize::{Encodable, Encoder};
|
||||
|
||||
pub enum ExceptionHandling {
|
||||
// Report any exception and don't throw it to the caller code.
|
||||
eReportExceptions,
|
||||
|
@ -26,6 +29,20 @@ pub struct CallbackInterface {
|
|||
callback: *JSObject
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for CallbackInterface {
|
||||
fn encode(&self, s: &mut S) {
|
||||
unsafe {
|
||||
let tracer: *mut JSTracer = cast::transmute(s);
|
||||
"callback".to_c_str().with_ref(|name| {
|
||||
(*tracer).debugPrinter = ptr::null();
|
||||
(*tracer).debugPrintIndex = -1;
|
||||
(*tracer).debugPrintArg = name as *libc::c_void;
|
||||
JS_CallTracer(tracer as *JSTracer, self.callback, JSTRACE_OBJECT as u32);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CallbackContainer {
|
||||
fn callback(&self) -> *JSObject;
|
||||
}
|
||||
|
@ -66,7 +83,7 @@ pub fn GetJSObjectFromCallback<T: CallbackContainer>(callback: &T) -> *JSObject
|
|||
|
||||
pub fn WrapCallThisObject<T: 'static + CallbackContainer + Reflectable>(cx: *JSContext,
|
||||
_scope: *JSObject,
|
||||
p: @mut T) -> *JSObject {
|
||||
p: ~T) -> *JSObject {
|
||||
let obj = GetJSObjectFromCallback(p);
|
||||
assert!(obj.is_not_null());
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ DOMInterfaces = {
|
|||
|
||||
'Blob': [
|
||||
{
|
||||
'headerFile': 'nsIDOMFile.h',
|
||||
},
|
||||
#{
|
||||
# 'workers': True,
|
||||
|
@ -121,19 +120,14 @@ DOMInterfaces = {
|
|||
}],
|
||||
|
||||
'CharacterData': {
|
||||
'nativeType': 'AbstractNode',
|
||||
'concreteType': 'CharacterData',
|
||||
'pointerType': ''
|
||||
},
|
||||
|
||||
'ClientRect': [
|
||||
{
|
||||
'nativeType': 'ClientRect',
|
||||
}],
|
||||
|
||||
'ClientRectList': [
|
||||
{
|
||||
'nativeType': 'ClientRectList',
|
||||
}],
|
||||
|
||||
'Console': {
|
||||
|
@ -150,8 +144,6 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'Document': {
|
||||
'nativeType': 'AbstractDocument',
|
||||
'pointerType': '',
|
||||
'customTrace': 'trace',
|
||||
'needsAbstract': [
|
||||
'createComment',
|
||||
|
@ -165,15 +157,12 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'DOMException': {
|
||||
'nativeType': 'DOMException',
|
||||
},
|
||||
|
||||
'DOMImplementation': {
|
||||
'nativeType': 'DOMImplementation',
|
||||
},
|
||||
|
||||
'DOMParser': {
|
||||
'nativeType': 'DOMParser',
|
||||
},
|
||||
|
||||
'DOMSettableTokenList': [
|
||||
|
@ -195,15 +184,10 @@ DOMInterfaces = {
|
|||
}],
|
||||
|
||||
'Element': {
|
||||
'nativeType': 'AbstractNode',
|
||||
'pointerType': '',
|
||||
'needsAbstract': ['getClientRects', 'getBoundingClientRect', 'setAttribute', 'setAttributeNS', 'removeAttribute', 'removeAttributeNS', 'id', 'attributes', 'innerHTML', 'outerHTML']
|
||||
},
|
||||
|
||||
'Event': {
|
||||
'nativeType': 'AbstractEvent',
|
||||
'concreteType': 'Event',
|
||||
'pointerType': '',
|
||||
},
|
||||
|
||||
'EventListener': {
|
||||
|
@ -211,9 +195,6 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'EventTarget': {
|
||||
'nativeType': 'AbstractEventTarget',
|
||||
'concreteType': 'EventTarget',
|
||||
'pointerType': '',
|
||||
'needsAbstract': ['dispatchEvent']
|
||||
},
|
||||
|
||||
|
@ -241,22 +222,12 @@ DOMInterfaces = {
|
|||
|
||||
'HTMLCollection': [
|
||||
{
|
||||
'nativeType': 'HTMLCollection',
|
||||
'pointerType': '@mut '
|
||||
}],
|
||||
|
||||
'HTMLDocument': {
|
||||
'nativeType': 'AbstractDocument',
|
||||
'pointerType': '',
|
||||
'customTrace': 'trace'
|
||||
},
|
||||
|
||||
'HTMLFormElement': {
|
||||
'nativeType': 'AbstractNode',
|
||||
'pointerType': '',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'HTMLOptionsCollection': [
|
||||
{
|
||||
'nativeType': 'nsHTMLOptionCollection',
|
||||
|
@ -306,27 +277,21 @@ DOMInterfaces = {
|
|||
}],
|
||||
|
||||
'MouseEvent': {
|
||||
'nativeType': 'AbstractEvent',
|
||||
'concreteType': 'MouseEvent',
|
||||
'pointerType': '',
|
||||
},
|
||||
|
||||
'Navigator': {
|
||||
},
|
||||
|
||||
'Node': {
|
||||
'nativeType': 'AbstractNode',
|
||||
'concreteType': 'Node',
|
||||
'pointerType': '',
|
||||
'needsAbstract': [
|
||||
'appendChild',
|
||||
'insertBefore',
|
||||
'replaceChild',
|
||||
'childNodes',
|
||||
'insertBefore',
|
||||
'nodeName',
|
||||
'nodeValue',
|
||||
'removeChild',
|
||||
'replaceChild',
|
||||
'textContent',
|
||||
'childNodes',
|
||||
'contains',
|
||||
'isEqualNode',
|
||||
]
|
||||
|
@ -334,8 +299,6 @@ DOMInterfaces = {
|
|||
|
||||
'NodeList': [
|
||||
{
|
||||
'nativeType': 'NodeList',
|
||||
'pointerType': '@mut ',
|
||||
'resultNotAddRefed': ['item']
|
||||
}],
|
||||
|
||||
|
@ -410,9 +373,6 @@ DOMInterfaces = {
|
|||
}],
|
||||
|
||||
'UIEvent': {
|
||||
'nativeType': 'AbstractEvent',
|
||||
'concreteType': 'UIEvent',
|
||||
'pointerType': '',
|
||||
},
|
||||
|
||||
'ValidityState': {
|
||||
|
@ -592,7 +552,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None):
|
|||
# FIXME: This should be renamed: https://github.com/mozilla/servo/issues/1625
|
||||
def addHTMLElement(element, concrete=None, needsAbstract=[]):
|
||||
DOMInterfaces[element] = {
|
||||
'nativeType': 'AbstractNode',
|
||||
'nativeType': 'JS<%s>' % element,
|
||||
'pointerType': '',
|
||||
'concreteType': concrete if concrete else element,
|
||||
'customTrace': 'trace',
|
||||
|
|
|
@ -102,7 +102,8 @@ class CastableObjectUnwrapper():
|
|||
"source" : source,
|
||||
"target" : target,
|
||||
"codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define(),
|
||||
"unwrapped_val" : "Some(val)" if isOptional else "val" }
|
||||
"unwrapped_val" : "Some(val)" if isOptional else "val",
|
||||
"unwrapFn": "unwrap_jsmanaged" if 'JS' in descriptor.nativeType else "unwrap_object"}
|
||||
if descriptor.hasXPConnectImpls:
|
||||
# We don't use xpc_qsUnwrapThis because it will always throw on
|
||||
# unwrap failure, whereas we want to control whether we throw or
|
||||
|
@ -123,7 +124,7 @@ class CastableObjectUnwrapper():
|
|||
|
||||
def __str__(self):
|
||||
return string.Template(
|
||||
"""match unwrap_object(${source}, ${prototype}, ${depth}) {
|
||||
"""match ${unwrapFn}(${source}, ${prototype}, ${depth}) {
|
||||
Ok(val) => ${target} = ${unwrapped_val},
|
||||
Err(()) => {
|
||||
${codeOnFailure}
|
||||
|
@ -406,8 +407,7 @@ class FakeCastableDescriptor():
|
|||
def __init__(self, descriptor):
|
||||
self.castable = True
|
||||
self.workers = descriptor.workers
|
||||
self.nativeType = descriptor.nativeType
|
||||
self.pointerType = descriptor.pointerType
|
||||
self.nativeType = "*Box<%s>" % descriptor.concreteType
|
||||
self.name = descriptor.name
|
||||
self.hasXPConnectImpls = descriptor.hasXPConnectImpls
|
||||
class FakeInterface:
|
||||
|
@ -934,8 +934,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
forceOwningType = (descriptor.interface.isCallback() and
|
||||
not descriptor.workers) or isMember
|
||||
|
||||
typeName = descriptor.nativeType
|
||||
typePtr = descriptor.pointerType + typeName
|
||||
typePtr = descriptor.nativeType
|
||||
|
||||
# Compute a few things:
|
||||
# - declType is the type we want to return as the first element of our
|
||||
|
@ -1730,9 +1729,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
|||
returnType.unroll().inner.identifier.name)
|
||||
result = CGGeneric(descriptor.nativeType)
|
||||
if returnType.nullable():
|
||||
result = CGWrapper(result, pre=("Option<" + descriptor.pointerType), post=">")
|
||||
else:
|
||||
result = CGWrapper(result, pre=descriptor.pointerType)
|
||||
result = CGWrapper(result, pre="Option<", post=">")
|
||||
return result, False
|
||||
if returnType.isCallback():
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
|
@ -2497,33 +2494,40 @@ class CGAbstractMethod(CGThing):
|
|||
def definition_body(self):
|
||||
assert(False) # Override me!
|
||||
|
||||
def DOMObjectPointerType(descriptor):
|
||||
return "~"
|
||||
|
||||
def DOMObjectPointerArg(descriptor):
|
||||
return DOMObjectPointerType(descriptor) + descriptor.concreteType
|
||||
|
||||
def CreateBindingJSObject(descriptor, parent=None):
|
||||
create = " let raw: *mut %s = &mut *aObject;\n" % descriptor.concreteType;
|
||||
if descriptor.proxy:
|
||||
assert not descriptor.createGlobal
|
||||
handler = """
|
||||
let page = page_from_context(aCx);
|
||||
let handler = (*page).js_info.get_ref().dom_static.proxy_handlers.get(&(PrototypeList::id::%s as uint));
|
||||
""" % descriptor.name
|
||||
create = handler + """ let obj = NewProxyObject(aCx, *handler,
|
||||
ptr::to_unsafe_ptr(&RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void)),
|
||||
create += handler + """ let obj = NewProxyObject(aCx, *handler,
|
||||
ptr::to_unsafe_ptr(&RUST_PRIVATE_TO_JSVAL(squirrel_away_unique(aObject) as *libc::c_void)),
|
||||
proto, %s,
|
||||
ptr::null(), ptr::null());
|
||||
if obj.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
""" % parent
|
||||
""" % (parent)
|
||||
else:
|
||||
if descriptor.createGlobal:
|
||||
create = " let obj = CreateDOMGlobal(aCx, &Class.base);\n"
|
||||
create += " let obj = CreateDOMGlobal(aCx, &Class.base);\n"
|
||||
else:
|
||||
create = " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent
|
||||
create += " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent
|
||||
create += """ if obj.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32,
|
||||
RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void));
|
||||
RUST_PRIVATE_TO_JSVAL(squirrel_away_unique(aObject) as *libc::c_void));
|
||||
"""
|
||||
return create
|
||||
|
||||
|
@ -2531,7 +2535,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
def __init__(self, descriptor):
|
||||
assert descriptor.interface.hasInterfacePrototypeObject()
|
||||
args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aScope'),
|
||||
Argument('@mut ' + descriptor.concreteType, 'aObject')]
|
||||
Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap_', '*JSObject', args)
|
||||
|
||||
def definition_body(self):
|
||||
|
@ -2548,20 +2552,20 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
if proto.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
%s
|
||||
|
||||
//NS_ADDREF(aObject);
|
||||
(*raw).mut_reflector().set_jsobject(obj);
|
||||
|
||||
aObject.mut_reflector().set_jsobject(obj);
|
||||
|
||||
return obj;""" % (CreateBindingJSObject(self.descriptor, "aScope"))
|
||||
return obj;""" % CreateBindingJSObject(self.descriptor, "aScope")
|
||||
else:
|
||||
return """
|
||||
assert!(aScope.is_null());
|
||||
|
||||
%s
|
||||
let proto = GetProtoObject(aCx, obj, obj);
|
||||
JS_SetPrototype(aCx, obj, proto);
|
||||
aObject.mut_reflector().set_jsobject(obj);
|
||||
(*raw).mut_reflector().set_jsobject(obj);
|
||||
return obj;""" % CreateBindingJSObject(self.descriptor)
|
||||
|
||||
class CGWrapMethod(CGAbstractMethod):
|
||||
|
@ -2569,7 +2573,7 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
# XXX can we wrap if we don't have an interface prototype object?
|
||||
assert descriptor.interface.hasInterfacePrototypeObject()
|
||||
args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aScope'),
|
||||
Argument('@mut ' + descriptor.concreteType, 'aObject')]
|
||||
Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', '*JSObject', args, inline=True, pub=True)
|
||||
|
||||
def definition_body(self):
|
||||
|
@ -2961,7 +2965,11 @@ class CGCallGenerator(CGThing):
|
|||
if a.type.isObject() and not a.type.nullable() and not a.optional:
|
||||
name = "(JSObject&)" + name
|
||||
#XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer
|
||||
if a.type.isDictionary():
|
||||
if a.type.isGeckoInterface():
|
||||
argDescriptor = descriptorProvider.getDescriptor(a.type.name)
|
||||
if not (a.type.nullable() or a.optional):
|
||||
name = "&mut " + name
|
||||
elif a.type.isDictionary():
|
||||
name = "&" + name
|
||||
args.append(CGGeneric(name))
|
||||
|
||||
|
@ -3288,8 +3296,8 @@ class CGSpecializedMethod(CGAbstractExternMethod):
|
|||
argsPre = []
|
||||
if name in self.descriptor.needsAbstract:
|
||||
abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType)
|
||||
extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['abstract_this']
|
||||
extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['&mut abstract_this']
|
||||
return CGWrapper(CGMethodCall(argsPre, nativeName, self.method.isStatic(),
|
||||
self.descriptor, self.method),
|
||||
pre=extraPre +
|
||||
|
@ -3317,8 +3325,10 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
|||
|
||||
def generate_code(self):
|
||||
return CGIndenter(CGGeneric(
|
||||
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, &*vp));\n"
|
||||
"return CallJitPropertyOp(info, cx, obj, this as *libc::c_void, &*vp);"))
|
||||
"return with_gc_disabled(cx, || {\n"
|
||||
" let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, &*vp));\n"
|
||||
" CallJitPropertyOp(info, cx, obj, this as *libc::c_void, &*vp)\n"
|
||||
"});\n"))
|
||||
|
||||
class CGSpecializedGetter(CGAbstractExternMethod):
|
||||
"""
|
||||
|
@ -3348,8 +3358,8 @@ class CGSpecializedGetter(CGAbstractExternMethod):
|
|||
getter=True))
|
||||
if name in self.descriptor.needsAbstract:
|
||||
abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType)
|
||||
extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['abstract_this']
|
||||
extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['&mut abstract_this']
|
||||
if resultOutParam or self.attr.type.nullable() or not infallible:
|
||||
nativeName = "Get" + nativeName
|
||||
return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName,
|
||||
|
@ -3381,7 +3391,10 @@ class CGGenericSetter(CGAbstractBindingMethod):
|
|||
"let undef = JSVAL_VOID;\n"
|
||||
"let argv: *JSVal = if argc != 0 { JS_ARGV(cx, cast::transmute(vp)) } else { &undef as *JSVal };\n"
|
||||
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, cast::transmute(vp)));\n"
|
||||
"if CallJitPropertyOp(info, cx, obj, this as *libc::c_void, argv) == 0 {"
|
||||
"let ok = with_gc_disabled(cx, || {\n"
|
||||
" CallJitPropertyOp(info, cx, obj, this as *libc::c_void, argv)\n"
|
||||
"});\n"
|
||||
"if ok == 0 {\n"
|
||||
" return 0;\n"
|
||||
"}\n"
|
||||
"*vp = JSVAL_VOID;\n"
|
||||
|
@ -3408,8 +3421,8 @@ class CGSpecializedSetter(CGAbstractExternMethod):
|
|||
extraPre = ''
|
||||
if name in self.descriptor.needsAbstract:
|
||||
abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType)
|
||||
extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['abstract_this']
|
||||
extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName
|
||||
argsPre = ['&mut abstract_this']
|
||||
return CGWrapper(CGIndenter(CGSetterCall(argsPre, self.attr.type, nativeName,
|
||||
self.descriptor, self.attr)),
|
||||
pre=extraPre +
|
||||
|
@ -4482,9 +4495,9 @@ def finalizeHook(descriptor, hookName, context):
|
|||
else:
|
||||
assert descriptor.nativeIsISupports
|
||||
release = """let val = JS_GetReservedSlot(obj, dom_object_slot(obj));
|
||||
let _: @mut %s = cast::transmute(RUST_JSVAL_TO_PRIVATE(val));
|
||||
let _: %s %s = cast::transmute(RUST_JSVAL_TO_PRIVATE(val));
|
||||
debug!("%s finalize: {:p}", this);
|
||||
""" % (descriptor.concreteType, descriptor.concreteType)
|
||||
""" % (DOMObjectPointerType(descriptor), descriptor.concreteType, descriptor.concreteType)
|
||||
#return clearWrapper + release
|
||||
return release
|
||||
|
||||
|
@ -4530,10 +4543,10 @@ class CGClassConstructHook(CGAbstractExternMethod):
|
|||
// or through unwrapping a slot or something). We'll punt and get the Window
|
||||
// from the context for now.
|
||||
let page = page_from_context(cx);
|
||||
let global = (*page).frame.get_ref().window;
|
||||
let global = (*page).frame.get_ref().window.clone();
|
||||
let obj = global.reflector().get_jsobject();
|
||||
"""
|
||||
preArgs = ["global"]
|
||||
preArgs = ["&global"]
|
||||
|
||||
name = self._ctor.identifier.name
|
||||
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
|
||||
|
@ -5151,6 +5164,7 @@ class CGBindingRoot(CGThing):
|
|||
'js::jsfriendapi::bindgen::*',
|
||||
'js::glue::*',
|
||||
'dom::types::*',
|
||||
'dom::bindings::js::JS',
|
||||
'dom::bindings::utils::*',
|
||||
'dom::bindings::callback::*',
|
||||
'dom::bindings::conversions::*',
|
||||
|
@ -5158,10 +5172,6 @@ class CGBindingRoot(CGThing):
|
|||
'script_task::{JSPageInfo, page_from_context}',
|
||||
'dom::bindings::proxyhandler',
|
||||
'dom::bindings::proxyhandler::*',
|
||||
'dom::document::AbstractDocument',
|
||||
'dom::node::AbstractNode',
|
||||
'dom::eventtarget::AbstractEventTarget',
|
||||
'dom::event::AbstractEvent',
|
||||
'servo_util::str::DOMString',
|
||||
'servo_util::vec::zip_copies',
|
||||
'std::cast',
|
||||
|
@ -5427,9 +5437,9 @@ class CGNativeMember(ClassMethod):
|
|||
else:
|
||||
typeDecl = "NonNull<%s>"
|
||||
else:
|
||||
typeDecl = "%s%s"
|
||||
typeDecl = "%s"
|
||||
descriptor = self.descriptorProvider.getDescriptor(iface.identifier.name)
|
||||
return (typeDecl % (descriptor.pointerType, descriptor.nativeType),
|
||||
return (typeDecl % descriptor.nativeType,
|
||||
False, False)
|
||||
|
||||
if type.isSpiderMonkeyInterface():
|
||||
|
@ -5560,7 +5570,7 @@ class CGCallback(CGClass):
|
|||
bases=[ClassBase(baseName)],
|
||||
constructors=self.getConstructors(),
|
||||
methods=realMethods+getters+setters,
|
||||
decorators="#[deriving(Eq,Clone)]")
|
||||
decorators="#[deriving(Eq,Clone,Encodable)]")
|
||||
|
||||
def getConstructors(self):
|
||||
return [ClassConstructor(
|
||||
|
@ -5591,20 +5601,19 @@ class CGCallback(CGClass):
|
|||
args.append(Argument("ExceptionHandling", "aExceptionHandling",
|
||||
"eReportExceptions"))
|
||||
|
||||
# Ensure the first argument is mutable
|
||||
args[0] = Argument(args[0].argType, args[0].name, args[0].default, mutable=True)
|
||||
args[0] = Argument('&' + args[0].argType, args[0].name, args[0].default)
|
||||
method.args[2] = args[0]
|
||||
|
||||
# And now insert our template argument.
|
||||
argsWithoutThis = list(args)
|
||||
args.insert(0, Argument("@mut T", "thisObj"))
|
||||
args.insert(0, Argument("~T", "thisObj"))
|
||||
|
||||
# And the self argument
|
||||
method.args.insert(0, Argument(None, "&self"))
|
||||
args.insert(0, Argument(None, "&self"))
|
||||
argsWithoutThis.insert(0, Argument(None, "&self"))
|
||||
|
||||
setupCall = ("let s = CallSetup::new(cx_for_dom_object(&mut ${cxProvider}), aExceptionHandling);\n"
|
||||
setupCall = ("let s = CallSetup::new(cx_for_dom_object(${cxProvider}), aExceptionHandling);\n"
|
||||
"if s.GetContext().is_null() {\n"
|
||||
" return${errorReturn};\n"
|
||||
"}\n")
|
||||
|
@ -5619,7 +5628,7 @@ class CGCallback(CGClass):
|
|||
"errorReturn" : method.getDefaultRetval(),
|
||||
"callArgs" : ", ".join(argnamesWithThis),
|
||||
"methodName": 'self.' + method.name,
|
||||
"cxProvider": '*thisObj'
|
||||
"cxProvider": 'thisObj'
|
||||
})
|
||||
bodyWithoutThis = string.Template(
|
||||
setupCall +
|
||||
|
@ -5954,8 +5963,14 @@ class CallbackMethod(CallbackMember):
|
|||
replacements["argv"] = "nullptr"
|
||||
replacements["argc"] = "0"
|
||||
return string.Template("${getCallable}"
|
||||
"if unsafe { JS_CallFunctionValue(cx, ${thisObj}, callable,\n"
|
||||
" ${argc}, ${argv}, &rval) == 0 } {\n"
|
||||
"let ok = unsafe {\n"
|
||||
" //JS_AllowGC(cx); // It's unsafe to enable GC at arbitrary points during Rust execution; leave it disabled\n"
|
||||
" let ok = JS_CallFunctionValue(cx, ${thisObj}, callable,\n"
|
||||
" ${argc}, ${argv}, &rval);\n"
|
||||
" //JS_InhibitGC(cx);\n"
|
||||
" ok\n"
|
||||
"};\n"
|
||||
"if ok == 0 {\n"
|
||||
" return${errorReturn};\n"
|
||||
"}\n").substitute(replacements)
|
||||
|
||||
|
@ -6176,3 +6191,66 @@ class GlobalGenRoots():
|
|||
curr = CGList([CGGeneric(declare="pub mod %sBinding;\n" % name) for name in descriptors])
|
||||
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
return curr
|
||||
|
||||
@staticmethod
|
||||
def InheritTypes(config):
|
||||
|
||||
descriptors = config.getDescriptors(register=True, hasInterfaceObject=True)
|
||||
allprotos = [CGGeneric(declare="#[allow(unused_imports)];\n"),
|
||||
CGGeneric(declare="use dom::types::*;\n"),
|
||||
CGGeneric(declare="use dom::bindings::js::JS;\n"),
|
||||
CGGeneric(declare="use dom::bindings::utils::Traceable;\n"),
|
||||
CGGeneric(declare="use extra::serialize::{Encodable, Encoder};\n"),
|
||||
CGGeneric(declare="use js::jsapi::JSTracer;\n\n")]
|
||||
for descriptor in descriptors:
|
||||
name = descriptor.name
|
||||
protos = [CGGeneric(declare='pub trait %s {}\n' % (name + 'Base'))]
|
||||
for proto in descriptor.prototypeChain:
|
||||
protos += [CGGeneric(declare='impl %s for %s {}\n' % (proto + 'Base',
|
||||
descriptor.concreteType))]
|
||||
derived = [CGGeneric(declare='pub trait %s { fn %s(&self) -> bool; }\n' %
|
||||
(name + 'Derived', 'is_' + name.lower()))]
|
||||
for protoName in descriptor.prototypeChain[1:-1]:
|
||||
protoDescriptor = config.getDescriptor(protoName, False)
|
||||
delegate = string.Template('''impl ${selfName} for ${baseName} {
|
||||
fn ${fname}(&self) -> bool {
|
||||
self.${parentName}.${fname}()
|
||||
}
|
||||
}
|
||||
''').substitute({'fname': 'is_' + name.lower(),
|
||||
'selfName': name + 'Derived',
|
||||
'baseName': protoDescriptor.concreteType,
|
||||
'parentName': protoDescriptor.prototypeChain[-2].lower()})
|
||||
derived += [CGGeneric(declare=delegate)]
|
||||
derived += [CGGeneric(declare='\n')]
|
||||
|
||||
cast = [CGGeneric(declare=string.Template('''pub trait ${castTraitName} {
|
||||
fn from<T: ${fromBound}>(derived: &JS<T>) -> JS<Self> {
|
||||
unsafe { derived.clone().transmute() }
|
||||
}
|
||||
|
||||
fn to<T: ${toBound}>(base: &JS<T>) -> JS<Self> {
|
||||
assert!(base.get().${checkFn}());
|
||||
unsafe { base.clone().transmute() }
|
||||
}
|
||||
}
|
||||
''').substitute({'checkFn': 'is_' + name.lower(),
|
||||
'castTraitName': name + 'Cast',
|
||||
'fromBound': name + 'Base',
|
||||
'toBound': name + 'Derived'})),
|
||||
CGGeneric(declare="impl %s for %s {}\n\n" % (name + 'Cast', name))]
|
||||
|
||||
trace = [CGGeneric(declare=string.Template('''impl Traceable for ${name} {
|
||||
fn trace(&self, tracer: *mut JSTracer) {
|
||||
unsafe {
|
||||
self.encode(&mut *tracer);
|
||||
}
|
||||
}
|
||||
}
|
||||
''').substitute({'name': name}))]
|
||||
|
||||
allprotos += protos + derived + cast + trace
|
||||
|
||||
curr = CGList(allprotos)
|
||||
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
return curr
|
||||
|
|
|
@ -158,10 +158,9 @@ class Descriptor(DescriptorProvider):
|
|||
if self.workers:
|
||||
nativeTypeDefault = "workers::" + ifaceName
|
||||
else:
|
||||
nativeTypeDefault = ifaceName
|
||||
nativeTypeDefault = 'JS<%s>' % ifaceName
|
||||
|
||||
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
||||
self.pointerType = desc.get('pointerType', '@mut ')
|
||||
self.concreteType = desc.get('concreteType', ifaceName)
|
||||
self.needsAbstract = desc.get('needsAbstract', [])
|
||||
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
||||
|
@ -253,7 +252,7 @@ class Descriptor(DescriptorProvider):
|
|||
self.prefable = desc.get('prefable', False)
|
||||
|
||||
self.nativeIsISupports = not self.workers
|
||||
self.customTrace = desc.get('customTrace', self.workers)
|
||||
self.customTrace = desc.get('customTrace', self.workers) or 'trace'
|
||||
self.customFinalize = desc.get('customFinalize', self.workers)
|
||||
self.wrapperCache = self.workers or desc.get('wrapperCache', True)
|
||||
|
||||
|
|
|
@ -83,6 +83,9 @@ def main():
|
|||
# Generate the type list.
|
||||
generate_file(config, 'InterfaceTypes', 'declare+define')
|
||||
|
||||
# Generate the type list.
|
||||
generate_file(config, 'InheritTypes', 'declare+define')
|
||||
|
||||
# Generate the module declarations.
|
||||
generate_file(config, 'BindingDeclarations', 'declare+define')
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::types::*;
|
||||
use dom::bindings::utils::{Reflectable, Reflector, Traceable};
|
||||
|
||||
use js::jsapi::JSTracer;
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
|
||||
// generate_cacheable_wrapper
|
||||
macro_rules! generate_cacheable_wrapper(
|
||||
|
@ -58,277 +56,149 @@ macro_rules! generate_cacheable_wrapper_base(
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
// generate_traceable
|
||||
macro_rules! generate_traceable(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, element)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_characterdata(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, characterdata)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_htmlelement(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, htmlelement)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_htmlmediaelement(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, htmlmediaelement)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_htmltablecellelement(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, htmltablecellelement)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_node(
|
||||
($name: path) => (
|
||||
generate_traceable_base!($name, node)
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! generate_traceable_base(
|
||||
($name: path, $parent: ident) => (
|
||||
impl Traceable for $name {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.$parent.trace(trc);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
generate_cacheable_wrapper_characterdata!(Comment, CommentBinding::Wrap)
|
||||
generate_traceable_characterdata!(Comment)
|
||||
|
||||
generate_cacheable_wrapper_node!(DocumentFragment, DocumentFragmentBinding::Wrap)
|
||||
generate_traceable_node!(DocumentFragment)
|
||||
|
||||
generate_cacheable_wrapper_node!(DocumentType, DocumentTypeBinding::Wrap)
|
||||
generate_traceable_node!(DocumentType)
|
||||
|
||||
generate_cacheable_wrapper_characterdata!(Text, TextBinding::Wrap)
|
||||
generate_traceable_characterdata!(Text)
|
||||
|
||||
generate_cacheable_wrapper_characterdata!(ProcessingInstruction, ProcessingInstruction::Wrap)
|
||||
generate_traceable_characterdata!(ProcessingInstruction)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLHeadElement, HTMLHeadElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLHeadElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLAnchorElement, HTMLAnchorElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLAnchorElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLAppletElement, HTMLAppletElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLAppletElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLAreaElement, HTMLAreaElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLAreaElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlmediaelement!(HTMLAudioElement, HTMLAudioElementBinding::Wrap)
|
||||
generate_traceable_htmlmediaelement!(HTMLAudioElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLBaseElement, HTMLBaseElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLBaseElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLBodyElement, HTMLBodyElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLBodyElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLButtonElement, HTMLButtonElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLButtonElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLCanvasElement, HTMLCanvasElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLCanvasElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLDataListElement, HTMLDataListElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLDataListElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLDListElement, HTMLDListElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLDListElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLFormElement, HTMLFormElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLFormElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLFrameElement, HTMLFrameElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLFrameElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLFrameSetElement, HTMLFrameSetElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLFrameSetElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLBRElement, HTMLBRElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLBRElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLHRElement, HTMLHRElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLHRElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLHtmlElement, HTMLHtmlElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLHtmlElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLDataElement, HTMLDataElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLDataElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLDirectoryElement, HTMLDirectoryElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLDirectoryElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLDivElement, HTMLDivElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLDivElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLEmbedElement, HTMLEmbedElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLEmbedElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLFieldSetElement, HTMLFieldSetElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLFieldSetElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLFontElement, HTMLFontElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLFontElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLHeadingElement, HTMLHeadingElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLHeadingElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLIFrameElement, HTMLIFrameElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLIFrameElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLImageElement, HTMLImageElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLImageElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLInputElement, HTMLInputElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLInputElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLLabelElement, HTMLLabelElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLLabelElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLLegendElement, HTMLLegendElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLLegendElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLLIElement, HTMLLIElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLLIElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLLinkElement, HTMLLinkElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLLinkElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLMainElement, HTMLMainElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLMainElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLMapElement, HTMLMapElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLMapElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLMediaElement, HTMLMediaElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLMediaElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLMetaElement, HTMLMetaElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLMetaElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLMeterElement, HTMLMeterElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLMeterElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLModElement, HTMLModElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLModElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLObjectElement, HTMLObjectElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLObjectElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLOListElement, HTMLOListElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLOListElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLOptGroupElement, HTMLOptGroupElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLOptGroupElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLOptionElement, HTMLOptionElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLOptionElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLOutputElement, HTMLOutputElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLOutputElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLParagraphElement, HTMLParagraphElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLParagraphElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLParamElement, HTMLParamElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLParamElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLPreElement, HTMLPreElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLPreElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLProgressElement, HTMLProgressElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLProgressElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLQuoteElement, HTMLQuoteElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLQuoteElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLScriptElement, HTMLScriptElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLScriptElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLSelectElement, HTMLSelectElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLSelectElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLSourceElement, HTMLSourceElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLSourceElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLSpanElement, HTMLSpanElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLSpanElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLStyleElement, HTMLStyleElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLStyleElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableElement, HTMLTableElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableCaptionElement, HTMLTableCaptionElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableCaptionElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableCellElement, HTMLTableCellElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableCellElement)
|
||||
|
||||
generate_cacheable_wrapper_htmltablecellelement!(HTMLTableDataCellElement, HTMLTableDataCellElementBinding::Wrap)
|
||||
generate_traceable_htmltablecellelement!(HTMLTableDataCellElement)
|
||||
|
||||
generate_cacheable_wrapper_htmltablecellelement!(HTMLTableHeaderCellElement, HTMLTableHeaderCellElementBinding::Wrap)
|
||||
generate_traceable_htmltablecellelement!(HTMLTableHeaderCellElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableColElement, HTMLTableColElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableColElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableRowElement, HTMLTableRowElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableRowElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTableSectionElement, HTMLTableSectionElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTableSectionElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTemplateElement, HTMLTemplateElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTemplateElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTextAreaElement, HTMLTextAreaElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTextAreaElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTitleElement, HTMLTitleElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTitleElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTimeElement, HTMLTimeElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTimeElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLTrackElement, HTMLTrackElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLTrackElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLUListElement, HTMLUListElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLUListElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlelement!(HTMLUnknownElement, HTMLUnknownElementBinding::Wrap)
|
||||
generate_traceable_htmlelement!(HTMLUnknownElement)
|
||||
|
||||
generate_cacheable_wrapper_htmlmediaelement!(HTMLVideoElement, HTMLVideoElementBinding::Wrap)
|
||||
generate_traceable_htmlmediaelement!(HTMLVideoElement)
|
||||
|
||||
generate_cacheable_wrapper!(HTMLElement, HTMLElementBinding::Wrap)
|
||||
generate_traceable!(HTMLElement)
|
||||
|
||||
generate_traceable_node!(Element)
|
||||
|
||||
generate_traceable_node!(CharacterData)
|
||||
|
|
99
src/components/script/dom/bindings/js.rs
Normal file
99
src/components/script/dom/bindings/js.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::utils::{Reflector, Reflectable};
|
||||
use dom::window;
|
||||
use js::jsapi::{JSContext, JSObject};
|
||||
use layout_interface::TrustedNodeAddress;
|
||||
|
||||
use std::cast;
|
||||
use std::cell::RefCell;
|
||||
use std::unstable::raw::Box;
|
||||
|
||||
pub struct JS<T> {
|
||||
priv ptr: RefCell<*mut T>
|
||||
}
|
||||
|
||||
impl<T> Eq for JS<T> {
|
||||
fn eq(&self, other: &JS<T>) -> bool {
|
||||
self.ptr == other.ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl <T> Clone for JS<T> {
|
||||
fn clone(&self) -> JS<T> {
|
||||
JS {
|
||||
ptr: self.ptr.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflectable> JS<T> {
|
||||
pub fn new(mut obj: ~T,
|
||||
window: &window::Window,
|
||||
wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~T) -> *JSObject) -> JS<T> {
|
||||
let cx = window.get_cx();
|
||||
let scope = window.reflector().get_jsobject();
|
||||
let raw: *mut T = &mut *obj;
|
||||
if wrap_fn(cx, scope, obj).is_null() {
|
||||
fail!("Could not eagerly wrap object");
|
||||
}
|
||||
JS {
|
||||
ptr: RefCell::new(raw)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn from_raw(raw: *mut T) -> JS<T> {
|
||||
JS {
|
||||
ptr: RefCell::new(raw)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub unsafe fn from_box(box_: *mut Box<T>) -> JS<T> {
|
||||
let raw: *mut T = &mut (*box_).data;
|
||||
JS {
|
||||
ptr: RefCell::new(raw)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<T> {
|
||||
JS {
|
||||
ptr: RefCell::new(inner as *mut T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflectable> Reflectable for JS<T> {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.get().reflector()
|
||||
}
|
||||
|
||||
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
|
||||
self.get_mut().mut_reflector()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> JS<T> {
|
||||
pub fn get<'a>(&'a self) -> &'a T {
|
||||
let borrowed = self.ptr.borrow();
|
||||
unsafe {
|
||||
&(**borrowed.get())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut<'a>(&'a mut self) -> &'a mut T {
|
||||
let mut borrowed = self.ptr.borrow_mut();
|
||||
unsafe {
|
||||
&mut (**borrowed.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<From, To> JS<From> {
|
||||
//XXXjdm It would be lovely if this could be private.
|
||||
pub unsafe fn transmute(self) -> JS<To> {
|
||||
cast::transmute(self)
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::utils::{Reflectable, Reflector, Traceable, trace_reflector};
|
||||
use dom::types::*;
|
||||
use dom::node::AbstractNode;
|
||||
|
||||
use std::cast;
|
||||
use std::libc;
|
||||
use std::ptr;
|
||||
use js::jsapi::{JSTracer, JSTRACE_OBJECT, JS_CallTracer};
|
||||
|
||||
impl Reflectable for AbstractNode {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.node().reflector()
|
||||
}
|
||||
|
||||
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
|
||||
self.mut_node().mut_reflector()
|
||||
}
|
||||
}
|
||||
|
||||
impl Traceable for Node {
|
||||
fn trace(&self, tracer: *mut JSTracer) {
|
||||
fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode>, name: &str) {
|
||||
if node.is_none() {
|
||||
return;
|
||||
}
|
||||
debug!("tracing {:s}", name);
|
||||
let node = node.unwrap();
|
||||
let obj = node.reflector().get_jsobject();
|
||||
assert!(obj.is_not_null());
|
||||
unsafe {
|
||||
(*tracer).debugPrinter = ptr::null();
|
||||
(*tracer).debugPrintIndex = -1;
|
||||
name.to_c_str().with_ref(|name| {
|
||||
(*tracer).debugPrintArg = name as *libc::c_void;
|
||||
JS_CallTracer(cast::transmute(tracer), obj, JSTRACE_OBJECT as u32);
|
||||
});
|
||||
}
|
||||
}
|
||||
debug!("tracing {:p}?:", self.reflector().get_jsobject());
|
||||
trace_node(tracer, self.parent_node, "parent");
|
||||
trace_node(tracer, self.first_child, "first child");
|
||||
trace_node(tracer, self.last_child, "last child");
|
||||
trace_node(tracer, self.next_sibling, "next sibling");
|
||||
trace_node(tracer, self.prev_sibling, "prev sibling");
|
||||
let owner_doc = self.owner_doc();
|
||||
trace_reflector(tracer, "document", owner_doc.reflector());
|
||||
}
|
||||
}
|
28
src/components/script/dom/bindings/trace.rs
Normal file
28
src/components/script/dom/bindings/trace.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::js::JS;
|
||||
use dom::bindings::utils::{Reflectable, trace_reflector, Reflector};
|
||||
|
||||
use js::jsapi::JSTracer;
|
||||
|
||||
use std::cast;
|
||||
use extra::serialize::{Encodable, Encoder};
|
||||
|
||||
// IMPORTANT: We rely on the fact that we never attempt to encode DOM objects using
|
||||
// any encoder but JSTracer. Since we derive trace hooks automatically,
|
||||
// we are unfortunately required to use generic types everywhere and
|
||||
// unsafely cast to the concrete JSTracer we actually require.
|
||||
|
||||
impl<T: Reflectable+Encodable<S>, S: Encoder> Encodable<S> for JS<T> {
|
||||
fn encode(&self, s: &mut S) {
|
||||
let s: &mut JSTracer = unsafe { cast::transmute(s) };
|
||||
trace_reflector(s, "", self.reflector());
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Reflector {
|
||||
fn encode(&self, _s: &mut S) {
|
||||
}
|
||||
}
|
|
@ -4,11 +4,13 @@
|
|||
|
||||
use dom::bindings::codegen::PrototypeList;
|
||||
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
|
||||
use dom::bindings::js::JS;
|
||||
use dom::window;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
use std::libc::c_uint;
|
||||
use std::cast;
|
||||
use std::cmp::Eq;
|
||||
use std::hashmap::HashMap;
|
||||
use std::libc;
|
||||
use std::ptr;
|
||||
|
@ -32,7 +34,7 @@ use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer};
|
|||
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
|
||||
use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses};
|
||||
use js::jsapi::{JSString, JS_CallTracer, JSTRACE_OBJECT};
|
||||
use js::jsapi::{JS_IsExceptionPending};
|
||||
use js::jsapi::{JS_IsExceptionPending, JS_AllowGC, JS_InhibitGC};
|
||||
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
||||
use js::{JSPROP_ENUMERATE, JSVAL_NULL, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
|
||||
use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER};
|
||||
|
@ -174,6 +176,17 @@ pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_d
|
|||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_jsmanaged<T: Reflectable>(obj: *JSObject,
|
||||
proto_id: PrototypeList::id::ID,
|
||||
proto_depth: uint) -> Result<JS<T>, ()> {
|
||||
let result: Result<*mut Box<T>, ()> = unwrap_object(obj, proto_id, proto_depth);
|
||||
result.map(|unwrapped| {
|
||||
unsafe {
|
||||
JS::from_box(unwrapped)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<T, ()> {
|
||||
unsafe {
|
||||
let obj = RUST_JSVAL_TO_OBJECT(*val);
|
||||
|
@ -182,8 +195,11 @@ pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth
|
|||
}
|
||||
|
||||
pub unsafe fn squirrel_away<T>(x: @mut T) -> *Box<T> {
|
||||
let y: *Box<T> = cast::transmute(x);
|
||||
y
|
||||
cast::transmute(x)
|
||||
}
|
||||
|
||||
pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *Box<T> {
|
||||
cast::transmute(x)
|
||||
}
|
||||
|
||||
pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> DOMString {
|
||||
|
@ -557,10 +573,6 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
|
|||
}
|
||||
}
|
||||
|
||||
pub fn trace_option<T: Reflectable>(tracer: *mut JSTracer, description: &str, option: Option<@mut T>) {
|
||||
option.map(|some| trace_reflector(tracer, description, some.reflector()));
|
||||
}
|
||||
|
||||
pub fn initialize_global(global: *JSObject) {
|
||||
let protoArray = @mut ([0 as *JSObject, ..PrototypeList::id::_ID_Count as uint]);
|
||||
unsafe {
|
||||
|
@ -579,21 +591,17 @@ pub trait Reflectable {
|
|||
}
|
||||
|
||||
pub fn reflect_dom_object<T: Reflectable>
|
||||
(obj: @mut T,
|
||||
(obj: ~T,
|
||||
window: &window::Window,
|
||||
wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut T) -> *JSObject)
|
||||
-> @mut T {
|
||||
let cx = window.get_cx();
|
||||
let scope = window.reflector().get_jsobject();
|
||||
if wrap_fn(cx, scope, obj).is_null() {
|
||||
fail!("Could not eagerly wrap object");
|
||||
}
|
||||
assert!(obj.reflector().get_jsobject().is_not_null());
|
||||
obj
|
||||
wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~T) -> *JSObject)
|
||||
-> JS<T> {
|
||||
JS::new(obj, window, wrap_fn)
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub struct Reflector {
|
||||
object: *JSObject
|
||||
object: *JSObject,
|
||||
force_box_layout: @int,
|
||||
}
|
||||
|
||||
impl Reflector {
|
||||
|
@ -610,7 +618,8 @@ impl Reflector {
|
|||
|
||||
pub fn new() -> Reflector {
|
||||
Reflector {
|
||||
object: ptr::null()
|
||||
object: ptr::null(),
|
||||
force_box_layout: @1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -849,11 +858,11 @@ fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext {
|
|||
}
|
||||
|
||||
/// Returns the global object of the realm that the given DOM object was created in.
|
||||
pub fn global_object_for_dom_object<T: Reflectable>(obj: &mut T) -> *Box<window::Window> {
|
||||
pub fn global_object_for_dom_object<T: Reflectable>(obj: &T) -> *Box<window::Window> {
|
||||
global_object_for_js_object(obj.reflector().get_jsobject())
|
||||
}
|
||||
|
||||
pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext {
|
||||
pub fn cx_for_dom_object<T: Reflectable>(obj: &T) -> *JSContext {
|
||||
cx_for_dom_reflector(obj.reflector().get_jsobject())
|
||||
}
|
||||
|
||||
|
@ -870,6 +879,26 @@ pub fn throw_method_failed_with_details<T>(cx: *JSContext,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// Execute arbitrary code with the JS GC enabled, then disable it afterwards.
|
||||
pub fn with_gc_enabled<R>(cx: *JSContext, f: || -> R) -> R {
|
||||
unsafe {
|
||||
JS_AllowGC(cx);
|
||||
let rv = f();
|
||||
JS_InhibitGC(cx);
|
||||
rv
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute arbitrary code with the JS GC disabled, then enable it afterwards.
|
||||
pub fn with_gc_disabled<R>(cx: *JSContext, f: || -> R) -> R {
|
||||
unsafe {
|
||||
JS_InhibitGC(cx);
|
||||
let rv = f();
|
||||
JS_AllowGC(cx);
|
||||
rv
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
|
||||
/// for details.
|
||||
#[deriving(Eq)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue