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 = """\
|
||||
do_create_interface_objects(cx, receiver, parent_proto.handle(),
|
||||
%s, %s,
|
||||
&named_constructors,
|
||||
%s,
|
||||
&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([
|
||||
CGGeneric(getParentProto),
|
||||
CGGeneric(createArray),
|
||||
CGGeneric(call % self.properties.variableNames())
|
||||
], "\n")
|
||||
|
||||
|
@ -4422,6 +4436,30 @@ let args = CallArgs::from_vp(vp, argc);
|
|||
self.descriptor, self._ctor)
|
||||
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):
|
||||
"""
|
||||
A hook for finalize, used to release our native object.
|
||||
|
@ -4568,6 +4606,8 @@ class CGDescriptor(CGThing):
|
|||
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
cgThings.append(CGClassConstructHook(descriptor))
|
||||
for ctor in descriptor.interface.namedConstructors:
|
||||
cgThings.append(CGClassNameConstructHook(descriptor, ctor))
|
||||
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
||||
|
||||
if not descriptor.interface.isCallback():
|
||||
|
|
|
@ -205,6 +205,7 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
|||
proto_proto: HandleObject,
|
||||
proto_class: Option<&'static JSClass>,
|
||||
constructor: Option<(NonNullJSNative, &'static str, u32)>,
|
||||
named_constructors: &[(NonNullJSNative, &'static str, u32)],
|
||||
dom_class: *const DOMClass,
|
||||
members: &'static NativeProperties,
|
||||
rval: MutableHandleObject) {
|
||||
|
@ -226,6 +227,55 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
|||
native, nargs, rval.handle(),
|
||||
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*.
|
||||
|
@ -236,39 +286,28 @@ fn create_interface_object(cx: *mut JSContext,
|
|||
ctor_nargs: u32, proto: HandleObject,
|
||||
members: &'static NativeProperties,
|
||||
name: *const libc::c_char) {
|
||||
let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name));
|
||||
assert!(!constructor.ptr.is_null());
|
||||
|
||||
if let Some(static_methods) = members.static_methods {
|
||||
define_methods(cx, constructor.handle(), static_methods);
|
||||
}
|
||||
|
||||
if let Some(static_properties) = members.static_attrs {
|
||||
define_properties(cx, constructor.handle(), static_properties);
|
||||
}
|
||||
|
||||
if let Some(constants) = members.consts {
|
||||
define_constants(cx, constructor.handle(), constants);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
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());
|
||||
|
||||
if let Some(static_methods) = members.static_methods {
|
||||
define_methods(cx, constructor.handle(), static_methods);
|
||||
}
|
||||
|
||||
if let Some(static_properties) = members.static_attrs {
|
||||
define_properties(cx, constructor.handle(), static_properties);
|
||||
}
|
||||
|
||||
if let Some(constants) = members.consts {
|
||||
define_constants(cx, constructor.handle(), constants);
|
||||
}
|
||||
|
||||
if !proto.get().is_null() {
|
||||
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`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue