aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py203
-rw-r--r--components/script/dom/bindings/interface.rs155
-rw-r--r--components/script/dom/bindings/mod.rs1
-rw-r--r--components/script/dom/bindings/utils.rs202
4 files changed, 261 insertions, 300 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 8ff336566d6..067e5b76386 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -2355,30 +2355,6 @@ class PropertyArrays():
return define
-class CGNativeProperties(CGThing):
- def __init__(self, descriptor, properties):
- CGThing.__init__(self)
- self.properties = properties
-
- def define(self):
- def getField(array):
- propertyArray = getattr(self.properties, array)
- if propertyArray.length() > 0:
- value = "Some(%s)" % propertyArray.variableName()
- else:
- value = "None"
-
- return CGGeneric(string.Template('${name}: ${value},').substitute({
- 'name': array,
- 'value': value,
- }))
-
- nativeProps = CGList([getField(array) for array in self.properties.arrayNames()], '\n')
- return CGWrapper(CGIndenter(nativeProps),
- pre="static sNativeProperties: NativeProperties = NativeProperties {\n",
- post="\n};\n").define()
-
-
class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
"""
Generate the CreateInterfaceObjects method for an interface descriptor.
@@ -2389,59 +2365,85 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'global'),
Argument('HandleObject', 'receiver'),
Argument('MutableHandleObject', 'rval')]
- CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
+ CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args,
+ unsafe=True)
self.properties = properties
def definition_body(self):
+ name = self.descriptor.interface.identifier.name
+ if self.descriptor.interface.isCallback():
+ assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
+ return CGGeneric("""\
+create_callback_interface_object(cx, receiver, throwing_constructor, 0, sConstants, %s);""" % str_to_const_array(name))
+
protoChain = self.descriptor.prototypeChain
if len(protoChain) == 1:
- self.unsafe = True
- getParentProto = "parent_proto.ptr = JS_GetObjectPrototype(cx, global)"
+ getPrototypeProto = "prototype_proto.ptr = JS_GetObjectPrototype(cx, global)"
else:
- parentProtoName = self.descriptor.prototypeChain[-2]
- getParentProto = ("%s::GetProtoObject(cx, global, receiver, parent_proto.handle_mut())" %
- toBindingNamespace(parentProtoName))
-
- getParentProto = ("let mut parent_proto = RootedObject::new(cx, ptr::null_mut());\n"
- "%s;\n"
- "assert!(!parent_proto.ptr.is_null());\n") % getParentProto
-
- if self.descriptor.interface.isCallback():
- protoClass = "None"
- else:
- protoClass = "Some(&PrototypeClass)"
+ getPrototypeProto = ("%s::GetProtoObject(cx, global, receiver, prototype_proto.handle_mut())" %
+ toBindingNamespace(self.descriptor.prototypeChain[-2]))
+
+ code = [CGGeneric("""\
+let mut prototype_proto = RootedObject::new(cx, ptr::null_mut());
+%s;
+assert!(!prototype_proto.ptr.is_null());""" % getPrototypeProto)]
+
+ properties = {"id": name}
+ for arrayName in self.properties.arrayNames():
+ array = getattr(self.properties, arrayName)
+ if arrayName == "consts":
+ if array.length():
+ properties[arrayName] = array.variableName()
+ else:
+ properties[arrayName] = "&[]"
+ elif array.length():
+ properties[arrayName] = "Some(%s)" % array.variableName()
+ else:
+ properties[arrayName] = "None"
+
+ code.append(CGGeneric("""
+create_interface_prototype_object(cx,
+ prototype_proto.handle(),
+ &PrototypeClass,
+ %(methods)s,
+ %(attrs)s,
+ %(consts)s,
+ rval);
+assert!(!rval.ptr.is_null());""" % properties))
if self.descriptor.interface.hasInterfaceObject():
+ properties["name"] = str_to_const_array(name)
if self.descriptor.interface.ctor():
- constructHook = CONSTRUCT_HOOK_NAME
- constructArgs = methodLength(self.descriptor.interface.ctor())
+ properties["constructor"] = CONSTRUCT_HOOK_NAME
+ properties["length"] = methodLength(self.descriptor.interface.ctor())
else:
- constructHook = "throwing_constructor"
- constructArgs = 0
-
- constructor = 'Some((%s as NonNullJSNative, "%s", %d))' % (
- constructHook, self.descriptor.interface.identifier.name,
- constructArgs)
- else:
- constructor = 'None'
-
- call = """\
-do_create_interface_objects(cx, receiver, parent_proto.handle(),
- %s, %s,
- &named_constructors,
- &sNativeProperties, rval);""" % (protoClass, constructor)
-
- 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 += "];"
+ properties["constructor"] = "throwing_constructor"
+ properties["length"] = 0
+
+ code.append(CGGeneric("""\
+
+create_noncallback_interface_object(cx,
+ receiver,
+ %(constructor)s,
+ %(static_methods)s,
+ %(static_attrs)s,
+ %(consts)s,
+ rval.handle(),
+ %(name)s,
+ %(length)s);""" % properties))
+
+ constructors = self.descriptor.interface.namedConstructors
+ if constructors:
+ decl = "let named_constructors: [(NonNullJSNative, &'static [u8], u32); %d]" % len(constructors)
+ specs = []
+ for constructor in constructors:
+ hook = CONSTRUCT_HOOK_NAME + "_" + constructor.identifier.name
+ name = str_to_const_array(constructor.identifier.name)
+ length = methodLength(constructor)
+ specs.append(CGGeneric("(%s as NonNullJSNative, %s, %d)" % (hook, name, length)))
+ values = CGIndenter(CGList(specs, "\n"), 4)
+ code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];"))
+ code.append(CGGeneric("create_named_constructors(cx, receiver, &named_constructors, rval.handle());"))
if self.descriptor.hasUnforgeableMembers:
# We want to use the same JSClass and prototype as the object we'll
@@ -2457,41 +2459,22 @@ let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [
# the prototype.
if self.descriptor.proxy or self.descriptor.isGlobal():
holderClass = "ptr::null()"
- holderProto = "ptr::null_mut()"
+ holderProto = "HandleObject::null()"
else:
holderClass = "&Class.base as *const js::jsapi::Class as *const JSClass"
- holderProto = "rval.get()"
- # JS_NewObjectWithoutMetadata() is unsafe.
- self.unsafe = True
- createUnforgeableHolder = CGGeneric("""
+ holderProto = "rval.handle()"
+ code.append(CGGeneric("""
let mut unforgeable_holder = RootedObject::new(cx, ptr::null_mut());
-{
- let holder_class = %(holderClass)s;
- let holder_proto = RootedObject::new(cx, %(holderProto)s);
- unforgeable_holder.handle_mut().set(
- JS_NewObjectWithoutMetadata(cx, holder_class, holder_proto.handle()));
- assert!(!unforgeable_holder.ptr.is_null());
-}""" % {'holderClass': holderClass, 'holderProto': holderProto})
- defineUnforgeables = InitUnforgeablePropertiesOnHolder(self.descriptor,
- self.properties)
- createUnforgeableHolder = CGList(
- [createUnforgeableHolder, defineUnforgeables], "\n")
-
- installUnforgeableHolder = CGGeneric("""\
+unforgeable_holder.handle_mut().set(
+ JS_NewObjectWithoutMetadata(cx, %(holderClass)s, %(holderProto)s));
+assert!(!unforgeable_holder.ptr.is_null());
+""" % {'holderClass': holderClass, 'holderProto': holderProto}))
+ code.append(InitUnforgeablePropertiesOnHolder(self.descriptor, self.properties))
+ code.append(CGGeneric("""\
JS_SetReservedSlot(rval.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT,
- ObjectValue(&*unforgeable_holder.ptr))""")
-
- unforgeableHolderSetup = CGList(
- [createUnforgeableHolder, installUnforgeableHolder], "\n")
- else:
- unforgeableHolderSetup = None
+ ObjectValue(&*unforgeable_holder.ptr))"""))
- return CGList([
- CGGeneric(getParentProto),
- CGGeneric(createArray),
- CGGeneric(call % self.properties.variableNames()),
- unforgeableHolderSetup,
- ], "\n")
+ return CGList(code, "\n")
class CGGetPerInterfaceObject(CGAbstractMethod):
@@ -4883,7 +4866,6 @@ class CGDescriptor(CGThing):
properties = PropertyArrays(descriptor)
cgThings.append(CGGeneric(str(properties)))
- cgThings.append(CGNativeProperties(descriptor, properties))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
cgThings.append(CGNamespace.build([descriptor.name + "Constants"],
@@ -5271,16 +5253,16 @@ class CGBindingRoot(CGThing):
'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
'js::jsapi::{JS_ComputeThis, JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
- 'js::jsapi::{JS_GetClass, JS_GetGlobalForObject, JS_GetObjectPrototype}',
- 'js::jsapi::{JS_GetProperty, JS_GetPropertyById, JS_GetPropertyDescriptorById}',
- 'js::jsapi::{JS_GetReservedSlot, JS_HasProperty, JS_HasPropertyById}',
- 'js::jsapi::{JS_InitializePropertiesFromCompatibleNativeObject, JS_InternString}',
- 'js::jsapi::{JS_IsExceptionPending, JS_NewObject, JS_NewObjectWithGivenProto}',
- 'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty, JS_SetPrototype}',
- 'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSAutoCompartment, JSAutoRequest}',
- 'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec, JSJitGetterCallArgs}',
- 'js::jsapi::{JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs, JSNative}',
- 'js::jsapi::{JSObject, JSNativeWrapper, JSPropertyDescriptor, JSPropertySpec}',
+ 'js::jsapi::{JS_GetClass, JS_GetFunctionPrototype, JS_GetGlobalForObject}',
+ 'js::jsapi::{JS_GetObjectPrototype, JS_GetProperty, JS_GetPropertyById}',
+ 'js::jsapi::{JS_GetPropertyDescriptorById, JS_GetReservedSlot, JS_HasProperty}',
+ 'js::jsapi::{JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
+ 'js::jsapi::{JS_InternString, JS_IsExceptionPending, JS_NewObject}',
+ 'js::jsapi::{JS_NewObjectWithGivenProto, JS_NewObjectWithoutMetadata, JS_SetProperty}',
+ 'js::jsapi::{JS_SetPrototype, JS_SetReservedSlot, JS_WrapValue, JSAutoCompartment}',
+ 'js::jsapi::{JSAutoRequest, JSContext, JSClass, JSFreeOp, JSFunctionSpec}',
+ 'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
+ 'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertyDescriptor, JSPropertySpec}',
'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
'js::jsapi::{ObjectOpResult, OpType, MutableHandle, MutableHandleObject}',
'js::jsapi::{MutableHandleValue, RootedId, RootedObject, RootedString}',
@@ -5296,13 +5278,14 @@ class CGBindingRoot(CGThing):
'js::rust::{GCMethods, define_methods, define_properties}',
'dom::bindings',
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
+ 'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
+ 'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
'dom::bindings::js::{JS, Root, RootedReference}',
'dom::bindings::js::{OptionalRootedReference}',
'dom::bindings::reflector::{Reflectable}',
'dom::bindings::utils::{ConstantSpec, DOMClass, DOMJSClass}',
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
- 'dom::bindings::utils::{NativeProperties, NonNullJSNative, create_dom_global}',
- 'dom::bindings::utils::{do_create_interface_objects, finalize_global}',
+ 'dom::bindings::utils::{NonNullJSNative, create_dom_global, finalize_global}',
'dom::bindings::utils::{find_enum_string_index, generic_getter}',
'dom::bindings::utils::{generic_lenient_getter, generic_lenient_setter}',
'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
new file mode 100644
index 00000000000..a7420c2aeb4
--- /dev/null
+++ b/components/script/dom/bindings/interface.rs
@@ -0,0 +1,155 @@
+/* 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/. */
+
+//! Machinery to initialise interface prototype objects and interface objects.
+
+use dom::bindings::utils::{ConstantSpec, NonNullJSNative, define_constants};
+use js::jsapi::{HandleObject, JSClass, JSContext, JSFunctionSpec, JSObject};
+use js::jsapi::{JSPropertySpec, JS_DefineProperty1, JS_GetFunctionObject};
+use js::jsapi::{JS_LinkConstructorAndPrototype, JS_NewFunction};
+use js::jsapi::{JS_NewObjectWithUniqueType, MutableHandleObject, RootedObject};
+use js::rust::{define_methods, define_properties};
+use js::{JSFUN_CONSTRUCTOR, JSPROP_PERMANENT, JSPROP_READONLY};
+use libc;
+use std::ptr;
+
+/// Create and define the interface object of a callback interface.
+pub unsafe fn create_callback_interface_object(
+ cx: *mut JSContext,
+ receiver: HandleObject,
+ constructor_native: NonNullJSNative,
+ length: u32,
+ constants: &'static [ConstantSpec],
+ name: &'static [u8]) {
+ assert!(!constants.is_empty());
+ let interface_object =
+ RootedObject::new(cx, create_constructor(cx, constructor_native, length, name));
+ assert!(!interface_object.ptr.is_null());
+ define_constants(cx, interface_object.handle(), constants);
+ define_on_global_object(cx, receiver, name, interface_object.handle());
+}
+
+/// Create the interface prototype object of a non-callback interface.
+pub unsafe fn create_interface_prototype_object(
+ cx: *mut JSContext,
+ proto: HandleObject,
+ class: &'static JSClass,
+ regular_methods: Option<&'static [JSFunctionSpec]>,
+ regular_properties: Option<&'static [JSPropertySpec]>,
+ constants: &'static [ConstantSpec],
+ rval: MutableHandleObject) {
+ create_object(cx, proto, class, regular_methods, regular_properties, constants, rval);
+}
+
+/// Create and define the interface object of a non-callback interface.
+pub unsafe fn create_noncallback_interface_object(
+ cx: *mut JSContext,
+ receiver: HandleObject,
+ constructor_native: NonNullJSNative,
+ static_methods: Option<&'static [JSFunctionSpec]>,
+ static_properties: Option<&'static [JSPropertySpec]>,
+ constants: &'static [ConstantSpec],
+ interface_prototype_object: HandleObject,
+ name: &'static [u8],
+ length: u32) {
+ assert!(!interface_prototype_object.ptr.is_null());
+
+ let interface_object =
+ RootedObject::new(cx, create_constructor(cx, constructor_native, length, name));
+ assert!(!interface_object.ptr.is_null());
+
+ if let Some(static_methods) = static_methods {
+ define_methods(cx, interface_object.handle(), static_methods).unwrap();
+ }
+
+ if let Some(static_properties) = static_properties {
+ define_properties(cx, interface_object.handle(), static_properties).unwrap();
+ }
+
+ define_constants(cx, interface_object.handle(), constants);
+
+ assert!(JS_LinkConstructorAndPrototype(cx, interface_object.handle(),
+ interface_prototype_object));
+ define_on_global_object(cx, receiver, name, interface_object.handle());
+}
+
+/// Create and define the named constructors of a non-callback interface.
+pub unsafe fn create_named_constructors(
+ cx: *mut JSContext,
+ receiver: HandleObject,
+ named_constructors: &[(NonNullJSNative, &'static [u8], u32)],
+ interface_prototype_object: HandleObject) {
+ let mut constructor = RootedObject::new(cx, ptr::null_mut());
+
+ for &(native, name, arity) in named_constructors {
+ assert!(*name.last().unwrap() == b'\0');
+
+ constructor.ptr = create_constructor(cx, native, arity, name);
+ assert!(!constructor.ptr.is_null());
+
+ assert!(JS_DefineProperty1(cx,
+ constructor.handle(),
+ b"prototype\0".as_ptr() as *const libc::c_char,
+ interface_prototype_object,
+ JSPROP_PERMANENT | JSPROP_READONLY,
+ None,
+ None));
+
+ define_on_global_object(cx, receiver, name, constructor.handle());
+ }
+}
+
+unsafe fn create_constructor(
+ cx: *mut JSContext,
+ constructor_native: NonNullJSNative,
+ ctor_nargs: u32,
+ name: &'static [u8])
+ -> *mut JSObject {
+ assert!(*name.last().unwrap() == b'\0');
+
+ let fun = JS_NewFunction(cx,
+ Some(constructor_native),
+ ctor_nargs,
+ JSFUN_CONSTRUCTOR,
+ name.as_ptr() as *const _);
+ assert!(!fun.is_null());
+
+ let constructor = JS_GetFunctionObject(fun);
+ assert!(!constructor.is_null());
+
+ constructor
+}
+
+unsafe fn create_object(
+ cx: *mut JSContext,
+ proto: HandleObject,
+ class: &'static JSClass,
+ methods: Option<&'static [JSFunctionSpec]>,
+ properties: Option<&'static [JSPropertySpec]>,
+ constants: &'static [ConstantSpec],
+ rval: MutableHandleObject) {
+ rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
+ assert!(!rval.ptr.is_null());
+ if let Some(methods) = methods {
+ define_methods(cx, rval.handle(), methods).unwrap();
+ }
+ if let Some(properties) = properties {
+ define_properties(cx, rval.handle(), properties).unwrap();
+ }
+ define_constants(cx, rval.handle(), constants);
+}
+
+unsafe fn define_on_global_object(
+ cx: *mut JSContext,
+ receiver: HandleObject,
+ name: &'static [u8],
+ obj: HandleObject) {
+ assert!(*name.last().unwrap() == b'\0');
+ assert!(JS_DefineProperty1(cx,
+ receiver,
+ name.as_ptr() as *const libc::c_char,
+ obj,
+ 0,
+ None, None));
+}
diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs
index df5f37ad07f..8bef928034c 100644
--- a/components/script/dom/bindings/mod.rs
+++ b/components/script/dom/bindings/mod.rs
@@ -138,6 +138,7 @@ pub mod conversions;
pub mod error;
pub mod global;
pub mod inheritance;
+pub mod interface;
pub mod js;
pub mod num;
pub mod proxyhandler;
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index 6173144490e..7815593355c 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -19,32 +19,19 @@ use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT};
use js::glue::{RUST_JSID_TO_INT, UnwrapObject};
-use js::jsapi::JSAutoCompartment;
-use js::jsapi::JS_DeletePropertyById1;
-use js::jsapi::JS_GetFunctionObject;
-use js::jsapi::JS_IsExceptionPending;
-use js::jsapi::JS_NewObjectWithUniqueType;
-use js::jsapi::JS_ObjectToOuterObject;
-use js::jsapi::{CallArgs, GetGlobalForObjectCrossCompartment, JSJitInfo};
-use js::jsapi::{CompartmentOptions, OnNewGlobalHookOption};
-use js::jsapi::{DOMCallbacks, JSWrapObjectCallbacks};
-use js::jsapi::{HandleId, HandleObject, HandleValue, MutableHandleValue};
-use js::jsapi::{Heap, MutableHandleObject, ObjectOpResult, RootedObject, RootedValue};
-use js::jsapi::{JSClass, JSContext, JSObject, JSTracer};
-use js::jsapi::{JSFunctionSpec, JSPropertySpec};
-use js::jsapi::{JSTraceOp, JS_AlreadyHasOwnProperty, JS_NewFunction};
-use js::jsapi::{JSVersion, JS_FireOnNewGlobalObject};
-use js::jsapi::{JS_DefineProperty, JS_DefineProperty1, JS_ForwardGetPropertyTo};
-use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype};
-use js::jsapi::{JS_GetProperty, JS_HasProperty, JS_SetProperty};
-use js::jsapi::{JS_GetPrototype, JS_HasPropertyById};
-use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot};
-use js::jsapi::{JS_InitStandardClasses, JS_NewGlobalObject};
+use js::jsapi::{CallArgs, CompartmentOptions, DOMCallbacks, GetGlobalForObjectCrossCompartment};
+use js::jsapi::{HandleId, HandleObject, HandleValue, Heap, JSAutoCompartment, JSClass, JSContext};
+use js::jsapi::{JSJitInfo, JSObject, JSTraceOp, JSTracer, JSVersion, JSWrapObjectCallbacks};
+use js::jsapi::{JS_DefineProperty, JS_DeletePropertyById1, JS_FireOnNewGlobalObject};
+use js::jsapi::{JS_ForwardGetPropertyTo, JS_GetClass, JS_GetProperty, JS_GetPrototype};
+use js::jsapi::{JS_GetReservedSlot, JS_HasProperty, JS_HasPropertyById, JS_InitStandardClasses};
+use js::jsapi::{JS_IsExceptionPending, JS_NewGlobalObject, JS_ObjectToOuterObject, JS_SetProperty};
+use js::jsapi::{JS_SetReservedSlot, MutableHandleValue, ObjectOpResult, OnNewGlobalHookOption};
+use js::jsapi::{RootedObject, RootedValue};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue};
use js::jsval::{PrivateValue, UInt32Value, UndefinedValue};
-use js::rust::{GCMethods, ToString, define_methods, define_properties};
-use js::{JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE, JS_CALLEE};
-use js::{JSPROP_PERMANENT, JSPROP_READONLY};
+use js::rust::{GCMethods, ToString};
+use js::{JS_CALLEE, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY};
use libc::{self, c_uint};
use std::default::Default;
use std::ffi::CString;
@@ -168,153 +155,13 @@ pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray
}
}
-/// Contains references to lists of methods, attributes, and constants for a
-/// given interface.
-pub struct NativeProperties {
- /// Instance methods for the interface.
- pub methods: Option<&'static [JSFunctionSpec]>,
- /// Unforgeable instance methods for the interface.
- pub unforgeable_methods: Option<&'static [JSFunctionSpec]>,
- /// Instance attributes for the interface.
- pub attrs: Option<&'static [JSPropertySpec]>,
- /// Unforgeable instance attributes for the interface.
- pub unforgeable_attrs: Option<&'static [JSPropertySpec]>,
- /// Constants for the interface.
- pub consts: Option<&'static [ConstantSpec]>,
- /// Static methods for the interface.
- pub static_methods: Option<&'static [JSFunctionSpec]>,
- /// Static attributes for the interface.
- pub static_attrs: Option<&'static [JSPropertySpec]>,
-}
-unsafe impl Sync for NativeProperties {}
-
/// A JSNative that cannot be null.
pub type NonNullJSNative =
unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> bool;
-/// Creates the *interface prototype object* (if a `proto_class` is given)
-/// and the *interface object* (if a `constructor` is given).
-/// Fails on JSAPI failure.
-pub fn do_create_interface_objects(cx: *mut JSContext,
- receiver: HandleObject,
- proto_proto: HandleObject,
- proto_class: Option<&'static JSClass>,
- constructor: Option<(NonNullJSNative, &'static str, u32)>,
- named_constructors: &[(NonNullJSNative, &'static str, u32)],
- members: &'static NativeProperties,
- rval: MutableHandleObject) {
- assert!(rval.get().is_null());
- if let Some(proto_class) = proto_class {
- create_interface_prototype_object(cx, proto_proto, proto_class, members, rval);
- }
-
- if let Some((native, name, nargs)) = constructor {
- let s = CString::new(name).unwrap();
- create_interface_object(cx,
- receiver,
- native,
- nargs,
- rval.handle(),
- members,
- s.as_ptr())
- }
-
- for ctor in named_constructors {
- 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(),
- b"prototype\0".as_ptr() as *const libc::c_char,
- rval.handle(),
- JSPROP_PERMANENT | JSPROP_READONLY,
- None,
- None));
- }
- 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 = false;
- assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined));
-
- if !already_defined {
- assert!(JS_DefineProperty1(cx, receiver, name, constructor, 0, None, None));
- }
-
- }
-}
-
-/// Creates the *interface object*.
-/// Fails on JSAPI failure.
-fn create_interface_object(cx: *mut JSContext,
- receiver: HandleObject,
- constructor_native: NonNullJSNative,
- ctor_nargs: u32,
- proto: HandleObject,
- members: &'static NativeProperties,
- name: *const libc::c_char) {
- unsafe {
- 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).unwrap();
- }
-
- if let Some(static_properties) = members.static_attrs {
- define_properties(cx, constructor.handle(), static_properties).unwrap();
- }
-
- if let Some(constants) = members.consts {
- define_constants(cx, constructor.handle(), constants);
- }
-
- if !proto.get().is_null() {
- assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto));
- }
-
- define_constructor(cx, receiver, name, constructor.handle());
- }
-}
-
/// Defines constants on `obj`.
/// Fails on JSAPI failure.
-fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'static [ConstantSpec]) {
+pub fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'static [ConstantSpec]) {
for spec in constants {
let value = RootedValue::new(cx, spec.get_value());
unsafe {
@@ -329,31 +176,6 @@ fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'static [
}
}
-/// Creates the *interface prototype object*.
-/// Fails on JSAPI failure.
-fn create_interface_prototype_object(cx: *mut JSContext,
- parent_proto: HandleObject,
- proto_class: &'static JSClass,
- members: &'static NativeProperties,
- rval: MutableHandleObject) {
- unsafe {
- rval.set(JS_NewObjectWithUniqueType(cx, proto_class, parent_proto));
- assert!(!rval.get().is_null());
-
- if let Some(methods) = members.methods {
- define_methods(cx, rval.handle(), methods).unwrap();
- }
-
- if let Some(properties) = members.attrs {
- define_properties(cx, rval.handle(), properties).unwrap();
- }
-
- if let Some(constants) = members.consts {
- define_constants(cx, rval.handle(), constants);
- }
- }
-}
-
/// A throwing constructor, for those interfaces that have neither
/// `NoInterfaceObject` nor `Constructor`.
pub unsafe extern "C" fn throwing_constructor(cx: *mut JSContext,