summaryrefslogtreecommitdiffstats
path: root/dom/bindings/BindingUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/bindings/BindingUtils.cpp')
-rw-r--r--dom/bindings/BindingUtils.cpp65
1 files changed, 32 insertions, 33 deletions
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index 11d12dd364..198db3b5e2 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -770,19 +770,31 @@ bool LegacyFactoryFunctionJSNative(JSContext* cx, unsigned argc,
->mNative(cx, argc, vp);
}
-static JSObject* CreateLegacyFactoryFunction(JSContext* cx, jsid name,
- const JSNativeHolder* nativeHolder,
- unsigned ctorNargs) {
- JSFunction* fun = js::NewFunctionByIdWithReserved(
- cx, LegacyFactoryFunctionJSNative, ctorNargs, JSFUN_CONSTRUCTOR, name);
+// This creates a JSFunction and sets its length and name properties in the
+// order that ECMAScript's CreateBuiltinFunction does.
+static JSObject* CreateBuiltinFunctionForConstructor(
+ JSContext* aCx, JSNative aNative, size_t aNativeReservedSlot,
+ void* aNativeReserved, unsigned int aNargs, jsid aName,
+ JS::Handle<JSObject*> aProto) {
+ JSFunction* fun = js::NewFunctionByIdWithReservedAndProto(
+ aCx, aNative, aProto, aNargs, JSFUN_CONSTRUCTOR, aName);
if (!fun) {
return nullptr;
}
- JSObject* constructor = JS_GetFunctionObject(fun);
- js::SetFunctionNativeReserved(
- constructor, LEGACY_FACTORY_FUNCTION_NATIVE_HOLDER_RESERVED_SLOT,
- JS::PrivateValue(const_cast<JSNativeHolder*>(nativeHolder)));
+ JS::Rooted<JSObject*> constructor(aCx, JS_GetFunctionObject(fun));
+ js::SetFunctionNativeReserved(constructor, aNativeReservedSlot,
+ JS::PrivateValue(aNativeReserved));
+
+ // Eagerly force creation of the .length and .name properties, because
+ // SpiderMonkey creates them lazily (see
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1629803).
+ bool unused;
+ if (!JS_HasProperty(aCx, constructor, "length", &unused) ||
+ !JS_HasProperty(aCx, constructor, "name", &unused)) {
+ return nullptr;
+ }
+
return constructor;
}
@@ -936,29 +948,12 @@ static JSObject* CreateInterfaceObject(
JS::Rooted<jsid> nameId(cx, JS::PropertyKey::NonIntAtom(name));
- JS::Rooted<JSObject*> constructor(cx);
- {
- JSFunction* fun = js::NewFunctionByIdWithReservedAndProto(
- cx, InterfaceObjectJSNative, interfaceProto, ctorNargs,
- JSFUN_CONSTRUCTOR, nameId);
- if (!fun) {
- return nullptr;
- }
-
- constructor = JS_GetFunctionObject(fun);
- }
-
- js::SetFunctionNativeReserved(
- constructor, INTERFACE_OBJECT_INFO_RESERVED_SLOT,
- JS::PrivateValue(const_cast<DOMInterfaceInfo*>(interfaceInfo)));
-
- // Eagerly force creation of the .length and .name properties, because they
- // need to be defined before the .prototype property (CreateBuiltinFunction
- // called from the WebIDL spec sets them, and then the .prototype property is
- // defined in the WebIDL spec itself).
- bool unused;
- if (!JS_HasProperty(cx, constructor, "length", &unused) ||
- !JS_HasProperty(cx, constructor, "name", &unused)) {
+ JS::Rooted<JSObject*> constructor(
+ cx, CreateBuiltinFunctionForConstructor(
+ cx, InterfaceObjectJSNative, INTERFACE_OBJECT_INFO_RESERVED_SLOT,
+ const_cast<DOMInterfaceInfo*>(interfaceInfo), ctorNargs, nameId,
+ interfaceProto));
+ if (!constructor) {
return nullptr;
}
@@ -1001,7 +996,11 @@ static JSObject* CreateInterfaceObject(
nameId = JS::PropertyKey::NonIntAtom(fname);
JS::Rooted<JSObject*> legacyFactoryFunction(
- cx, CreateLegacyFactoryFunction(cx, nameId, &lff.mHolder, lff.mNargs));
+ cx, CreateBuiltinFunctionForConstructor(
+ cx, LegacyFactoryFunctionJSNative,
+ LEGACY_FACTORY_FUNCTION_NATIVE_HOLDER_RESERVED_SLOT,
+ const_cast<JSNativeHolder*>(&lff.mHolder), lff.mNargs, nameId,
+ nullptr));
if (!legacyFactoryFunction ||
!JS_DefineProperty(cx, legacyFactoryFunction, "prototype", proto,
JSPROP_PERMANENT | JSPROP_READONLY) ||