Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @oncall react_native
*/

import type {Dependency} from 'metro/private/ModuleGraph/worker/collectDependencies';

Check warning on line 12 in packages/metro-transform-plugins/src/__tests__/import-export-plugin-test.js

View workflow job for this annotation

GitHub Actions / Type check, lint, smoke test

Requires should be sorted alphabetically, with at least one line between imports/requires and code

import collectDependencies from 'metro/private/ModuleGraph/worker/collectDependencies';

Expand Down Expand Up @@ -325,7 +325,7 @@
const expected = `
Object.defineProperty(exports, '__esModule', {value: true});

var _bar = require("bar");
var _bar = require('bar');

for (var _key in _bar) {
exports[_key] = _bar[_key];
Expand Down Expand Up @@ -373,17 +373,17 @@
const expected = `
Object.defineProperty(exports, '__esModule', {value: true});

var _baz = require('bar').baz;
const bax = 'bax';

var _default = bax;

var _foo = require("foo");
var _foo = require('foo');

for (var _key in _foo) {
exports[_key] = _foo[_key];
}

var _baz = require('bar').baz;
const bax = 'bax';

var _default = bax;

exports.baz = _baz;
exports.default = _default;
`;
Expand Down Expand Up @@ -425,6 +425,35 @@
expect(context.exports.sourceOnly).toBe('source only');
});

test('re-export dependencies evaluate before module body at runtime', () => {
const transformedCode = generate(
transformToAst(
[importExportPlugin],
`
events.push('body');
export {value} from 'foo';
export * from 'bar';
`,
opts,
),
).code;
const events = [];
const context = {
events,
exports: {} as {[string]: unknown},
require: (id: string) => {
events.push(`require ${id}`);
return id === 'foo' ? {value: 'foo value'} : {star: 'bar star'};
},
};

vm.runInNewContext(transformedCode, context);

expect(events).toEqual(['require foo', 'require bar', 'body']);
expect(context.exports.value).toBe('foo value');
expect(context.exports.star).toBe('bar star');
});

test('enables module exporting when something is exported', () => {
const code = `
foo();
Expand Down
59 changes: 26 additions & 33 deletions packages/metro-transform-plugins/src/import-export-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,23 @@ export default function importExportPlugin({
path: NodePath<ExportAllDeclaration>,
state: State,
): void {
const loc = path.node.loc;
const file = path.node.source;

state.exportAll.push({
file: path.node.source.value,
loc: path.node.loc,
file: file.value,
loc,
});

withLocation(
exportAllTemplate({
FILE: resolvePath(t.cloneNode(file), state.opts.resolve),
REQUIRED: path.scope.generateUidIdentifier(file.value),
KEY: path.scope.generateUidIdentifier('key'),
}),
loc,
).forEach(node => state.imports.push({node}));

path.remove();
},

Expand Down Expand Up @@ -258,16 +270,16 @@ export default function importExportPlugin({
const source = nullthrows(path.node.source);
const temp = path.scope.generateUidIdentifier(remote.name);

path.insertBefore(
withLocation(
state.imports.push({
node: withLocation(
importTemplate({
IMPORT: t.cloneNode(state.importAll),
FILE: resolvePath(t.cloneNode(source), state.opts.resolve),
LOCAL: temp,
}),
loc,
),
);
});

state.exportNamed.push({
local: temp.name,
Expand All @@ -286,8 +298,8 @@ export default function importExportPlugin({
// $FlowFixMe[incompatible-type]
// $FlowFixMe[incompatible-use]
if (local.name === 'default') {
path.insertBefore(
withLocation(
state.imports.push({
node: withLocation(
importTemplate({
IMPORT: t.cloneNode(state.importDefault),
FILE: resolvePath(
Expand All @@ -298,16 +310,16 @@ export default function importExportPlugin({
}),
loc,
),
);
});

state.exportNamed.push({
local: temp.name,
remote: remote.name,
loc,
});
} else if (remote.name === 'default') {
path.insertBefore(
withLocation(
state.imports.push({
node: withLocation(
importNamedTemplate({
FILE: resolvePath(
t.cloneNode(nullthrows(path.node.source)),
Expand All @@ -318,12 +330,12 @@ export default function importExportPlugin({
}),
loc,
),
);
});

state.exportDefault.push({local: temp.name, loc});
} else {
path.insertBefore(
withLocation(
state.imports.push({
node: withLocation(
importNamedTemplate({
FILE: resolvePath(
t.cloneNode(nullthrows(path.node.source)),
Expand All @@ -334,7 +346,7 @@ export default function importExportPlugin({
}),
loc,
),
);
});

state.exportNamed.push({
local: temp.name,
Expand Down Expand Up @@ -522,25 +534,6 @@ export default function importExportPlugin({
body.unshift(e.node);
});

state.exportAll.forEach(
(e: {file: string, loc: ?SourceLocation, ...}) => {
body.push(
// $FlowFixMe[incompatible-call]
...withLocation(
exportAllTemplate({
FILE: resolvePath(
t.stringLiteral(e.file),
state.opts.resolve,
),
REQUIRED: path.scope.generateUidIdentifier(e.file),
KEY: path.scope.generateUidIdentifier('key'),
}),
e.loc,
),
);
},
);

state.exportNamed.forEach(
(e: {local: string, remote: string, loc: ?SourceLocation, ...}) => {
body.push(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Object {
"export-destructuring: ARRAY_REST",
],
"exportStarDefault": "export-star-overrides: DEFAULT",
"exportStarEvaluationOrder": Array [
"source module",
"barrel body",
],
"exportStarOverridden": "export-star-overrides: OVERRIDDEN",
"exportStarSourceOnly": "export-star-source: SOURCE_ONLY",
"foo": "export-null: FOO",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ test('builds a simple bundle', async () => {
expect(object.extraData.exportStarDefault).toBe(
'export-star-overrides: DEFAULT',
);
expect(object.extraData.exportStarEvaluationOrder).toEqual([
'source module',
'barrel body',
]);
expect(object.extraData.exportStarOverridden).toBe(
'export-star-overrides: OVERRIDDEN',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

export * from './export-star-source';

(global.__exportStarEvents || (global.__exportStarEvents = [])).push(
'barrel body',
);

export const evaluationOrder = global.__exportStarEvents;

export const overridden = 'export-star-overrides: OVERRIDDEN';

export default 'export-star-overrides: DEFAULT';
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

'use strict';

(global.__exportStarEvents || (global.__exportStarEvents = [])).push(
'source module',
);

export default 'export-star-source: DEFAULT';

export const overridden = 'export-star-source: OVERRIDDEN';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import primitiveDefault, {
foo as primitiveFoo,
} from './export-primitive-default';
import exportStarDefault, {
evaluationOrder as exportStarEvaluationOrder,
overridden as exportStarOverridden,
sourceOnly as exportStarSourceOnly,
} from './export-star-overrides';
Expand All @@ -39,6 +40,7 @@ export const extraData = {
arrayFirst,
arrayRest,
exportStarDefault,
exportStarEvaluationOrder,
exportStarOverridden,
exportStarSourceOnly,
foo,
Expand Down
Loading