-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(import-bundle): Test bundle format #2719 #2735
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,59 @@ export async function importBundle(bundle, options = {}, powers = {}) { | |
return namespace; | ||
} | ||
|
||
// The 'test' format is not generated by bundleSource and is not | ||
// serializable as JSON and is not passable because copy-records cannot have symbol keys. | ||
if (moduleFormat === 'test') { | ||
const exports = bundle[Symbol.for('exports')]; | ||
if (exports === undefined) { | ||
throw new Error( | ||
'Cannot import bundle with moduleFormat "test" that lacks an symbol-named property @exports and has likely been partially transported via JSON or eventual-send', | ||
); | ||
} | ||
|
||
// We emulate a module exports namespace object, which has certain invariants: | ||
// Property names are only strings, so we will ignore symbol-named properties. | ||
// All properties are enumerable, so we will ignore non-enumerable properties. | ||
// All properties should be writable, but we deliberately deviate rather than | ||
// emulate the exotic behavior of standard module exports namespace objects. | ||
// The namespace object is sealed. | ||
// Because we deviate from the standard behavior, the namespace object is | ||
// frozen by implication. | ||
// We capture the value for each property now and never again consult the given exports object. | ||
return Object.seal( | ||
Object.create( | ||
null, | ||
Object.fromEntries([ | ||
...Object.entries(Object.getOwnPropertyDescriptors(exports)) | ||
// eslint-disable-next-line no-nested-ternary | ||
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)) | ||
.filter( | ||
([name, descriptor]) => | ||
typeof name === 'string' && descriptor.enumerable, | ||
) | ||
.map(([name]) => [ | ||
name, | ||
{ | ||
value: exports[name], | ||
writable: false, | ||
enumerable: true, | ||
configurable: false, | ||
}, | ||
]), | ||
[ | ||
Symbol.toStringTag, | ||
{ | ||
value: 'Module', | ||
writable: false, | ||
enumerable: false, | ||
configurable: false, | ||
}, | ||
], | ||
]), | ||
), | ||
); | ||
} | ||
|
||
let { source } = bundle; | ||
const { sourceMap } = bundle; | ||
if (moduleFormat === 'getExport') { | ||
|
@@ -124,6 +177,23 @@ export async function importBundle(bundle, options = {}, powers = {}) { | |
} | ||
} | ||
|
||
/** | ||
* A utility function for producing test bundles, which are not serializable | ||
* as JSON or passable. | ||
* @param {Record<PropertyKey, unknown>} exports | ||
*/ | ||
export const bundleTestExports = exports => { | ||
const symbols = Object.getOwnPropertySymbols(exports).filter( | ||
name => name !== Symbol.toStringTag, | ||
); | ||
symbols.length > 0 && | ||
Fail`exports must not have symbol-named properties, got: ${symbols.map(String).join(', ')}`; | ||
return { | ||
moduleFormat: 'test', | ||
[Symbol.for('exports')]: exports, | ||
}; | ||
Comment on lines
+191
to
+194
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we freeze the object (not harden it since we don't care about the stability of exports at this point) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be a departure from the norm for |
||
}; | ||
|
||
/* | ||
importBundle(bundle, { metering: { getMeter, meteringOptions } }); | ||
importBundle(bundle, { transforms: [ meterTransform ], lexicals: { getMeter } }); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// A fixture for the sole purpose of verifying that a module exports namespace | ||
// is a suitable argument for bundleTestExports. | ||
export {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh interesting in French it's "ressemble"