diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 50 | ||||
-rw-r--r-- | components/script/dom/bindings/error.rs | 6 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 4 |
3 files changed, 45 insertions, 15 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index b0f89c6a1d3..985a6c590c9 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -3963,6 +3963,17 @@ let global = GlobalScope::from_object(args.callee()); raise NotImplementedError # Override me! +def GetConstructorNameForReporting(descriptor, ctor): + # Figure out the name of our constructor for reporting purposes. + # For unnamed webidl constructors, identifier.name is "constructor" but + # the name JS sees is the interface name; for legacy factory functions + # identifier.name is the actual name. + ctorName = ctor.identifier.name + if ctorName == "constructor": + return descriptor.interface.identifier.name + return ctorName + + class CGSpecializedMethod(CGAbstractExternMethod): """ A class for generating the C++ code for a specialized method that the JIT @@ -6117,24 +6128,11 @@ class CGClassConstructHook(CGAbstractExternMethod): preamble = """let cx = SafeJSContext::from_ptr(cx); let args = CallArgs::from_vp(vp, argc); let global = GlobalScope::from_object(JS_CALLEE(*cx, vp).to_object()); -rooted!(in(*cx) let mut desired_proto = ptr::null_mut::<JSObject>()); -let proto_result = get_desired_proto( - cx, - &args, - PrototypeList::ID::%s, - CreateInterfaceObjects, - desired_proto.handle_mut(), -); - assert!(proto_result.is_ok()); -if proto_result.is_err() { - return false; -} -""" % (MakeNativeName(self.descriptor.name)) +""" if len(self.exposureSet) == 1: preamble += """\ let global = DomRoot::downcast::<dom::types::%s>(global).unwrap(); """ % list(self.exposureSet)[0] - preamble = CGGeneric(preamble) if self.constructor.isHTMLConstructor(): signatures = self.constructor.signatures() assert len(signatures) == 1 @@ -6145,12 +6143,32 @@ let global = DomRoot::downcast::<dom::types::%s>(global).unwrap(); GetProtoObject, )""" % self.descriptor.name) else: + ctorName = GetConstructorNameForReporting(self.descriptor, self.constructor) + preamble += """ +if !callargs_is_constructing(&args) { + throw_constructor_without_new(*cx, "%s"); + return false; +} + +rooted!(in(*cx) let mut desired_proto = ptr::null_mut::<JSObject>()); +let proto_result = get_desired_proto( + cx, + &args, + PrototypeList::ID::%s, + CreateInterfaceObjects, + desired_proto.handle_mut(), +); +assert!(proto_result.is_ok()); +if proto_result.is_err() { + return false; +} +""" % (ctorName, MakeNativeName(self.descriptor.name)) name = self.constructor.identifier.name nativeName = MakeNativeName(self.descriptor.binaryNameFor(name)) args = ["&global", "Some(desired_proto.handle())"] constructorCall = CGMethodCall(args, nativeName, True, self.descriptor, self.constructor) - return CGList([preamble, constructorCall]) + return CGList([CGGeneric(preamble), constructorCall]) class CGClassFinalizeHook(CGAbstractClassHook): @@ -6490,6 +6508,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'crate::dom::bindings::utils::DOM_PROTO_UNFORGEABLE_HOLDER_SLOT', 'crate::dom::bindings::utils::JSCLASS_DOM_GLOBAL', 'crate::dom::bindings::utils::ProtoOrIfaceArray', + 'crate::dom::bindings::utils::callargs_is_constructing', 'crate::dom::bindings::utils::enumerate_global', 'crate::dom::bindings::utils::finalize_global', 'crate::dom::bindings::utils::generic_getter', @@ -6540,6 +6559,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'crate::dom::bindings::error::Fallible', 'crate::dom::bindings::error::Error::JSFailed', 'crate::dom::bindings::error::throw_dom_exception', + 'crate::dom::bindings::error::throw_constructor_without_new', 'crate::dom::bindings::guard::Condition', 'crate::dom::bindings::guard::Guard', 'crate::dom::bindings::inheritance::Castable', diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs index 9356918ccc1..87df14d0544 100644 --- a/components/script/dom/bindings/error.rs +++ b/components/script/dom/bindings/error.rs @@ -312,6 +312,12 @@ pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) { throw_type_error(cx, &error); } +pub unsafe fn throw_constructor_without_new(cx: *mut JSContext, name: &str) { + debug_assert!(!JS_IsExceptionPending(cx)); + let error = format!("{} constructor: 'new' is required", name); + throw_type_error(cx, &error); +} + impl Error { /// Convert this error value to a JS value, consuming it in the process. pub unsafe fn to_jsval( diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 87748da1ec4..7557f4a3fa8 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -637,3 +637,7 @@ impl AsCCharPtrPtr for [u8] { self as *const [u8] as *const c_char } } + +pub unsafe fn callargs_is_constructing(args: &CallArgs) -> bool { + (*args.argv_.offset(-1)).is_magic() +} |