diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-04-25 02:45:29 -0700 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-04-25 02:45:29 -0700 |
commit | a92a6360cf2833c405ec668ee144db5de44c15cf (patch) | |
tree | cca9606df80b4a8b3bebdc03873c9392c08ada91 | |
parent | 59205323da10b5867d4386a50a290c3a7500c217 (diff) | |
parent | 4c2ca7a8c9244746ac168942651b0df6b6476626 (diff) | |
download | servo-a92a6360cf2833c405ec668ee144db5de44c15cf.tar.gz servo-a92a6360cf2833c405ec668ee144db5de44c15cf.zip |
Auto merge of #10819 - nox:call-without-new, r=Ms2ger
Refactor the `call` hook on non-callback interface objects (fixes #10744)
<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10819)
<!-- Reviewable:end -->
6 files changed, 67 insertions, 49 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 74dff1cce9f..1ef2e0a4eb9 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1897,20 +1897,24 @@ class CGInterfaceObjectJSClass(CGThing): def define(self): if self.descriptor.interface.ctor(): - constructor = CONSTRUCT_HOOK_NAME + constructorBehavior = "InterfaceConstructorBehavior::call(%s)" % CONSTRUCT_HOOK_NAME else: - constructor = "throwing_constructor" + constructorBehavior = "InterfaceConstructorBehavior::throw()" name = self.descriptor.interface.identifier.name args = { - "constructor": constructor, + "constructorBehavior": constructorBehavior, "id": name, "representation": str_to_const_array("function %s() {\\n [native code]\\n}" % name), "depth": self.descriptor.prototypeDepth } return """\ -static InterfaceObjectClass: NonCallbackInterfaceObjectClass = - NonCallbackInterfaceObjectClass::new(%(constructor)s, %(representation)s, - PrototypeList::ID::%(id)s, %(depth)s); +static InterfaceObjectClass: NonCallbackInterfaceObjectClass = unsafe { + NonCallbackInterfaceObjectClass::new( + %(constructorBehavior)s, + %(representation)s, + PrototypeList::ID::%(id)s, + %(depth)s) +}; """ % args @@ -2449,10 +2453,8 @@ if <*mut JSObject>::needs_post_barrier(prototype.ptr) { if self.descriptor.interface.hasInterfaceObject(): properties["name"] = str_to_const_array(name) if self.descriptor.interface.ctor(): - properties["constructor"] = CONSTRUCT_HOOK_NAME properties["length"] = methodLength(self.descriptor.interface.ctor()) else: - properties["constructor"] = "throwing_constructor" properties["length"] = 0 if self.descriptor.interface.parent: parentName = toBindingNamespace(self.descriptor.getParentName()) @@ -5400,9 +5402,9 @@ 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::{NonCallbackInterfaceObjectClass, create_callback_interface_object}', - 'dom::bindings::interface::{create_interface_prototype_object, create_named_constructors}', - 'dom::bindings::interface::{create_noncallback_interface_object}', + 'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}', + 'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}', + 'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}', 'dom::bindings::interface::{ConstantSpec, NonNullJSNative}', 'dom::bindings::interface::ConstantVal::{IntVal, UintVal}', 'dom::bindings::js::{JS, Root, RootedReference}', @@ -5416,8 +5418,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}', 'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}', 'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}', - 'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property}', - 'dom::bindings::utils::{throwing_constructor, trace_global}', + 'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}', 'dom::bindings::trace::{JSTraceable, RootedTraceable}', 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}', 'dom::bindings::callback::{CallSetup,ExceptionHandling}', diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 7db3c6e17c4..f41941f08b0 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -7,10 +7,11 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::conversions::get_dom_class; use dom::bindings::utils::get_proto_or_iface_array; +use js::error::throw_type_error; use js::glue::UncheckedUnwrapObject; use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment}; use js::jsapi::{HandleObject, HandleValue, JSClass, JSContext, JSFunctionSpec}; -use js::jsapi::{JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2}; +use js::jsapi::{JSNative, JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2}; use js::jsapi::{JS_DefineProperty4, JS_GetClass, JS_GetFunctionObject, JS_GetPrototype}; use js::jsapi::{JS_InternString, JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject}; use js::jsapi::{JS_NewObjectWithUniqueType, JS_NewStringCopyZ, JS_DefineProperty}; @@ -93,10 +94,6 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext, ret } -/// A constructor class hook. -pub type ConstructorClassHook = - unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool; - /// The class of a non-callback interface object. #[derive(Copy, Clone)] pub struct NonCallbackInterfaceObjectClass { @@ -114,8 +111,8 @@ unsafe impl Sync for NonCallbackInterfaceObjectClass {} impl NonCallbackInterfaceObjectClass { /// Create a new `NonCallbackInterfaceObjectClass` structure. - pub const fn new( - constructor: ConstructorClassHook, + pub const unsafe fn new( + constructor_behavior: InterfaceConstructorBehavior, string_rep: &'static [u8], proto_id: PrototypeList::ID, proto_depth: u16) @@ -132,8 +129,8 @@ impl NonCallbackInterfaceObjectClass { resolve: None, convert: None, finalize: None, - call: Some(constructor), - construct: Some(constructor), + call: constructor_behavior.call, + construct: constructor_behavior.construct, hasInstance: Some(has_instance_hook), trace: None, spec: ClassSpec { @@ -183,6 +180,34 @@ impl NonCallbackInterfaceObjectClass { } } +/// A constructor class hook. +pub type ConstructorClassHook = + unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool; + +/// The constructor behavior of a non-callback interface object. +pub struct InterfaceConstructorBehavior { + call: JSNative, + construct: JSNative, +} + +impl InterfaceConstructorBehavior { + /// An interface constructor that unconditionally throws a type error. + pub const fn throw() -> InterfaceConstructorBehavior { + InterfaceConstructorBehavior { + call: Some(invalid_constructor), + construct: Some(invalid_constructor), + } + } + + /// An interface constructor that calls a native Rust function. + pub const fn call(hook: ConstructorClassHook) -> InterfaceConstructorBehavior { + InterfaceConstructorBehavior { + call: Some(non_new_constructor), + construct: Some(hook), + } + } +} + /// Create and define the interface object of a callback interface. pub unsafe fn create_callback_interface_object( cx: *mut JSContext, @@ -380,3 +405,21 @@ unsafe fn define_on_global_object( 0, None, None)); } + +unsafe extern "C" fn invalid_constructor( + cx: *mut JSContext, + _argc: libc::c_uint, + _vp: *mut JSVal) + -> bool { + throw_type_error(cx, "Illegal constructor."); + false +} + +unsafe extern "C" fn non_new_constructor( + cx: *mut JSContext, + _argc: libc::c_uint, + _vp: *mut JSVal) + -> bool { + throw_type_error(cx, "This constructor needs to be called with `new`."); + false +} diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 2b4e5ee5ae0..9302bb40a09 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -16,7 +16,6 @@ use dom::browsingcontext; use dom::window; use heapsize::HeapSizeOf; use js; -use js::error::throw_type_error; use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper}; use js::glue::{GetCrossCompartmentWrapper, WrapperNew}; use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING}; @@ -35,7 +34,7 @@ use js::jsval::{JSVal}; use js::jsval::{PrivateValue, UndefinedValue}; use js::rust::{GCMethods, ToString}; use js::{JS_CALLEE}; -use libc::{self, c_uint}; +use libc; use std::default::Default; use std::ffi::CString; use std::os::raw::c_void; @@ -123,16 +122,6 @@ pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray } } -/// A throwing constructor, for those interfaces that have neither -/// `NoInterfaceObject` nor `Constructor`. -pub unsafe extern "C" fn throwing_constructor(cx: *mut JSContext, - _argc: c_uint, - _vp: *mut JSVal) - -> bool { - throw_type_error(cx, "Illegal constructor."); - false -} - /// An array of *mut JSObject of size PROTO_OR_IFACE_LENGTH. pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH]; diff --git a/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini b/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini index 233ecbce3d6..d0887557728 100644 --- a/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini +++ b/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini @@ -42,7 +42,3 @@ [Array with mixed types] expected: FAIL - [Blob constructor with no arguments, without 'new'] - bug: https://github.com/servo/servo/issues/10744 - expected: FAIL - diff --git a/tests/wpt/metadata/dom/events/Event-constructors.html.ini b/tests/wpt/metadata/dom/events/Event-constructors.html.ini deleted file mode 100644 index 82df4c7bb6b..00000000000 --- a/tests/wpt/metadata/dom/events/Event-constructors.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[Event-constructors.html] - type: testharness - [Event constructors 4] - expected: FAIL - bug: https://github.com/servo/servo/issues/10744 - diff --git a/tests/wpt/metadata/url/urlsearchparams-constructor.html.ini b/tests/wpt/metadata/url/urlsearchparams-constructor.html.ini deleted file mode 100644 index af33a71e148..00000000000 --- a/tests/wpt/metadata/url/urlsearchparams-constructor.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[urlsearchparams-constructor.html] - type: testharness - [URLSearchParams constructor, empty.] - expected: FAIL - |