From a45f117838d542ceb8f3557321dc410d4fbab3e5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 23 Apr 2016 13:43:49 +0200 Subject: Make NonCallbackInterfaceObjectClass::new unsafe --- components/script/dom/bindings/interface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/interface.rs') diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 7db3c6e17c4..668a87daa8f 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -114,7 +114,7 @@ unsafe impl Sync for NonCallbackInterfaceObjectClass {} impl NonCallbackInterfaceObjectClass { /// Create a new `NonCallbackInterfaceObjectClass` structure. - pub const fn new( + pub const unsafe fn new( constructor: ConstructorClassHook, string_rep: &'static [u8], proto_id: PrototypeList::ID, -- cgit v1.2.3 From 4c2ca7a8c9244746ac168942651b0df6b6476626 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 23 Apr 2016 14:02:55 +0200 Subject: Refactor the `call` hook on non-callback interface objects (fixes #10744) It's now set through the intermediate InterfaceConstructorBehavior structure, which lets us improve the abstraction around NonCallbackInterfaceObjectClass a bit better. When the interface's constructor is supposed to always throw, the error for calling `Foo()` without new is "Illegal constructor.". when the interface actually defines an interface, the error is instead "This constructor needs to be called with `new`.". --- components/script/dom/bindings/interface.rs | 59 +++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 8 deletions(-) (limited to 'components/script/dom/bindings/interface.rs') diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 668a87daa8f..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 { @@ -115,7 +112,7 @@ unsafe impl Sync for NonCallbackInterfaceObjectClass {} impl NonCallbackInterfaceObjectClass { /// Create a new `NonCallbackInterfaceObjectClass` structure. pub const unsafe fn new( - constructor: ConstructorClassHook, + 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 +} -- cgit v1.2.3