Bug 1873610 - Part 2: Improve modules import/export error messages. r=jonco

Refactor the error message with the adding the information from the imported
module, for example:

// a.mjs
import { a } from "./b.mjs";

// b.mjs
const b = 1;

Originally the error message is "import not found: default", now it
becomes "The requested module: b.mjs doesn't provide an export named: a"

// c.mjs
import { c } from "./d.mjs";

// d.mjs
export * from "./d1.mjs";
export * from "./d2.mjs";

// d1.mjs
export const c = 1;

// d2.mjs
export const c = 2;

Originally the error message is "ambiguous import: c", now it becomes
"The requested module d.mjs contains ambiguous star export: c from
d1.mjs and d2.mjs"

Add another error message for circular import:

// e.mjs
export { e } from "f.mjs";

// f.mjs
export { e } from "e.mjs";

Originally it was "indirect export not found: e", now it is
"The request module: f.mjs contains circular import: e".

Differential Revision: https://phabricator.services.mozilla.com/D200345
This commit is contained in:
Yoshi Cheng-Hao Huang 2024-03-18 14:04:14 +00:00
parent ba055daed8
commit bf48a8b593
23 changed files with 225 additions and 103 deletions

View file

@ -295,3 +295,7 @@ browser/extensions/translations/extension/
# "scaffolding" used by uniffi which isn't valid JS in its original form. # "scaffolding" used by uniffi which isn't valid JS in its original form.
toolkit/components/uniffi-bindgen-gecko-js/src/templates/js/ toolkit/components/uniffi-bindgen-gecko-js/src/templates/js/
toolkit/components/uniffi-bindgen-gecko-js/components/generated/* toolkit/components/uniffi-bindgen-gecko-js/components/generated/*
# Test files for circular import in modules.
dom/base/test/jsmodules/import_circular.mjs
dom/base/test/jsmodules/import_circular_1.mjs

View file

@ -3,11 +3,21 @@ support-files = [
"ambiguous_export.mjs", "ambiguous_export.mjs",
"import_ambiguous.mjs", "import_ambiguous.mjs",
"import_ambiguous_indirect_export.mjs", "import_ambiguous_indirect_export.mjs",
"import_ambiguous_export.mjs",
"import_ambiguous_export_star.mjs",
"import_circular.mjs",
"import_circular_1.mjs",
"import_no_export.mjs", "import_no_export.mjs",
"import_no_indirect_export.mjs", "import_no_indirect_export.mjs",
"exportA1.mjs", "exportA1.mjs",
"exportA2.mjs", "exportA2.mjs",
"export_ambiguous.mjs", "export_ambiguous.mjs",
"export_star_ambiguous.mjs",
"module_a.mjs",
"module_b.mjs",
"module_c.mjs",
"module_d.mjs",
"module_e.mjs",
"module_setRan.mjs", "module_setRan.mjs",
"module_testSyntax.mjs", "module_testSyntax.mjs",
"module_badSyntax.mjs", "module_badSyntax.mjs",
@ -47,6 +57,8 @@ support-files = [
["test_import_errorMessage.html"] ["test_import_errorMessage.html"]
["test_import_errorMessage2.html"]
["test_import_meta_resolve.html"] ["test_import_meta_resolve.html"]
["test_importedModuleMemoization.html"] ["test_importedModuleMemoization.html"]

View file

@ -0,0 +1 @@
export * from "./ambiguous_export.mjs";

View file

@ -0,0 +1 @@
import { a } from "./ambiguous_export.mjs";

View file

@ -0,0 +1 @@
import { a } from "./export_star_ambiguous.mjs";

View file

@ -0,0 +1 @@
export { a } from "./import_circular_1.mjs";

View file

@ -0,0 +1 @@
export { a } from "./import_circular.mjs";

View file

@ -1 +1 @@
import x from "./no_export.mjs"; import { x } from "./no_export.mjs";

View file

@ -1,2 +1,2 @@
/* eslint-disable import/default */ /* eslint-disable import/default */
import x from "./no_indirect_export.mjs"; import { a } from "./no_indirect_export.mjs";

View file

@ -0,0 +1,2 @@
export var a = 1;
export var b = 2;

View file

@ -0,0 +1,2 @@
export var b = 3;
export var c = 4;

View file

@ -0,0 +1,3 @@
/* eslint-disable import/export */
export * from "./module_a.mjs";
export * from "./module_b.mjs";

View file

@ -0,0 +1 @@
import { a } from "./module_c.mjs";

View file

@ -0,0 +1 @@
import { b } from "./module_c.mjs";

View file

@ -8,40 +8,38 @@
let count = 0; let count = 0;
window.onerror = function (event, src, lineno, colno, error) { window.onerror = function (event, src, lineno, colno, error) {
info("window.onerror :" + error.message); info("window.onerror: message: " + error.message);
info("window.onerror: src: " + src);
ok(error instanceof SyntaxError, "Should be a SyntaxError."); ok(error instanceof SyntaxError, "Should be a SyntaxError.");
// import_no_indirect_export.mjs and import_ambiguous_indirect_export.mjs if (src.match("no_indirect_export.mjs") ||
// are related to indirect import/export. src.match("import_no_export.mjs")) {
if (count < 2) { ok(error.message.match("doesn't provide an export named"));
ok(error.message.match("indirect"), "Should contain 'indirect'"); } else if(src.match("export_ambiguous.mjs") ||
} src.match("import_ambiguous_export_star.mjs") ||
src.match("import_ambiguous_export.mjs") ||
// import_ambiguous_indirect_export.mjs and import_ambiguous.mjs both src.match("import_ambiguous.mjs")) {
// have ambiguous import/export. ok(error.message.match("contains ambiguous star export"));
if (count % 2 === 1) { } else if (src.match("import_circular_1.mjs")) {
ok(error.message.match("ambiguous"), "Should contain 'ambiguous'"); ok(error.message.match("contains circular import"));
} } else {
ok(false, "unknown src " + src);
if (count === 2) {
ok(!error.message.match("ambiguous") && !error.message.match("indirect"),
"Should NOT contain 'indirect' nor 'ambiguous'");
} }
count++; count++;
}; };
function testLoaded() { function testLoaded() {
ok(count === 4, "Should have 4 SynaxErrors thrown."); ok(count === 7, "Should have 7 SynaxErrors thrown.");
SimpleTest.finish(); SimpleTest.finish();
} }
</script> </script>
<!--
In window.onerror will test the error messages, so if the order is changed,
the code in window.onerror should be updated as well.
-->
<script type="module" src="import_no_indirect_export.mjs"></script> <script type="module" src="import_no_indirect_export.mjs"></script>
<script type="module" src="import_ambiguous_indirect_export.mjs"></script> <script type="module" src="import_ambiguous_indirect_export.mjs"></script>
<script type="module" src="import_ambiguous_export_star.mjs"></script>
<script type="module" src="import_ambiguous_export.mjs"></script>
<script type="module" src="import_no_export.mjs"></script> <script type="module" src="import_no_export.mjs"></script>
<script type="module" src="import_ambiguous.mjs"></script> <script type="module" src="import_ambiguous.mjs"></script>
<script type="module" src="import_circular.mjs"></script>
<body onload='testLoaded()'></body> <body onload='testLoaded()'></body>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test to get the filename of the requested module after it has been evaluated</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
SimpleTest.waitForExplicitFinish();
let count = 0;
window.onerror = function (event, src, lineno, colno, error) {
info("window.onerror: message: " + error.message);
info("window.onerror: src: " + src);
ok(error instanceof SyntaxError, "Should be a SyntaxError.");
if (src.match("module_e.mjs")) {
ok(error.message.match("contains ambiguous star export"));
} else {
ok(false, "unknown src " + src);
}
count++;
};
function testLoaded() {
ok(count === 1, "Should have 1 SynaxError thrown.");
SimpleTest.finish();
}
</script>
<!--module_c.mjs will be evaluated here-->
<script type="module" src="module_d.mjs"></script>
<!--module_c.mjs will be linked again here-->
<script type="module" src="module_e.mjs"></script>
<body onload='testLoaded()'></body>

View file

@ -714,10 +714,9 @@ MSG_DEF(JSMSG_CANT_DELETE_SUPER, 0, JSEXN_REFERENCEERR, "invalid delete involvin
MSG_DEF(JSMSG_REINIT_THIS, 0, JSEXN_REFERENCEERR, "super() called twice in derived class constructor") MSG_DEF(JSMSG_REINIT_THIS, 0, JSEXN_REFERENCEERR, "super() called twice in derived class constructor")
// Modules // Modules
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "indirect export not found") MSG_DEF(JSMSG_MODULE_NO_EXPORT, 2, JSEXN_SYNTAXERR, "The requested module '{0}' doesn't provide an export named: '{1}'")
MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "ambiguous indirect export") MSG_DEF(JSMSG_MODULE_CIRCULAR_IMPORT, 2, JSEXN_SYNTAXERR, "The requested module '{0}' contains circular import: '{1}'")
MSG_DEF(JSMSG_MISSING_IMPORT, 0, JSEXN_SYNTAXERR, "import not found") MSG_DEF(JSMSG_MODULE_AMBIGUOUS, 4, JSEXN_SYNTAXERR, "The requested module '{0}' contains ambiguous star export: '{1}' from '{2}' and '{3}'")
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 0, JSEXN_SYNTAXERR, "ambiguous import")
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found") MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
MSG_DEF(JSMSG_BAD_MODULE_STATUS, 1, JSEXN_INTERNALERR, "module record has unexpected status: {0}") MSG_DEF(JSMSG_BAD_MODULE_STATUS, 1, JSEXN_INTERNALERR, "module record has unexpected status: {0}")
MSG_DEF(JSMSG_DYNAMIC_IMPORT_FAILED, 1, JSEXN_TYPEERR, "error loading dynamically imported module: {0}") MSG_DEF(JSMSG_DYNAMIC_IMPORT_FAILED, 1, JSEXN_TYPEERR, "error loading dynamically imported module: {0}")

View file

@ -359,7 +359,8 @@ static ModuleObject* HostResolveImportedModule(
static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module, static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
Handle<JSAtom*> exportName, Handle<JSAtom*> exportName,
MutableHandle<ResolveSet> resolveSet, MutableHandle<ResolveSet> resolveSet,
MutableHandle<Value> result); MutableHandle<Value> result,
ModuleErrorInfo* errorInfoOut = nullptr);
static bool SyntheticModuleResolveExport(JSContext* cx, static bool SyntheticModuleResolveExport(JSContext* cx,
Handle<ModuleObject*> module, Handle<ModuleObject*> module,
Handle<JSAtom*> exportName, Handle<JSAtom*> exportName,
@ -577,7 +578,8 @@ static ModuleObject* HostResolveImportedModule(
// //
bool js::ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module, bool js::ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
Handle<JSAtom*> exportName, Handle<JSAtom*> exportName,
MutableHandle<Value> result) { MutableHandle<Value> result,
ModuleErrorInfo* errorInfoOut = nullptr) {
if (module->hasSyntheticModuleFields()) { if (module->hasSyntheticModuleFields()) {
return ::SyntheticModuleResolveExport(cx, module, exportName, result); return ::SyntheticModuleResolveExport(cx, module, exportName, result);
} }
@ -585,7 +587,8 @@ bool js::ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// Step 1. If resolveSet is not present, set resolveSet to a new empty List. // Step 1. If resolveSet is not present, set resolveSet to a new empty List.
Rooted<ResolveSet> resolveSet(cx); Rooted<ResolveSet> resolveSet(cx);
return ::ModuleResolveExport(cx, module, exportName, &resolveSet, result); return ::ModuleResolveExport(cx, module, exportName, &resolveSet, result,
errorInfoOut);
} }
static bool CreateResolvedBindingObject(JSContext* cx, static bool CreateResolvedBindingObject(JSContext* cx,
@ -605,7 +608,8 @@ static bool CreateResolvedBindingObject(JSContext* cx,
static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module, static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
Handle<JSAtom*> exportName, Handle<JSAtom*> exportName,
MutableHandle<ResolveSet> resolveSet, MutableHandle<ResolveSet> resolveSet,
MutableHandle<Value> result) { MutableHandle<Value> result,
ModuleErrorInfo* errorInfoOut) {
// Step 2. For each Record { [[Module]], [[ExportName]] } r of resolveSet, do: // Step 2. For each Record { [[Module]], [[ExportName]] } r of resolveSet, do:
for (const auto& entry : resolveSet) { for (const auto& entry : resolveSet) {
// Step 2.a. If module and r.[[Module]] are the same Module Record and // Step 2.a. If module and r.[[Module]] are the same Module Record and
@ -614,6 +618,9 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// Step 2.a.i. Assert: This is a circular import request. // Step 2.a.i. Assert: This is a circular import request.
// Step 2.a.ii. Return null. // Step 2.a.ii. Return null.
result.setNull(); result.setNull();
if (errorInfoOut) {
errorInfoOut->setCircularImport(cx, module);
}
return true; return true;
} }
} }
@ -669,8 +676,8 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// importedModule.ResolveExport(e.[[ImportName]], // importedModule.ResolveExport(e.[[ImportName]],
// resolveSet). // resolveSet).
name = e.importName(); name = e.importName();
return ModuleResolveExport(cx, importedModule, name, resolveSet, return ModuleResolveExport(cx, importedModule, name, resolveSet, result,
result); errorInfoOut);
} }
} }
} }
@ -683,6 +690,9 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// Step 6.c. NOTE: A default export cannot be provided by an export * from // Step 6.c. NOTE: A default export cannot be provided by an export * from
// "mod" declaration. // "mod" declaration.
result.setNull(); result.setNull();
if (errorInfoOut) {
errorInfoOut->setImportedModule(cx, module);
}
return true; return true;
} }
@ -705,7 +715,7 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// Step 8.b. Let resolution be ? importedModule.ResolveExport(exportName, // Step 8.b. Let resolution be ? importedModule.ResolveExport(exportName,
// resolveSet). // resolveSet).
if (!ModuleResolveExport(cx, importedModule, exportName, resolveSet, if (!ModuleResolveExport(cx, importedModule, exportName, resolveSet,
&resolution)) { &resolution, errorInfoOut)) {
return false; return false;
} }
@ -744,6 +754,12 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
if (binding->module() != starResolution->module() || if (binding->module() != starResolution->module() ||
binding->bindingName() != starResolution->bindingName()) { binding->bindingName() != starResolution->bindingName()) {
result.set(StringValue(cx->names().ambiguous)); result.set(StringValue(cx->names().ambiguous));
if (errorInfoOut) {
Rooted<ModuleObject*> module1(cx, starResolution->module());
Rooted<ModuleObject*> module2(cx, binding->module());
errorInfoOut->setForAmbiguousImport(cx, module, module1, module2);
}
return true; return true;
} }
} }
@ -752,6 +768,9 @@ static bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
// Step 9. Return starResolution. // Step 9. Return starResolution.
result.setObjectOrNull(starResolution); result.setObjectOrNull(starResolution);
if (!starResolution && errorInfoOut) {
errorInfoOut->setImportedModule(cx, module);
}
return true; return true;
} }
@ -923,63 +942,93 @@ static ModuleNamespaceObject* ModuleNamespaceCreate(
return ns; return ns;
} }
void ModuleErrorInfo::setImportedModule(JSContext* cx,
ModuleObject* importedModule) {
imported = importedModule->filename();
}
void ModuleErrorInfo::setCircularImport(JSContext* cx,
ModuleObject* importedModule) {
setImportedModule(cx, importedModule);
isCircular = true;
}
void ModuleErrorInfo::setForAmbiguousImport(JSContext* cx,
ModuleObject* importedModule,
ModuleObject* module1,
ModuleObject* module2) {
setImportedModule(cx, importedModule);
entry1 = module1->filename();
entry2 = module2->filename();
}
static void CreateErrorNumberMessageUTF8(JSContext* cx, unsigned errorNumber,
JSErrorReport* reportOut, ...) {
va_list ap;
va_start(ap, reportOut);
AutoReportFrontendContext fc(cx);
if (!ExpandErrorArgumentsVA(&fc, GetErrorMessage, nullptr, errorNumber,
ArgumentsAreUTF8, reportOut, ap)) {
ReportOutOfMemory(cx);
return;
}
va_end(ap);
}
static void ThrowResolutionError(JSContext* cx, Handle<ModuleObject*> module, static void ThrowResolutionError(JSContext* cx, Handle<ModuleObject*> module,
Handle<Value> resolution, bool isDirectImport, Handle<Value> resolution, Handle<JSAtom*> name,
Handle<JSAtom*> name, uint32_t line, ModuleErrorInfo* errorInfo) {
JS::ColumnNumberOneOrigin column) { MOZ_ASSERT(errorInfo);
MOZ_ASSERT(line != 0); auto chars = StringToNewUTF8CharsZ(cx, *name);
if (!chars) {
ReportOutOfMemory(cx);
return;
}
bool isAmbiguous = resolution == StringValue(cx->names().ambiguous); bool isAmbiguous = resolution == StringValue(cx->names().ambiguous);
// ErrorNumbers: unsigned errorNumber;
// | MISSING | AMBIGUOUS | if (errorInfo->isCircular) {
// ---------+---------+-----------+ errorNumber = JSMSG_MODULE_CIRCULAR_IMPORT;
// INDIRECT | } else if (isAmbiguous) {
// DIRECT | errorNumber = JSMSG_MODULE_AMBIGUOUS;
static constexpr unsigned ErrorNumbers[2][2] = {
{JSMSG_MISSING_INDIRECT_EXPORT, JSMSG_AMBIGUOUS_INDIRECT_EXPORT},
{JSMSG_MISSING_IMPORT, JSMSG_AMBIGUOUS_IMPORT}};
unsigned errorNumber = ErrorNumbers[isDirectImport][isAmbiguous];
const JSErrorFormatString* errorString =
GetErrorMessage(nullptr, errorNumber);
MOZ_ASSERT(errorString);
MOZ_ASSERT(errorString->argCount == 0);
Rooted<JSString*> message(cx, JS_NewStringCopyZ(cx, errorString->format));
if (!message) {
return;
}
Rooted<JSString*> separator(cx, JS_NewStringCopyZ(cx, ": "));
if (!separator) {
return;
}
message = ConcatStrings<CanGC>(cx, message, separator);
if (!message) {
return;
}
message = ConcatStrings<CanGC>(cx, message, name);
if (!message) {
return;
}
RootedString filename(cx);
if (const char* chars = module->script()->filename()) {
filename =
JS_NewStringCopyUTF8Z(cx, JS::ConstUTF8CharsZ(chars, strlen(chars)));
} else { } else {
filename = cx->names().empty_; errorNumber = JSMSG_MODULE_NO_EXPORT;
} }
JSErrorReport report;
report.isWarning_ = false;
report.errorNumber = errorNumber;
if (errorNumber == JSMSG_MODULE_AMBIGUOUS) {
CreateErrorNumberMessageUTF8(cx, errorNumber, &report, errorInfo->imported,
chars.get(), errorInfo->entry1,
errorInfo->entry2);
} else {
CreateErrorNumberMessageUTF8(cx, errorNumber, &report, errorInfo->imported,
chars.get());
}
Rooted<JSString*> message(cx, report.newMessageString(cx));
if (!message) {
ReportOutOfMemory(cx);
return;
}
const char* file = module->filename();
RootedString filename(
cx, JS_NewStringCopyUTF8Z(cx, JS::ConstUTF8CharsZ(file, strlen(file))));
if (!filename) { if (!filename) {
ReportOutOfMemory(cx);
return; return;
} }
RootedValue error(cx); RootedValue error(cx);
if (!JS::CreateError(cx, JSEXN_SYNTAXERR, nullptr, filename, line, column, if (!JS::CreateError(cx, JSEXN_SYNTAXERR, nullptr, filename,
nullptr, message, JS::NothingHandleValue, &error)) { errorInfo->lineNumber, errorInfo->columnNumber, nullptr,
message, JS::NothingHandleValue, &error)) {
ReportOutOfMemory(cx);
return; return;
} }
@ -1002,15 +1051,15 @@ bool js::ModuleInitializeEnvironment(JSContext* cx,
// Step 1.b. Let resolution be ? module.ResolveExport(e.[[ExportName]]). // Step 1.b. Let resolution be ? module.ResolveExport(e.[[ExportName]]).
exportName = e.exportName(); exportName = e.exportName();
if (!ModuleResolveExport(cx, module, exportName, &resolution)) { ModuleErrorInfo errorInfo{e.lineNumber(), e.columnNumber()};
if (!ModuleResolveExport(cx, module, exportName, &resolution, &errorInfo)) {
return false; return false;
} }
// Step 1.c. If resolution is either null or AMBIGUOUS, throw a SyntaxError // Step 1.c. If resolution is either null or AMBIGUOUS, throw a SyntaxError
// exception. // exception.
if (!IsResolvedBinding(cx, resolution)) { if (!IsResolvedBinding(cx, resolution)) {
ThrowResolutionError(cx, module, resolution, false, exportName, ThrowResolutionError(cx, module, resolution, exportName, &errorInfo);
e.lineNumber(), e.columnNumber());
return false; return false;
} }
} }
@ -1059,15 +1108,16 @@ bool js::ModuleInitializeEnvironment(JSContext* cx,
// Step 7.d. Else: // Step 7.d. Else:
// Step 7.d.i. Let resolution be ? // Step 7.d.i. Let resolution be ?
// importedModule.ResolveExport(in.[[ImportName]]). // importedModule.ResolveExport(in.[[ImportName]]).
if (!ModuleResolveExport(cx, importedModule, importName, &resolution)) { ModuleErrorInfo errorInfo{in.lineNumber(), in.columnNumber()};
if (!ModuleResolveExport(cx, importedModule, importName, &resolution,
&errorInfo)) {
return false; return false;
} }
// Step 7.d.ii. If resolution is null or ambiguous, throw a SyntaxError // Step 7.d.ii. If resolution is null or ambiguous, throw a SyntaxError
// exception. // exception.
if (!IsResolvedBinding(cx, resolution)) { if (!IsResolvedBinding(cx, resolution)) {
ThrowResolutionError(cx, module, resolution, true, importName, ThrowResolutionError(cx, module, resolution, importName, &errorInfo);
in.lineNumber(), in.columnNumber());
return false; return false;
} }

View file

@ -20,9 +20,34 @@ namespace js {
using ModuleVector = GCVector<ModuleObject*, 0, SystemAllocPolicy>; using ModuleVector = GCVector<ModuleObject*, 0, SystemAllocPolicy>;
// A struct with detailed error information when import/export failed.
struct ModuleErrorInfo {
ModuleErrorInfo(uint32_t lineNumber_, JS::ColumnNumberOneOrigin columnNumber_)
: lineNumber(lineNumber_), columnNumber(columnNumber_) {}
void setImportedModule(JSContext* cx, ModuleObject* importedModule);
void setCircularImport(JSContext* cx, ModuleObject* importedModule);
void setForAmbiguousImport(JSContext* cx, ModuleObject* importedModule,
ModuleObject* module1, ModuleObject* module2);
uint32_t lineNumber;
JS::ColumnNumberOneOrigin columnNumber;
// The filename of the imported module.
const char* imported;
// The filenames of the ambiguous entries.
const char* entry1;
const char* entry2;
// A bool to indicate the error is a circular import when it's true.
bool isCircular = false;
};
bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module, bool ModuleResolveExport(JSContext* cx, Handle<ModuleObject*> module,
Handle<JSAtom*> exportName, Handle<JSAtom*> exportName,
MutableHandle<Value> result); MutableHandle<Value> result,
ModuleErrorInfo* errorInfoOut);
ModuleNamespaceObject* GetOrCreateModuleNamespace(JSContext* cx, ModuleNamespaceObject* GetOrCreateModuleNamespace(JSContext* cx,
Handle<ModuleObject*> module); Handle<ModuleObject*> module);

View file

@ -204,7 +204,7 @@ ChromeUtils.importESModule("resource://test/es6module_import_error.js", {
`, sb); `, sb);
} catch (e) { } catch (e) {
caught = true; caught = true;
Assert.stringMatches(e.message, /import not found/); Assert.stringMatches(e.message, /doesn't provide an export named/);
} }
Assert.ok(caught); Assert.ok(caught);
}); });

View file

@ -1,5 +0,0 @@
[instantiation-error-3.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test that unresolvable cycles lead to SyntaxError events on window and load events on script]
expected: FAIL

View file

@ -1,5 +0,0 @@
[instantiation-error-4.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test that loading a graph in which a module is already errored results in an error.]
expected: FAIL

View file

@ -1,5 +0,0 @@
[instantiation-error-5.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test that loading a graph in which a module is already errored results an error.]
expected: FAIL