mirror of
https://github.com/servo/servo.git
synced 2025-06-08 16:43:28 +00:00
Add support for NamedConstructor in webidls
This commit is contained in:
parent
3e90a60170
commit
012be81eab
2 changed files with 107 additions and 28 deletions
|
@ -2286,11 +2286,25 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||||
call = """\
|
call = """\
|
||||||
do_create_interface_objects(cx, receiver, parent_proto.handle(),
|
do_create_interface_objects(cx, receiver, parent_proto.handle(),
|
||||||
%s, %s,
|
%s, %s,
|
||||||
|
&named_constructors,
|
||||||
%s,
|
%s,
|
||||||
&sNativeProperties, rval);""" % (protoClass, constructor, domClass)
|
&sNativeProperties, rval);""" % (protoClass, constructor, domClass)
|
||||||
|
|
||||||
|
createArray = """\
|
||||||
|
let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [
|
||||||
|
""" % len(self.descriptor.interface.namedConstructors)
|
||||||
|
for ctor in self.descriptor.interface.namedConstructors:
|
||||||
|
constructHook = CONSTRUCT_HOOK_NAME + "_" + ctor.identifier.name;
|
||||||
|
constructArgs = methodLength(ctor)
|
||||||
|
constructor = '(%s as NonNullJSNative, "%s", %d)' % (
|
||||||
|
constructHook, ctor.identifier.name, constructArgs)
|
||||||
|
createArray += constructor
|
||||||
|
createArray += ","
|
||||||
|
createArray += "];"
|
||||||
|
|
||||||
return CGList([
|
return CGList([
|
||||||
CGGeneric(getParentProto),
|
CGGeneric(getParentProto),
|
||||||
|
CGGeneric(createArray),
|
||||||
CGGeneric(call % self.properties.variableNames())
|
CGGeneric(call % self.properties.variableNames())
|
||||||
], "\n")
|
], "\n")
|
||||||
|
|
||||||
|
@ -4422,6 +4436,30 @@ let args = CallArgs::from_vp(vp, argc);
|
||||||
self.descriptor, self._ctor)
|
self.descriptor, self._ctor)
|
||||||
return CGList([preamble, callGenerator])
|
return CGList([preamble, callGenerator])
|
||||||
|
|
||||||
|
class CGClassNameConstructHook(CGAbstractExternMethod):
|
||||||
|
"""
|
||||||
|
JS-visible named constructor for our objects
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor, ctor):
|
||||||
|
args = [Argument('*mut JSContext', 'cx'), Argument('u32', 'argc'), Argument('*mut JSVal', 'vp')]
|
||||||
|
self._ctor = ctor
|
||||||
|
CGAbstractExternMethod.__init__(self, descriptor,
|
||||||
|
CONSTRUCT_HOOK_NAME + "_" +
|
||||||
|
self._ctor.identifier.name,
|
||||||
|
'u8', args)
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
preamble = CGGeneric("""\
|
||||||
|
let global = global_object_for_js_object(JS_CALLEE(cx, vp).to_object());
|
||||||
|
let args = CallArgs::from_vp(vp, argc);
|
||||||
|
""")
|
||||||
|
name = self._ctor.identifier.name
|
||||||
|
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
|
||||||
|
callGenerator = CGMethodCall(["global.r()"], nativeName, True,
|
||||||
|
self.descriptor, self._ctor)
|
||||||
|
return CGList([preamble, callGenerator])
|
||||||
|
|
||||||
|
|
||||||
class CGClassFinalizeHook(CGAbstractClassHook):
|
class CGClassFinalizeHook(CGAbstractClassHook):
|
||||||
"""
|
"""
|
||||||
A hook for finalize, used to release our native object.
|
A hook for finalize, used to release our native object.
|
||||||
|
@ -4568,6 +4606,8 @@ class CGDescriptor(CGThing):
|
||||||
|
|
||||||
if descriptor.interface.hasInterfaceObject():
|
if descriptor.interface.hasInterfaceObject():
|
||||||
cgThings.append(CGClassConstructHook(descriptor))
|
cgThings.append(CGClassConstructHook(descriptor))
|
||||||
|
for ctor in descriptor.interface.namedConstructors:
|
||||||
|
cgThings.append(CGClassNameConstructHook(descriptor, ctor))
|
||||||
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
||||||
|
|
||||||
if not descriptor.interface.isCallback():
|
if not descriptor.interface.isCallback():
|
||||||
|
|
|
@ -205,6 +205,7 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
||||||
proto_proto: HandleObject,
|
proto_proto: HandleObject,
|
||||||
proto_class: Option<&'static JSClass>,
|
proto_class: Option<&'static JSClass>,
|
||||||
constructor: Option<(NonNullJSNative, &'static str, u32)>,
|
constructor: Option<(NonNullJSNative, &'static str, u32)>,
|
||||||
|
named_constructors: &[(NonNullJSNative, &'static str, u32)],
|
||||||
dom_class: *const DOMClass,
|
dom_class: *const DOMClass,
|
||||||
members: &'static NativeProperties,
|
members: &'static NativeProperties,
|
||||||
rval: MutableHandleObject) {
|
rval: MutableHandleObject) {
|
||||||
|
@ -226,6 +227,55 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
||||||
native, nargs, rval.handle(),
|
native, nargs, rval.handle(),
|
||||||
members, s.as_ptr())
|
members, s.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ctor in named_constructors.iter() {
|
||||||
|
let (cnative, cname, cnargs) = *ctor;
|
||||||
|
|
||||||
|
let cs = CString::new(cname).unwrap();
|
||||||
|
let constructor = RootedObject::new(cx, create_constructor(cx, cnative, cnargs, cs.as_ptr()));
|
||||||
|
assert!(!constructor.ptr.is_null());
|
||||||
|
unsafe {
|
||||||
|
assert!(JS_DefineProperty1(cx, constructor.handle(), "prototype".as_ptr() as *const i8,
|
||||||
|
rval.handle(),
|
||||||
|
JSPROP_PERMANENT | JSPROP_READONLY,
|
||||||
|
None, None) != 0);
|
||||||
|
}
|
||||||
|
define_constructor(cx, receiver, cs.as_ptr(), constructor.handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_constructor(cx: *mut JSContext,
|
||||||
|
constructor_native: NonNullJSNative,
|
||||||
|
ctor_nargs: u32,
|
||||||
|
name: *const libc::c_char) -> *mut JSObject {
|
||||||
|
unsafe {
|
||||||
|
let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
|
||||||
|
JSFUN_CONSTRUCTOR, name);
|
||||||
|
assert!(!fun.is_null());
|
||||||
|
|
||||||
|
let constructor = JS_GetFunctionObject(fun);
|
||||||
|
assert!(!constructor.is_null());
|
||||||
|
|
||||||
|
constructor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_constructor(cx: *mut JSContext,
|
||||||
|
receiver: HandleObject,
|
||||||
|
name: *const libc::c_char,
|
||||||
|
constructor: HandleObject) {
|
||||||
|
unsafe {
|
||||||
|
let mut already_defined = 0;
|
||||||
|
assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
|
||||||
|
|
||||||
|
if already_defined == 0 {
|
||||||
|
assert!(JS_DefineProperty1(cx, receiver, name,
|
||||||
|
constructor,
|
||||||
|
0, None, None) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the *interface object*.
|
/// Creates the *interface object*.
|
||||||
|
@ -236,12 +286,7 @@ fn create_interface_object(cx: *mut JSContext,
|
||||||
ctor_nargs: u32, proto: HandleObject,
|
ctor_nargs: u32, proto: HandleObject,
|
||||||
members: &'static NativeProperties,
|
members: &'static NativeProperties,
|
||||||
name: *const libc::c_char) {
|
name: *const libc::c_char) {
|
||||||
unsafe {
|
let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name));
|
||||||
let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
|
|
||||||
JSFUN_CONSTRUCTOR, name);
|
|
||||||
assert!(!fun.is_null());
|
|
||||||
|
|
||||||
let constructor = RootedObject::new(cx, JS_GetFunctionObject(fun));
|
|
||||||
assert!(!constructor.ptr.is_null());
|
assert!(!constructor.ptr.is_null());
|
||||||
|
|
||||||
if let Some(static_methods) = members.static_methods {
|
if let Some(static_methods) = members.static_methods {
|
||||||
|
@ -256,19 +301,13 @@ fn create_interface_object(cx: *mut JSContext,
|
||||||
define_constants(cx, constructor.handle(), constants);
|
define_constants(cx, constructor.handle(), constants);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
if !proto.get().is_null() {
|
if !proto.get().is_null() {
|
||||||
assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto) != 0);
|
assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut already_defined = 0;
|
|
||||||
assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
|
|
||||||
|
|
||||||
if already_defined == 0 {
|
|
||||||
assert!(JS_DefineProperty1(cx, receiver, name,
|
|
||||||
constructor.handle(),
|
|
||||||
0, None, None) != 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define_constructor(cx, receiver, name, constructor.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines constants on `obj`.
|
/// Defines constants on `obj`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue