summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-11-28 10:17:43 +0000
committerMoonchild <moonchild@palemoon.org>2020-11-28 10:17:43 +0000
commite6b9d9cbeae7d90a7f368517c67775c0d72c6445 (patch)
treeb10c4075973d3949a47d60becd9db46b8e505fe4
parentb863bd2edc94c16498edc3274531f57fbfc30d3f (diff)
downloaduxp-modulefix.tar.gz
Issue #1624 - Add missing error handling and bail on null specifier.modulefix
-rw-r--r--dom/script/ScriptLoader.cpp65
-rw-r--r--js/public/Class.h2
-rw-r--r--js/src/builtin/Module.js4
-rw-r--r--js/src/builtin/ModuleObject.cpp128
-rw-r--r--js/src/builtin/ModuleObject.h41
-rw-r--r--js/src/builtin/ReflectParse.cpp3
-rw-r--r--js/src/frontend/BytecodeCompiler.cpp3
-rw-r--r--js/src/gc/Policy.h2
-rw-r--r--js/src/jit-test/tests/modules/requested-modules.js2
-rw-r--r--js/src/jsapi.cpp23
-rw-r--r--js/src/jsapi.h25
-rw-r--r--js/src/vm/GlobalObject.h13
12 files changed, 232 insertions, 79 deletions
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index 5b7bea8d22..e11511eb92 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -599,38 +599,31 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
return rv;
}
-static bool
-CreateTypeError(JSContext* aCx, ModuleScript* aScript, const nsString& aMessage,
- JS::MutableHandle<JS::Value> aError)
+static nsresult
+HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
+ const nsAString& aSpecifier,
+ uint32_t aLineNumber, uint32_t aColumnNumber)
{
- JS::Rooted<JSObject*> module(aCx, aScript->ModuleRecord());
- JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aCx, module));
+ nsAutoCString url;
+ aScript->BaseURL()->GetAsciiSpec(url);
+
JS::Rooted<JSString*> filename(aCx);
- filename = JS_NewStringCopyZ(aCx, JS_GetScriptFilename(script));
+ filename = JS_NewStringCopyZ(aCx, url.get());
if (!filename) {
- return false;
- }
-
- JS::Rooted<JSString*> message(aCx, JS_NewUCStringCopyZ(aCx, aMessage.get()));
- if (!message) {
- return false;
+ return NS_ERROR_OUT_OF_MEMORY;
}
- return JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
- message, aError);
-}
-
-static nsresult
-HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
- const nsAString& aSpecifier)
-{
- // TODO: How can we get the line number of the failed import?
-
nsAutoString message(NS_LITERAL_STRING("Error resolving module specifier: "));
message.Append(aSpecifier);
+ JS::Rooted<JSString*> string(aCx, JS_NewUCStringCopyZ(aCx, message.get()));
+ if (!string) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
JS::Rooted<JS::Value> error(aCx);
- if (!CreateTypeError(aCx, aScript, message, &error)) {
+ if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, aLineNumber,
+ aColumnNumber, nullptr, string, &error)) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -685,28 +678,37 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOu
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> moduleRecord(cx, ms->ModuleRecord());
- JS::Rooted<JSObject*> specifiers(cx, JS::GetRequestedModules(cx, moduleRecord));
+ JS::Rooted<JSObject*> requestedModules(cx);
+ requestedModules = JS::GetRequestedModules(cx, moduleRecord);
+ MOZ_ASSERT(requestedModules);
uint32_t length;
- if (!JS_GetArrayLength(cx, specifiers, &length)) {
+ if (!JS_GetArrayLength(cx, requestedModules, &length)) {
return NS_ERROR_FAILURE;
}
- JS::Rooted<JS::Value> val(cx);
+ JS::Rooted<JS::Value> element(cx);
for (uint32_t i = 0; i < length; i++) {
- if (!JS_GetElement(cx, specifiers, i, &val)) {
+ if (!JS_GetElement(cx, requestedModules, i, &element)) {
return NS_ERROR_FAILURE;
}
+ JS::Rooted<JSString*> str(cx, JS::GetRequestedModuleSpecifier(cx, element));
+ MOZ_ASSERT(str);
+
nsAutoJSString specifier;
- if (!specifier.init(cx, val)) {
+ if (!specifier.init(cx, str)) {
return NS_ERROR_FAILURE;
}
// Let url be the result of resolving a module specifier given module script and requested.
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
if (!uri) {
- nsresult rv = HandleResolveFailure(cx, ms, specifier);
+ uint32_t lineNumber = 0;
+ uint32_t columnNumber = 0;
+ JS::GetRequestedModuleSourcePos(cx, element, &lineNumber, &columnNumber);
+
+ nsresult rv = HandleResolveFailure(cx, ms, specifier, lineNumber, columnNumber);
NS_ENSURE_SUCCESS(rv, rv);
return NS_ERROR_FAILURE;
}
@@ -806,6 +808,11 @@ HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
auto script = static_cast<ModuleScript*>(value.toPrivate());
MOZ_ASSERT(script->ModuleRecord() == aModule);
+ // FIXME: in-line module scripts apparently pass a null specifier?
+ // At least make sure that doesn't crash the browser.
+ if (!aSpecifier)
+ return nullptr;
+
// Let url be the result of resolving a module specifier given referencing
// module script and specifier.
nsAutoJSString string;
diff --git a/js/public/Class.h b/js/public/Class.h
index 9cb3778920..094e4a7ed7 100644
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -778,7 +778,7 @@ struct JSClass {
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
- (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45)
+ (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 46)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js
index 355303d44d..a7758484eb 100644
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -363,7 +363,7 @@ function InnerModuleInstantiation(module, stack, index)
// Step 9
let requestedModules = module.requestedModules;
for (let i = 0; i < requestedModules.length; i++) {
- let required = requestedModules[i];
+ let required = requestedModules[i].moduleSpecifier;
let requiredModule = CallModuleResolveHook(module, required, MODULE_STATUS_UNINSTANTIATED);
index = InnerModuleInstantiation(requiredModule, stack, index);
@@ -591,7 +591,7 @@ function InnerModuleEvaluation(module, stack, index)
// Step 10
let requestedModules = module.requestedModules;
for (let i = 0; i < requestedModules.length; i++) {
- let required = requestedModules[i];
+ let required = requestedModules[i].moduleSpecifier;
let requiredModule =
CallModuleResolveHook(module, required, MODULE_STATUS_INSTANTIATED);
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 2790b1c444..a09dd77dde 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -125,7 +125,7 @@ GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
return false;
- global->setReservedSlot(IMPORT_ENTRY_PROTO, ObjectValue(*proto));
+ global->initReservedSlot(IMPORT_ENTRY_PROTO, ObjectValue(*proto));
return true;
}
@@ -203,7 +203,7 @@ GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
return false;
- global->setReservedSlot(EXPORT_ENTRY_PROTO, ObjectValue(*proto));
+ global->initReservedSlot(EXPORT_ENTRY_PROTO, ObjectValue(*proto));
return true;
}
@@ -241,6 +241,71 @@ ExportEntryObject::create(ExclusiveContext* cx,
}
///////////////////////////////////////////////////////////////////////////
+// RequestedModuleObject
+
+/* static */ const Class
+RequestedModuleObject::class_ = {
+ "RequestedModule",
+ JSCLASS_HAS_RESERVED_SLOTS(RequestedModuleObject::SlotCount) |
+ JSCLASS_IS_ANONYMOUS
+};
+
+DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, moduleSpecifier, ModuleSpecifierSlot)
+DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, lineNumber, LineNumberSlot)
+DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, columnNumber, ColumnNumberSlot)
+
+DEFINE_ATOM_ACCESSOR_METHOD(RequestedModuleObject, moduleSpecifier)
+DEFINE_UINT32_ACCESSOR_METHOD(RequestedModuleObject, lineNumber)
+DEFINE_UINT32_ACCESSOR_METHOD(RequestedModuleObject, columnNumber)
+
+/* static */ bool
+RequestedModuleObject::isInstance(HandleValue value)
+{
+ return value.isObject() && value.toObject().is<RequestedModuleObject>();
+}
+
+/* static */ bool
+GlobalObject::initRequestedModuleProto(JSContext* cx, Handle<GlobalObject*> global)
+{
+ static const JSPropertySpec protoAccessors[] = {
+ JS_PSG("moduleSpecifier", RequestedModuleObject_moduleSpecifierGetter, 0),
+ JS_PSG("lineNumber", RequestedModuleObject_lineNumberGetter, 0),
+ JS_PSG("columnNumber", RequestedModuleObject_columnNumberGetter, 0),
+ JS_PS_END
+ };
+
+ RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
+ if (!proto)
+ return false;
+
+ if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
+ return false;
+
+ global->initReservedSlot(REQUESTED_MODULE_PROTO, ObjectValue(*proto));
+ return true;
+}
+
+/* static */ RequestedModuleObject*
+RequestedModuleObject::create(JSContext* cx,
+ HandleAtom moduleSpecifier,
+ uint32_t lineNumber,
+ uint32_t columnNumber)
+{
+ MOZ_ASSERT(lineNumber > 0);
+
+ RootedObject proto(cx, cx->global()->getRequestedModulePrototype());
+ RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
+ if (!obj)
+ return nullptr;
+
+ RootedRequestedModuleObject self(cx, &obj->as<RequestedModuleObject>());
+ self->initReservedSlot(ModuleSpecifierSlot, StringValue(moduleSpecifier));
+ self->initReservedSlot(LineNumberSlot, Int32Value(lineNumber));
+ self->initReservedSlot(ColumnNumberSlot, Int32Value(columnNumber));
+ return self;
+}
+
+///////////////////////////////////////////////////////////////////////////
// IndirectBindingMap
IndirectBindingMap::Binding::Binding(ModuleEnvironmentObject* environment, Shape* shape)
@@ -1074,7 +1139,8 @@ ModuleBuilder::ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
: cx_(cx),
module_(cx, module),
tokenStream_(tokenStream),
- requestedModules_(cx, AtomVector(cx)),
+ requestedModuleSpecifiers_(cx, AtomSet(cx)),
+ requestedModules_(cx, RequestedModuleVector(cx)),
importedBoundNames_(cx, AtomVector(cx)),
importEntries_(cx, ImportEntryVector(cx)),
exportEntries_(cx, ExportEntryVector(cx)),
@@ -1084,6 +1150,12 @@ ModuleBuilder::ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
{}
bool
+ModuleBuilder::init()
+{
+ return requestedModuleSpecifiers_.init();
+}
+
+bool
ModuleBuilder::buildTables()
{
for (const auto& e : exportEntries_) {
@@ -1130,24 +1202,23 @@ ModuleBuilder::buildTables()
bool
ModuleBuilder::initModule()
{
- RootedArrayObject requestedModules(cx_, createArray<JSAtom*>(requestedModules_));
+ RootedArrayObject requestedModules(cx_, createArray(requestedModules_));
if (!requestedModules)
return false;
- RootedArrayObject importEntries(cx_, createArray<ImportEntryObject*>(importEntries_));
+ RootedArrayObject importEntries(cx_, createArray(importEntries_));
if (!importEntries)
return false;
- RootedArrayObject localExportEntries(cx_, createArray<ExportEntryObject*>(localExportEntries_));
+ RootedArrayObject localExportEntries(cx_, createArray(localExportEntries_));
if (!localExportEntries)
return false;
- RootedArrayObject indirectExportEntries(cx_);
- indirectExportEntries = createArray<ExportEntryObject*>(indirectExportEntries_);
+ RootedArrayObject indirectExportEntries(cx_, createArray(indirectExportEntries_));
if (!indirectExportEntries)
return false;
- RootedArrayObject starExportEntries(cx_, createArray<ExportEntryObject*>(starExportEntries_));
+ RootedArrayObject starExportEntries(cx_, createArray(starExportEntries_));
if (!starExportEntries)
return false;
@@ -1169,7 +1240,7 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
RootedAtom module(cx_, pn->pn_right->pn_atom);
- if (!maybeAppendRequestedModule(module))
+ if (!maybeAppendRequestedModule(module, pn->pn_right))
return false;
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
@@ -1277,7 +1348,7 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
RootedAtom module(cx_, pn->pn_right->pn_atom);
- if (!maybeAppendRequestedModule(module))
+ if (!maybeAppendRequestedModule(module, pn->pn_right))
return false;
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
@@ -1346,29 +1417,26 @@ ModuleBuilder::appendExportFromEntry(HandleAtom exportName, HandleAtom moduleReq
}
bool
-ModuleBuilder::maybeAppendRequestedModule(HandleAtom module)
+ModuleBuilder::maybeAppendRequestedModule(HandleAtom specifier, ParseNode* node)
{
- for (auto m : requestedModules_) {
- if (m == module)
- return true;
+ if (requestedModuleSpecifiers_.has(specifier)) {
+ return true;
}
- return requestedModules_.append(module);
-}
-
-static Value
-MakeElementValue(JSString *string)
-{
- return StringValue(string);
-}
-
-static Value
-MakeElementValue(JSObject *object)
-{
- return ObjectValue(*object);
+ uint32_t line;
+ uint32_t column;
+ tokenStream_.srcCoords.lineNumAndColumnIndex(node->pn_pos.begin, &line, &column);
+ JSContext* cx = reinterpret_cast<JSContext*>(cx_);
+ RootedRequestedModuleObject req(cx, RequestedModuleObject::create(cx, specifier, line, column));
+ if (!req) {
+ return false;
+ }
+ return FreezeObject(cx, req) &&
+ requestedModules_.append(req) &&
+ requestedModuleSpecifiers_.put(specifier);
}
template <typename T>
-ArrayObject* ModuleBuilder::createArray(const GCVector<T>& vector)
+ArrayObject* ModuleBuilder::createArray(const JS::Rooted<GCVector<T>>& vector)
{
uint32_t length = vector.length();
RootedArrayObject array(cx_, NewDenseFullyAllocatedArray(cx_, length));
@@ -1377,7 +1445,7 @@ ArrayObject* ModuleBuilder::createArray(const GCVector<T>& vector)
array->setDenseInitializedLength(length);
for (uint32_t i = 0; i < length; i++)
- array->initDenseElement(i, MakeElementValue(vector[i]));
+ array->initDenseElement(i, ObjectValue(*vector[i]));
return array;
}
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index dc078e6b28..fde02c6938 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -100,6 +100,32 @@ class ExportEntryObject : public NativeObject
typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
typedef Handle<ExportEntryObject*> HandleExportEntryObject;
+class RequestedModuleObject : public NativeObject
+{
+ public:
+ enum
+ {
+ ModuleSpecifierSlot = 0,
+ LineNumberSlot,
+ ColumnNumberSlot,
+ SlotCount
+ };
+
+ static const Class class_;
+ static JSObject* initClass(JSContext* cx, HandleObject obj);
+ static bool isInstance(HandleValue value);
+ static RequestedModuleObject* create(JSContext* cx,
+ HandleAtom moduleSpecifier,
+ uint32_t lineNumber,
+ uint32_t columnNumber);
+ JSAtom* moduleSpecifier() const;
+ uint32_t lineNumber() const;
+ uint32_t columnNumber() const;
+};
+
+typedef Rooted<RequestedModuleObject*> RootedRequestedModuleObject;
+typedef Handle<RequestedModuleObject*> HandleRequestedModuleObject;
+
class IndirectBindingMap
{
public:
@@ -318,6 +344,8 @@ class MOZ_STACK_CLASS ModuleBuilder
explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
const frontend::TokenStream& tokenStream);
+ bool init();
+
bool processImport(frontend::ParseNode* pn);
bool processExport(frontend::ParseNode* pn);
bool processExportFrom(frontend::ParseNode* pn);
@@ -334,15 +362,20 @@ class MOZ_STACK_CLASS ModuleBuilder
private:
using AtomVector = GCVector<JSAtom*>;
- using RootedAtomVector = JS::Rooted<AtomVector>;
using ImportEntryVector = GCVector<ImportEntryObject*>;
+ using RequestedModuleVector = GCVector<RequestedModuleObject*>;
+ using AtomSet = JS::GCHashSet<JSAtom*>;
+ using RootedAtomVector = JS::Rooted<AtomVector>;
using RootedImportEntryVector = JS::Rooted<ImportEntryVector>;
using RootedExportEntryVector = JS::Rooted<ExportEntryVector>;
+ using RootedRequestedModuleVector = JS::Rooted<RequestedModuleVector>;
+ using RootedAtomSet = JS::Rooted<AtomSet>;
ExclusiveContext* cx_;
RootedModuleObject module_;
const frontend::TokenStream& tokenStream_;
- RootedAtomVector requestedModules_;
+ RootedAtomSet requestedModuleSpecifiers_;
+ RootedRequestedModuleVector requestedModules_;
RootedAtomVector importedBoundNames_;
RootedImportEntryVector importEntries_;
RootedExportEntryVector exportEntries_;
@@ -357,10 +390,10 @@ class MOZ_STACK_CLASS ModuleBuilder
bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
HandleAtom importName, frontend::ParseNode* node);
- bool maybeAppendRequestedModule(HandleAtom module);
+ bool maybeAppendRequestedModule(HandleAtom specifier, frontend::ParseNode* node);
template <typename T>
- ArrayObject* createArray(const GCVector<T>& vector);
+ ArrayObject* createArray(const JS::Rooted<GCVector<T>>& vector);
};
} // namespace js
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 65bd16b270..ac69abab91 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3741,6 +3741,9 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
return false;
ModuleBuilder builder(cx, module, parser.tokenStream);
+ if (!builder.init())
+ return false;
+
ModuleSharedContext modulesc(cx, module, &cx->global()->emptyGlobalScope(), builder);
pn = parser.moduleBody(&modulesc);
if (!pn)
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index 6dc837eb3b..2c01b5a9f2 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -405,6 +405,9 @@ BytecodeCompiler::compileModule()
module->init(script);
ModuleBuilder builder(cx, module, parser->tokenStream);
+ if (!builder.init())
+ return nullptr;
+
ModuleSharedContext modulesc(cx, module, enclosingScope, builder);
ParseNode* pn = parser->moduleBody(&modulesc);
if (!pn)
diff --git a/js/src/gc/Policy.h b/js/src/gc/Policy.h
index 451dac1194..ba59336a52 100644
--- a/js/src/gc/Policy.h
+++ b/js/src/gc/Policy.h
@@ -46,6 +46,7 @@ class RegExpObject;
class SavedFrame;
class Scope;
class EnvironmentObject;
+class RequestedModuleObject;
class ScriptSourceObject;
class Shape;
class SharedArrayBufferObject;
@@ -84,6 +85,7 @@ class JitCode;
D(js::PlainObject*) \
D(js::PropertyName*) \
D(js::RegExpObject*) \
+ D(js::RequestedModuleObject*) \
D(js::SavedFrame*) \
D(js::Scope*) \
D(js::ScriptSourceObject*) \
diff --git a/js/src/jit-test/tests/modules/requested-modules.js b/js/src/jit-test/tests/modules/requested-modules.js
index ee572d12e3..acf58e5a6e 100644
--- a/js/src/jit-test/tests/modules/requested-modules.js
+++ b/js/src/jit-test/tests/modules/requested-modules.js
@@ -5,7 +5,7 @@ function testRequestedModules(source, expected) {
var actual = module.requestedModules;
assertEq(actual.length, expected.length);
for (var i = 0; i < actual.length; i++) {
- assertEq(actual[i], expected[i]);
+ assertEq(actual[i].moduleSpecifier, expected[i]);
}
}
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index dab4c25a43..4fb33464a6 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4729,13 +4729,28 @@ JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg)
return &moduleArg->as<ModuleObject>().requestedModules();
}
-JS_PUBLIC_API(JSScript*)
-JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
+JS_PUBLIC_API(JSString*)
+JS::GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue value)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
- assertSameCompartment(cx, moduleArg);
- return moduleArg->as<ModuleObject>().script();
+ assertSameCompartment(cx, value);
+ JSObject* obj = &value.toObject();
+ return obj->as<RequestedModuleObject>().moduleSpecifier();
+}
+
+JS_PUBLIC_API(void)
+JS::GetRequestedModuleSourcePos(JSContext* cx, JS::HandleValue value,
+ uint32_t* lineNumber, uint32_t* columnNumber)
+{
+ AssertHeapIsIdle(cx);
+ CHECK_REQUEST(cx);
+ assertSameCompartment(cx, value);
+ MOZ_ASSERT(lineNumber);
+ MOZ_ASSERT(columnNumber);
+ auto& requested = value.toObject().as<RequestedModuleObject>();
+ *lineNumber = requested.lineNumber();
+ *columnNumber = requested.columnNumber();
}
JS_PUBLIC_API(JSObject*)
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index f8203ee1fd..7d151fdb10 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4386,18 +4386,27 @@ ModuleEvaluate(JSContext* cx, JS::HandleObject moduleRecord);
* Get a list of the module specifiers used by a source text module
* record to request importation of modules.
*
- * The result is a JavaScript array of string values. To extract the individual
- * values use only JS_GetArrayLength and JS_GetElement with indices 0 to
- * length - 1.
+ * The result is a JavaScript array of object values. To extract the individual
+ * values use only JS_GetArrayLength and JS_GetElement with indices 0 to length
+ * - 1.
+ *
+ * The element values are objects with the following properties:
+ * - moduleSpecifier: the module specifier string
+ * - lineNumber: the line number of the import in the source text
+ * - columnNumber: the column number of the import in the source text
+ *
+ * These property values can be extracted with GetRequestedModuleSpecifier() and
+ * GetRequestedModuleSourcePos()
*/
extern JS_PUBLIC_API(JSObject*)
GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
-/*
- * Get the script associated with a module.
- */
-extern JS_PUBLIC_API(JSScript*)
-GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
+extern JS_PUBLIC_API(JSString*)
+GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue requestedModuleObject);
+
+extern JS_PUBLIC_API(void)
+GetRequestedModuleSourcePos(JSContext* cx, JS::HandleValue requestedModuleObject,
+ uint32_t* lineNumber, uint32_t* columnNumber);
} /* namespace JS */
diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h
index 011f90aa16..865f5e5ece 100644
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -112,6 +112,7 @@ class GlobalObject : public NativeObject
MODULE_PROTO,
IMPORT_ENTRY_PROTO,
EXPORT_ENTRY_PROTO,
+ REQUESTED_MODULE_PROTO,
REGEXP_STATICS,
WARNED_ONCE_FLAGS,
RUNTIME_CODEGEN_ENABLED,
@@ -524,6 +525,11 @@ class GlobalObject : public NativeObject
return value.isUndefined() ? nullptr : &value.toObject();
}
+ JSObject* maybeGetRequestedModulePrototype() {
+ Value value = getSlot(REQUESTED_MODULE_PROTO);
+ return value.isUndefined() ? nullptr : &value.toObject();
+ }
+
JSObject* getModulePrototype() {
JSObject* proto = maybeGetModulePrototype();
MOZ_ASSERT(proto);
@@ -542,6 +548,12 @@ class GlobalObject : public NativeObject
return proto;
}
+ JSObject* getRequestedModulePrototype() {
+ JSObject* proto = maybeGetRequestedModulePrototype();
+ MOZ_ASSERT(proto);
+ return proto;
+ }
+
static JSFunction*
getOrCreateTypedArrayConstructor(JSContext* cx, Handle<GlobalObject*> global) {
if (!ensureConstructor(cx, global, JSProto_TypedArray))
@@ -831,6 +843,7 @@ class GlobalObject : public NativeObject
static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
+ static bool initRequestedModuleProto(JSContext* cx, Handle<GlobalObject*> global);
// Implemented in builtin/TypedObject.cpp
static bool initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global);