@@ -770,19 +770,31 @@ bool LegacyFactoryFunctionJSNative(JSContext* cx, unsigned argc,
770770 ->mNative (cx, argc, vp);
771771}
772772
773- static JSObject* CreateLegacyFactoryFunction (JSContext* cx, jsid name,
774- const JSNativeHolder* nativeHolder,
775- unsigned ctorNargs) {
776- JSFunction* fun = js::NewFunctionByIdWithReserved (
777- cx, LegacyFactoryFunctionJSNative, ctorNargs, JSFUN_CONSTRUCTOR, name);
773+ // This creates a JSFunction and sets its length and name properties in the
774+ // order that ECMAScript's CreateBuiltinFunction does.
775+ static JSObject* CreateBuiltinFunctionForConstructor (
776+ JSContext* aCx, JSNative aNative, size_t aNativeReservedSlot,
777+ void * aNativeReserved, unsigned int aNargs, jsid aName,
778+ JS::Handle<JSObject*> aProto) {
779+ JSFunction* fun = js::NewFunctionByIdWithReservedAndProto (
780+ aCx, aNative, aProto, aNargs, JSFUN_CONSTRUCTOR, aName);
778781 if (!fun) {
779782 return nullptr ;
780783 }
781784
782- JSObject* constructor = JS_GetFunctionObject (fun);
783- js::SetFunctionNativeReserved (
784- constructor, LEGACY_FACTORY_FUNCTION_NATIVE_HOLDER_RESERVED_SLOT,
785- JS::PrivateValue (const_cast <JSNativeHolder*>(nativeHolder)));
785+ JS::Rooted<JSObject*> constructor (aCx, JS_GetFunctionObject (fun));
786+ js::SetFunctionNativeReserved (constructor, aNativeReservedSlot,
787+ JS::PrivateValue (aNativeReserved));
788+
789+ // Eagerly force creation of the .length and .name properties, because
790+ // SpiderMonkey creates them lazily (see
791+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1629803).
792+ bool unused;
793+ if (!JS_HasProperty (aCx, constructor, " length" , &unused) ||
794+ !JS_HasProperty (aCx, constructor, " name" , &unused)) {
795+ return nullptr ;
796+ }
797+
786798 return constructor;
787799}
788800
@@ -936,29 +948,12 @@ static JSObject* CreateInterfaceObject(
936948
937949 JS::Rooted<jsid> nameId (cx, JS::PropertyKey::NonIntAtom (name));
938950
939- JS::Rooted<JSObject*> constructor (cx);
940- {
941- JSFunction* fun = js::NewFunctionByIdWithReservedAndProto (
942- cx, InterfaceObjectJSNative, interfaceProto, ctorNargs,
943- JSFUN_CONSTRUCTOR, nameId);
944- if (!fun) {
945- return nullptr ;
946- }
947-
948- constructor = JS_GetFunctionObject (fun);
949- }
950-
951- js::SetFunctionNativeReserved (
952- constructor, INTERFACE_OBJECT_INFO_RESERVED_SLOT,
953- JS::PrivateValue (const_cast <DOMInterfaceInfo*>(interfaceInfo)));
954-
955- // Eagerly force creation of the .length and .name properties, because they
956- // need to be defined before the .prototype property (CreateBuiltinFunction
957- // called from the WebIDL spec sets them, and then the .prototype property is
958- // defined in the WebIDL spec itself).
959- bool unused;
960- if (!JS_HasProperty (cx, constructor, " length" , &unused) ||
961- !JS_HasProperty (cx, constructor, " name" , &unused)) {
951+ JS::Rooted<JSObject*> constructor (
952+ cx, CreateBuiltinFunctionForConstructor (
953+ cx, InterfaceObjectJSNative, INTERFACE_OBJECT_INFO_RESERVED_SLOT,
954+ const_cast <DOMInterfaceInfo*>(interfaceInfo), ctorNargs, nameId,
955+ interfaceProto));
956+ if (!constructor) {
962957 return nullptr ;
963958 }
964959
@@ -1001,7 +996,11 @@ static JSObject* CreateInterfaceObject(
1001996 nameId = JS::PropertyKey::NonIntAtom (fname);
1002997
1003998 JS::Rooted<JSObject*> legacyFactoryFunction (
1004- cx, CreateLegacyFactoryFunction (cx, nameId, &lff.mHolder , lff.mNargs ));
999+ cx, CreateBuiltinFunctionForConstructor (
1000+ cx, LegacyFactoryFunctionJSNative,
1001+ LEGACY_FACTORY_FUNCTION_NATIVE_HOLDER_RESERVED_SLOT,
1002+ const_cast <JSNativeHolder*>(&lff.mHolder ), lff.mNargs , nameId,
1003+ nullptr ));
10051004 if (!legacyFactoryFunction ||
10061005 !JS_DefineProperty (cx, legacyFactoryFunction, " prototype" , proto,
10071006 JSPROP_PERMANENT | JSPROP_READONLY) ||
0 commit comments