Skip to content

Commit

Permalink
test(ses): Coverage for module source validation
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Aug 27, 2024
1 parent 35636d9 commit f7d19b7
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 14 deletions.
14 changes: 6 additions & 8 deletions packages/ses/src/module-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,27 @@ function mayBeVirtualModuleSource(moduleSource) {
function validateVirtualModuleSource(moduleSource, moduleSpecifier) {
const { exports } = moduleSource;
isArray(exports) ||
Fail`Property 'exports' of a third-party module source must be an array, got ${q(
Fail`Invalid module source: 'exports' of a virtual module source must be an array, got ${q(
exports,
)}, for module ${q(moduleSpecifier)}`;
}

function validateModuleSource(moduleSource, moduleSpecifier) {
isObject(moduleSource) ||
Fail`Module sources must be of type object, got ${q(
Fail`Invalid module source: must be of type object, got ${q(
moduleSource,
)}, for module ${q(moduleSpecifier)}`;
const { imports, exports, reexports = [] } = moduleSource;
isArray(imports) ||
Fail`Property 'imports' of a module source must be an array, got ${q(
Fail`Invalid module source: 'imports' must be an array, got ${q(
imports,
)}, for module ${q(moduleSpecifier)}`;
isArray(exports) ||
Fail`Property 'exports' of a precompiled module source must be an array, got ${q(
Fail`Invalid module source: 'exports' must be an array, got ${q(
exports,
)}, for module ${q(moduleSpecifier)}`;
isArray(reexports) ||
Fail`Property 'reexports' of a precompiled module source must be an array if present, got ${q(
Fail`Invalid module source: 'reexports' must be an array if present, got ${q(
reexports,
)}, for module ${q(moduleSpecifier)}`;
}
Expand Down Expand Up @@ -138,9 +138,7 @@ export const instantiate = (
resolvedImports,
);
} else {
throw TypeError(
`importHook must provide a module source, got ${q(moduleSource)}`,
);
throw TypeError(`Invalid module source, got ${q(moduleSource)}`);
}

// Memoize.
Expand Down
23 changes: 17 additions & 6 deletions packages/ses/src/module-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import {
arrayJoin,
arrayMap,
arrayPush,
arraySome,
create,
freeze,
generatorNext,
generatorThrow,
getOwnPropertyNames,
isArray,
isObject,
mapGet,
mapHas,
Expand Down Expand Up @@ -85,14 +87,23 @@ const loadModuleSource = (
moduleLoads,
importMeta,
) => {
const { resolveHook } = weakmapGet(compartmentPrivateFields, compartment);
const { resolveHook, name: compartmentName } = weakmapGet(
compartmentPrivateFields,
compartment,
);

const { imports } = moduleSource;
if (
!isArray(imports) ||
arraySome(imports, specifier => typeof specifier !== 'string')
) {
throw makeError(
X`Invalid module source: 'imports' must be an array of strings, got ${imports} for module ${q(moduleSpecifier)} of compartment ${q(compartmentName)}`,
);
}

// resolve all imports relative to this referrer module.
const resolvedImports = resolveAll(
moduleSource.imports,
resolveHook,
moduleSpecifier,
);
const resolvedImports = resolveAll(imports, resolveHook, moduleSpecifier);
const moduleRecord = freeze({
compartment,
moduleSource,
Expand Down
71 changes: 71 additions & 0 deletions packages/ses/test/module-map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,77 @@ test('module map primed with module source descriptor with virtual module source
t.is(index.default, 42);
});

test('module map primed with module source descriptor with no-imports virtual module source', async t => {
const compartment = new Compartment({
modules: {
'./index.js': {
source: {},
},
},
resolveHook: specifier => specifier,
__noNamespaceBox__: true,
__options__: true,
});
await t.throwsAsync(() => compartment.import('./index.js'), {
message: /Invalid module source: 'imports' must be an array/,
});
});

test('module map primed with module source descriptor with imports-with-non-string virtual module source', async t => {
const compartment = new Compartment({
modules: {
'./index.js': {
source: {
imports: [1],
},
},
},
resolveHook: specifier => specifier,
__noNamespaceBox__: true,
__options__: true,
});
await t.throwsAsync(() => compartment.import('./index.js'), {
message: /Invalid module source: 'imports' must be an array of strings/,
});
});

test('module map primed with module source descriptor with no-exports virtual module source', async t => {
const compartment = new Compartment({
modules: {
'./index.js': {
source: {
imports: [],
},
},
},
resolveHook: specifier => specifier,
__noNamespaceBox__: true,
__options__: true,
});
await t.throwsAsync(() => compartment.import('./index.js'), {
message: /Invalid module source: 'exports' must be an array/,
});
});

test('module map primed with module source descriptor with no-execute virtual module source', async t => {
const compartment = new Compartment({
modules: {
'./index.js': {
source: {
imports: [],
exports: [],
},
},
},
resolveHook: specifier => specifier,
__noNamespaceBox__: true,
__options__: true,
});
await t.throwsAsync(() => compartment.import('./index.js'), {
message: /Invalid module source/,
});
});

test('module map primed with parent compartment module source descriptor with string reference to parent compartment', async t => {
const parent = new Compartment({
modules: {
Expand Down

0 comments on commit f7d19b7

Please sign in to comment.