Bug 1247934 - Handle receiving unboxed exports array from self hosted module code r=shu
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -295,20 +295,20 @@ ModuleNamespaceObject::create(JSContext*
}
ModuleObject&
ModuleNamespaceObject::module()
{
return GetProxyPrivate(this).toObject().as<ModuleObject>();
}
-ArrayObject&
+JSObject&
ModuleNamespaceObject::exports()
{
- ArrayObject* exports = module().namespaceExports();
+ JSObject* exports = module().namespaceExports();
MOZ_ASSERT(exports);
return *exports;
}
IndirectBindingMap&
ModuleNamespaceObject::bindings()
{
IndirectBindingMap* bindings = module().namespaceBindings();
@@ -493,25 +493,27 @@ ModuleNamespaceObject::ProxyHandler::del
return result.succeed();
}
bool
ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const
{
Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
- RootedArrayObject exports(cx, &ns->exports());
- uint32_t count = exports->length();
- if (!props.reserve(props.length() + count))
+ RootedObject exports(cx, &ns->exports());
+ uint32_t count;
+ if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count))
return false;
- for (uint32_t i = 0; i < count; i++) {
- Value value = exports->getDenseElement(i);
- props.infallibleAppend(AtomToId(&value.toString()->asAtom()));
- }
+ Rooted<ValueVector> names(cx, ValueVector(cx));
+ if (!names.resize(count) || !GetElements(cx, exports, count, names.begin()))
+ return false;
+
+ for (uint32_t i = 0; i < count; i++)
+ props.infallibleAppend(AtomToId(&names[i].toString()->asAtom()));
return true;
}
///////////////////////////////////////////////////////////////////////////
// FunctionDeclaration
FunctionDeclaration::FunctionDeclaration(HandleAtom name, HandleFunction fun)
@@ -626,24 +628,24 @@ ModuleObject::hasImportBindings() const
}
IndirectBindingMap&
ModuleObject::importBindings()
{
return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
}
-ArrayObject*
+JSObject*
ModuleObject::namespaceExports()
{
Value value = getReservedSlot(NamespaceExportsSlot);
if (value.isUndefined())
return nullptr;
- return &value.toObject().as<ArrayObject>();
+ return &value.toObject();
}
IndirectBindingMap*
ModuleObject::namespaceBindings()
{
Value value = getReservedSlot(NamespaceBindingsSlot);
if (value.isUndefined())
return nullptr;
@@ -815,19 +817,20 @@ ModuleObject::evaluate(JSContext* cx, Ha
JS_ReportError(cx, "Module declarations have not yet been instantiated");
return false;
}
return Execute(cx, script, *scope, rval.address());
}
/* static */ ModuleNamespaceObject*
-ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleArrayObject exports)
+ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
{
MOZ_ASSERT(!self->namespace_());
+ MOZ_ASSERT(exports->is<ArrayObject>() || exports->is<UnboxedArrayObject>());
RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
if (!ns)
return nullptr;
Zone* zone = cx->zone();
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
if (!bindings || !bindings->init()) {
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -128,17 +128,17 @@ class IndirectBindingMap
class ModuleNamespaceObject : public ProxyObject
{
public:
static bool isInstance(HandleValue value);
static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module);
ModuleObject& module();
- ArrayObject& exports();
+ JSObject& exports();
IndirectBindingMap& bindings();
bool addBinding(JSContext* cx, HandleAtom exportedName, HandleModuleObject targetModule,
HandleAtom localName);
private:
struct ProxyHandler : public BaseProxyHandler
{
@@ -240,29 +240,29 @@ class ModuleObject : public NativeObject
ModuleNamespaceObject* namespace_();
bool evaluated() const;
ArrayObject& requestedModules() const;
ArrayObject& importEntries() const;
ArrayObject& localExportEntries() const;
ArrayObject& indirectExportEntries() const;
ArrayObject& starExportEntries() const;
IndirectBindingMap& importBindings();
- ArrayObject* namespaceExports();
+ JSObject* namespaceExports();
IndirectBindingMap* namespaceBindings();
void createEnvironment();
bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
static bool instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self);
void setEvaluated();
static bool evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval);
static ModuleNamespaceObject* createNamespace(JSContext* cx, HandleModuleObject self,
- HandleArrayObject exports);
+ HandleObject exports);
private:
static void trace(JSTracer* trc, JSObject* obj);
static void finalize(js::FreeOp* fop, JSObject* obj);
bool hasScript() const;
bool hasImportBindings() const;
FunctionDeclarationVector* functionDeclarations();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1247934.js
@@ -0,0 +1,11 @@
+// |jit-test| --unboxed-arrays
+
+let moduleRepo = {};
+setModuleResolveHook(function(module, specifier) {
+ return moduleRepo[specifier];
+});
+setJitCompilerOption("ion.warmup.trigger", 50);
+s = "";
+for (i = 0; i < 1024; i++) s += "export let e" + i + "\n";
+moduleRepo['a'] = parseModule(s);
+parseModule("import * as ns from 'a'").declarationInstantiation();
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1629,17 +1629,17 @@ intrinsic_EvaluateModule(JSContext* cx,
}
static bool
intrinsic_NewModuleNamespace(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
- RootedArrayObject exports(cx, &args[1].toObject().as<ArrayObject>());
+ RootedObject exports(cx, &args[1].toObject());
RootedObject namespace_(cx, ModuleObject::createNamespace(cx, module, exports));
if (!namespace_)
return false;
args.rval().setObject(*namespace_);
return true;
}