Bug 1229493 - Stop shell-only modules classes being reported as standard classes r=shu a=ritu
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 21 Dec 2015 10:47:37 -0800
changeset 292342 e7aa47e75e677772756edc6d536a88c8d9b8ad07
parent 292341 64b098725084f19cd6e6e363e361137ea15c96f9
child 292343 e58f733c4778d95ac1ce6521e54d044173a407c2
push id224
push usercbook@mozilla.com
push dateWed, 23 Dec 2015 13:34:07 +0000
reviewersshu, ritu
bugs1229493
milestone43.0
Bug 1229493 - Stop shell-only modules classes being reported as standard classes r=shu a=ritu
js/public/Class.h
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/jsprototypes.h
js/src/shell/js.cpp
js/src/vm/GlobalObject.h
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -732,17 +732,17 @@ struct JSClass {
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
 #define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
 #define JSCLASS_GLOBAL_SLOT_COUNT                                             \
-    (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 36)
+    (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 39)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -67,17 +67,16 @@ ModuleValueGetter(JSContext* cx, unsigne
 
 ///////////////////////////////////////////////////////////////////////////
 // ImportEntryObject
 
 /* static */ const Class
 ImportEntryObject::class_ = {
     "ImportEntry",
     JSCLASS_HAS_RESERVED_SLOTS(ImportEntryObject::SlotCount) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_ImportEntry) |
     JSCLASS_IS_ANONYMOUS
 };
 
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, localName, LocalNameSlot)
 
 DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryObject, moduleRequest)
@@ -85,67 +84,62 @@ DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryO
 DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryObject, localName)
 
 /* static */ bool
 ImportEntryObject::isInstance(HandleValue value)
 {
     return value.isObject() && value.toObject().is<ImportEntryObject>();
 }
 
-/* static */ JSObject*
-ImportEntryObject::initClass(JSContext* cx, HandleObject obj)
+/* static */ bool
+GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     static const JSPropertySpec protoAccessors[] = {
         JS_PSG("moduleRequest", ImportEntryObject_moduleRequestGetter, 0),
         JS_PSG("importName", ImportEntryObject_importNameGetter, 0),
         JS_PSG("localName", ImportEntryObject_localNameGetter, 0),
         JS_PS_END
     };
 
-    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
     if (!proto)
-        return nullptr;
+        return false;
 
     if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
-        return nullptr;
+        return false;
 
-    global->setPrototype(JSProto_ImportEntry, ObjectValue(*proto));
-    return proto;
-}
-
-JSObject*
-js::InitImportEntryClass(JSContext* cx, HandleObject obj)
-{
-    return ImportEntryObject::initClass(cx, obj);
+    global->setReservedSlot(IMPORT_ENTRY_PROTO, ObjectValue(*proto));
+    return true;
 }
 
 /* static */ ImportEntryObject*
 ImportEntryObject::create(JSContext* cx,
                           HandleAtom moduleRequest,
                           HandleAtom importName,
                           HandleAtom localName)
 {
-    RootedImportEntry self(cx, NewBuiltinClassInstance<ImportEntryObject>(cx));
-    if (!self)
+    RootedObject proto(cx, cx->global()->getImportEntryPrototype());
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
+    if (!obj)
         return nullptr;
+
+    RootedImportEntry self(cx, &obj->as<ImportEntryObject>());
     self->initReservedSlot(ModuleRequestSlot, StringValue(moduleRequest));
     self->initReservedSlot(ImportNameSlot, StringValue(importName));
     self->initReservedSlot(LocalNameSlot, StringValue(localName));
     return self;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // ExportEntryObject
 
 /* static */ const Class
 ExportEntryObject::class_ = {
     "ExportEntry",
     JSCLASS_HAS_RESERVED_SLOTS(ExportEntryObject::SlotCount) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_ExportEntry) |
     JSCLASS_IS_ANONYMOUS
 };
 
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, exportName, ExportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, localName, LocalNameSlot)
 
@@ -155,61 +149,57 @@ DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(Expo
 DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, localName)
 
 /* static */ bool
 ExportEntryObject::isInstance(HandleValue value)
 {
     return value.isObject() && value.toObject().is<ExportEntryObject>();
 }
 
-/* static */ JSObject*
-ExportEntryObject::initClass(JSContext* cx, HandleObject obj)
+/* static */ bool
+GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     static const JSPropertySpec protoAccessors[] = {
         JS_PSG("exportName", ExportEntryObject_exportNameGetter, 0),
         JS_PSG("moduleRequest", ExportEntryObject_moduleRequestGetter, 0),
         JS_PSG("importName", ExportEntryObject_importNameGetter, 0),
         JS_PSG("localName", ExportEntryObject_localNameGetter, 0),
         JS_PS_END
     };
 
-    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
     if (!proto)
-        return nullptr;
+        return false;
 
     if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
-        return nullptr;
+        return false;
 
-    global->setPrototype(JSProto_ExportEntry, ObjectValue(*proto));
-    return proto;
-}
-
-JSObject*
-js::InitExportEntryClass(JSContext* cx, HandleObject obj)
-{
-    return ExportEntryObject::initClass(cx, obj);
+    global->setReservedSlot(EXPORT_ENTRY_PROTO, ObjectValue(*proto));
+    return true;
 }
 
 static Value
 StringOrNullValue(JSString* maybeString)
 {
     return maybeString ? StringValue(maybeString) : NullValue();
 }
 
 /* static */ ExportEntryObject*
 ExportEntryObject::create(JSContext* cx,
                           HandleAtom maybeExportName,
                           HandleAtom maybeModuleRequest,
                           HandleAtom maybeImportName,
                           HandleAtom maybeLocalName)
 {
-    RootedExportEntry self(cx, NewBuiltinClassInstance<ExportEntryObject>(cx));
-    if (!self)
+    RootedObject proto(cx, cx->global()->getExportEntryPrototype());
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
+    if (!obj)
         return nullptr;
+
+    RootedExportEntry self(cx, &obj->as<ExportEntryObject>());
     self->initReservedSlot(ExportNameSlot, StringOrNullValue(maybeExportName));
     self->initReservedSlot(ModuleRequestSlot, StringOrNullValue(maybeModuleRequest));
     self->initReservedSlot(ImportNameSlot, StringOrNullValue(maybeImportName));
     self->initReservedSlot(LocalNameSlot, StringOrNullValue(maybeLocalName));
     return self;
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -505,26 +495,25 @@ void FunctionDeclaration::trace(JSTracer
 
 ///////////////////////////////////////////////////////////////////////////
 // ModuleObject
 
 /* static */ const Class
 ModuleObject::class_ = {
     "Module",
     JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Module) |
     JSCLASS_IS_ANONYMOUS,
     nullptr,        /* addProperty */
     nullptr,        /* delProperty */
     nullptr,        /* getProperty */
     nullptr,        /* setProperty */
     nullptr,        /* enumerate   */
     nullptr,        /* resolve     */
     nullptr,        /* mayResolve  */
-    nullptr,        /* finalize    */
+    ModuleObject::finalize,
     nullptr,        /* call        */
     nullptr,        /* hasInstance */
     nullptr,        /* construct   */
     ModuleObject::trace
 };
 
 #define DEFINE_ARRAY_SLOT_ACCESSOR(cls, name, slot)                           \
     ArrayObject&                                                              \
@@ -543,20 +532,22 @@ DEFINE_ARRAY_SLOT_ACCESSOR(ModuleObject,
 ModuleObject::isInstance(HandleValue value)
 {
     return value.isObject() && value.toObject().is<ModuleObject>();
 }
 
 /* static */ ModuleObject*
 ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope)
 {
-    Rooted<ModuleObject*> self(cx, NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject));
-    if (!self)
+    RootedObject proto(cx, cx->global()->getModulePrototype());
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
+    if (!obj)
         return nullptr;
 
+    RootedModuleObject self(cx, &obj->as<ModuleObject>());
     self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(enclosingStaticScope));
 
     IndirectBindingMap* bindings = cx->new_<IndirectBindingMap>();
     if (!bindings || !bindings->init()) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
@@ -814,18 +805,18 @@ ModuleObject::createNamespace(JSContext*
 DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluated, EvaluatedSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, indirectExportEntries, IndirectExportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, starExportEntries, StarExportEntriesSlot)
 
-JSObject*
-js::InitModuleClass(JSContext* cx, HandleObject obj)
+/* static */ bool
+GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     static const JSPropertySpec protoAccessors[] = {
         JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
         JS_PSG("evaluated", ModuleObject_evaluatedGetter, 0),
         JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
         JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
         JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
         JS_PSG("indirectExportEntries", ModuleObject_indirectExportEntriesGetter, 0),
@@ -836,27 +827,34 @@ js::InitModuleClass(JSContext* cx, Handl
     static const JSFunctionSpec protoFunctions[] = {
         JS_SELF_HOSTED_FN("getExportedNames", "ModuleGetExportedNames", 1, 0),
         JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 3, 0),
         JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0),
         JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0),
         JS_FS_END
     };
 
-    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
-
     RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
     if (!proto)
-        return nullptr;
+        return false;
 
     if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, protoFunctions))
-        return nullptr;
+        return false;
+
+    global->setReservedSlot(MODULE_PROTO, ObjectValue(*proto));
+    return true;
+}
 
-    global->setPrototype(JSProto_Module, ObjectValue(*proto));
-    return proto;
+bool
+js::InitModuleClasses(JSContext* cx, HandleObject obj)
+{
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
+    return GlobalObject::initModuleProto(cx, global) &&
+           GlobalObject::initImportEntryProto(cx, global) &&
+           GlobalObject::initExportEntryProto(cx, global);
 }
 
 #undef DEFINE_GETTER_FUNCTIONS
 #undef DEFINE_STRING_ACCESSOR_METHOD
 #undef DEFINE_ARRAY_SLOT_ACCESSOR
 
 ///////////////////////////////////////////////////////////////////////////
 // ModuleBuilder
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -264,15 +264,13 @@ class MOZ_STACK_CLASS ModuleBuilder
                                    HandleAtom importName);
 
     bool maybeAppendRequestedModule(HandleAtom module);
 
     template <typename T>
     ArrayObject* createArray(const TraceableVector<T>& vector);
 };
 
-JSObject* InitModuleClass(JSContext* cx, HandleObject obj);
-JSObject* InitImportEntryClass(JSContext* cx, HandleObject obj);
-JSObject* InitExportEntryClass(JSContext* cx, HandleObject obj);
+bool InitModuleClasses(JSContext* cx, HandleObject obj);
 
 } // namespace js
 
 #endif /* builtin_ModuleObject_h */
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -107,15 +107,12 @@ IF_SAB(real,imaginary)(SharedUint16Array
 IF_SAB(real,imaginary)(SharedInt32Array,        47,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Int32)) \
 IF_SAB(real,imaginary)(SharedUint32Array,       48,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint32)) \
 IF_SAB(real,imaginary)(SharedFloat32Array,      49,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Float32)) \
 IF_SAB(real,imaginary)(SharedFloat64Array,      50,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Float64)) \
 IF_SAB(real,imaginary)(SharedUint8ClampedArray, 51,     InitViaClassSpec,       SHARED_TYPED_ARRAY_CLASP(Uint8Clamped)) \
     real(TypedArray,            52,      InitViaClassSpec,      &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
 IF_SAB(real,imaginary)(Atomics,                 53,     InitAtomicsClass, OCLASP(Atomics)) \
     real(SavedFrame,            54,      InitViaClassSpec,      &js::SavedFrame::class_) \
-    real(Module,                55,      InitModuleClass,       OCLASP(Module)) \
-    real(ImportEntry,           56,      InitImportEntryClass,  OCLASP(ImportEntry)) \
-    real(ExportEntry,           57,      InitExportEntryClass,  OCLASP(ExportEntry)) \
 
 #define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
 
 #endif /* jsprototypes_h */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5904,16 +5904,19 @@ NewGlobalObject(JSContext* cx, JS::Compa
 
         RootedObject domProto(cx, JS_InitClass(cx, glob, nullptr, &dom_class, dom_constructor,
                                                0, dom_props, dom_methods, nullptr, nullptr));
         if (!domProto)
             return nullptr;
 
         /* Initialize FakeDOMObject.prototype */
         InitDOMObject(domProto);
+
+        if (!js::InitModuleClasses(cx, glob))
+            return nullptr;
     }
 
     JS_FireOnNewGlobalObject(cx, glob);
 
     return glob;
 }
 
 static bool
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -100,16 +100,19 @@ class GlobalObject : public NativeObject
         STAR_GENERATOR_OBJECT_PROTO,
         STAR_GENERATOR_FUNCTION_PROTO,
         STAR_GENERATOR_FUNCTION,
         MAP_ITERATOR_PROTO,
         SET_ITERATOR_PROTO,
         COLLATOR_PROTO,
         NUMBER_FORMAT_PROTO,
         DATE_TIME_FORMAT_PROTO,
+        MODULE_PROTO,
+        IMPORT_ENTRY_PROTO,
+        EXPORT_ENTRY_PROTO,
         REGEXP_STATICS,
         WARNED_ONCE_FLAGS,
         RUNTIME_CODEGEN_ENABLED,
         DEBUGGERS,
         INTRINSICS,
         FLOAT32X4_TYPE_DESCR,
         FLOAT64X2_TYPE_DESCR,
         INT8X16_TYPE_DESCR,
@@ -499,16 +502,28 @@ class GlobalObject : public NativeObject
     JSObject* getOrCreateNumberFormatPrototype(JSContext* cx) {
         return getOrCreateObject(cx, NUMBER_FORMAT_PROTO, initNumberFormatProto);
     }
 
     JSObject* getOrCreateDateTimeFormatPrototype(JSContext* cx) {
         return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
     }
 
+    JSObject* getModulePrototype() {
+        return &getSlot(MODULE_PROTO).toObject();
+    }
+
+    JSObject* getImportEntryPrototype() {
+        return &getSlot(IMPORT_ENTRY_PROTO).toObject();
+    }
+
+    JSObject* getExportEntryPrototype() {
+        return &getSlot(EXPORT_ENTRY_PROTO).toObject();
+    }
+
     static JSFunction*
     getOrCreateTypedArrayConstructor(JSContext* cx, Handle<GlobalObject*> global) {
         if (!ensureConstructor(cx, global, JSProto_TypedArray))
             return nullptr;
         return &global->getConstructor(JSProto_TypedArray).toObject().as<JSFunction>();
     }
 
     static JSObject*
@@ -713,16 +728,21 @@ class GlobalObject : public NativeObject
     static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
 
     // Implemented in Intl.cpp.
     static bool initIntlObject(JSContext* cx, Handle<GlobalObject*> global);
     static bool initCollatorProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initNumberFormatProto(JSContext* cx, Handle<GlobalObject*> global);
     static bool initDateTimeFormatProto(JSContext* cx, Handle<GlobalObject*> global);
 
+    // Implemented in builtin/ModuleObject.cpp
+    static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
+    static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
+    static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
+
     // Implemented in builtin/TypedObject.cpp
     static bool initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global);
 
     static bool initStandardClasses(JSContext* cx, Handle<GlobalObject*> global);
     static bool initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> global,
                                         const JSFunctionSpec* builtins);
 
     typedef js::Vector<js::Debugger*, 0, js::SystemAllocPolicy> DebuggerVector;