mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 04:07:44 +00:00
LibJS: Follow the spec with storing im- and export entries
Because we can have arbitrary in- and export names with strings we can have '*' and '' which means using '*' as an indicating namespace imports failed / behaved incorrectly for string imports '*'. We now use more specific types to indicate these special states instead of these 'magic' string values. Do note that 'default' is not actually a magic string value but one specified by the spec. And you can in fact export the default value by doing: `export { 1 as default }`.
This commit is contained in:
parent
8473f6caee
commit
e0e4ead2c8
11 changed files with 190 additions and 96 deletions
|
@ -1,25 +1,22 @@
|
|||
// Because you can't easily load modules directly we load them via here and check
|
||||
// if they passed by checking the result
|
||||
|
||||
function expectModulePassed(filename) {
|
||||
function validTestModule(filename) {
|
||||
if (!filename.endsWith(".mjs") || !filename.startsWith("./")) {
|
||||
throw new ExpectationError(
|
||||
"Expected module name to start with './' " +
|
||||
"and end with '.mjs' but got '" +
|
||||
filename +
|
||||
"'"
|
||||
`Expected module name to start with './' and end with '.mjs' but got '${filename}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function getModule() {
|
||||
return import(filename);
|
||||
}
|
||||
function expectModulePassed(filename) {
|
||||
validTestModule(filename);
|
||||
|
||||
let moduleLoaded = false;
|
||||
let moduleResult = null;
|
||||
let thrownError = null;
|
||||
|
||||
getModule()
|
||||
import(filename)
|
||||
.then(result => {
|
||||
moduleLoaded = true;
|
||||
moduleResult = result;
|
||||
|
@ -36,10 +33,36 @@ function expectModulePassed(filename) {
|
|||
}
|
||||
|
||||
expect(moduleLoaded).toBeTrue();
|
||||
|
||||
return moduleResult;
|
||||
}
|
||||
|
||||
function expectedModuleToThrowSyntaxError(filename, message) {
|
||||
validTestModule(filename);
|
||||
|
||||
let moduleLoaded = false;
|
||||
let thrownError = null;
|
||||
|
||||
import(filename)
|
||||
.then(() => {
|
||||
moduleLoaded = true;
|
||||
})
|
||||
.catch(error => {
|
||||
thrownError = error;
|
||||
});
|
||||
|
||||
runQueuedPromiseJobs();
|
||||
|
||||
if (thrownError) {
|
||||
expect(() => {
|
||||
throw thrownError;
|
||||
}).toThrowWithMessage(SyntaxError, message);
|
||||
} else {
|
||||
throw new ExpectationError(
|
||||
`Expected module: '${filename}' to fail to load with a syntax error but did not throw.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe("testing behavior", () => {
|
||||
// To ensure the other tests are interpreter correctly we first test the underlying
|
||||
// mechanisms so these tests don't use expectModulePassed.
|
||||
|
@ -131,6 +154,25 @@ describe("in- and exports", () => {
|
|||
test("declaration exports which can be used in the module it self", () => {
|
||||
expectModulePassed("./declarations-tests.mjs");
|
||||
});
|
||||
|
||||
test("string '*' is not a full namespace import", () => {
|
||||
expectModulePassed("./string-import-names.mjs");
|
||||
});
|
||||
|
||||
test("can combine string and default exports", () => {
|
||||
expectModulePassed("./string-import-namespace.mjs");
|
||||
});
|
||||
|
||||
test("can re export string names", () => {
|
||||
expectModulePassed("./string-import-namespace-indirect.mjs");
|
||||
});
|
||||
|
||||
test("re exporting all-but-default does not export a default value", () => {
|
||||
expectedModuleToThrowSyntaxError(
|
||||
"./indirect-export-without-default.mjs",
|
||||
"Invalid or ambiguous export entry 'default'"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loops", () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue