diff options
author | Moonchild <moonchild@palemoon.org> | 2020-11-28 10:17:43 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2020-11-28 10:17:43 +0000 |
commit | e6b9d9cbeae7d90a7f368517c67775c0d72c6445 (patch) | |
tree | b10c4075973d3949a47d60becd9db46b8e505fe4 | |
parent | b863bd2edc94c16498edc3274531f57fbfc30d3f (diff) | |
download | uxp-e6b9d9cbeae7d90a7f368517c67775c0d72c6445.tar.gz |
Issue #1624 - Add missing error handling and bail on null specifier.modulefix
-rw-r--r-- | dom/script/ScriptLoader.cpp | 65 | ||||
-rw-r--r-- | js/public/Class.h | 2 | ||||
-rw-r--r-- | js/src/builtin/Module.js | 4 | ||||
-rw-r--r-- | js/src/builtin/ModuleObject.cpp | 128 | ||||
-rw-r--r-- | js/src/builtin/ModuleObject.h | 41 | ||||
-rw-r--r-- | js/src/builtin/ReflectParse.cpp | 3 | ||||
-rw-r--r-- | js/src/frontend/BytecodeCompiler.cpp | 3 | ||||
-rw-r--r-- | js/src/gc/Policy.h | 2 | ||||
-rw-r--r-- | js/src/jit-test/tests/modules/requested-modules.js | 2 | ||||
-rw-r--r-- | js/src/jsapi.cpp | 23 | ||||
-rw-r--r-- | js/src/jsapi.h | 25 | ||||
-rw-r--r-- | js/src/vm/GlobalObject.h | 13 |
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); |