aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py50
-rw-r--r--components/script/dom/bindings/error.rs6
-rw-r--r--components/script/dom/bindings/utils.rs4
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()
+}