Skip to content

Commit

Permalink
Implement constantReexports and enumerableModuleMeta assumptions (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Jan 24, 2021
1 parent db4ed59 commit 5323795
Show file tree
Hide file tree
Showing 60 changed files with 473 additions and 41 deletions.
2 changes: 2 additions & 0 deletions packages/babel-core/src/config/validation/options.js
Expand Up @@ -333,6 +333,8 @@ export type NestingPath = RootPath | OverridesPath | EnvPath;

export const assumptionsNames = new Set<string>([
"arrayLikeIsIterable",
"constantReexports",
"enumerableModuleMeta",
"ignoreFunctionLength",
"ignoreToPrimitiveHint",
"iterableIsArray",
Expand Down
49 changes: 28 additions & 21 deletions packages/babel-helper-module-transforms/src/index.js
Expand Up @@ -27,22 +27,27 @@ export { hasExports, isSideEffectImport, isModule, rewriteThis };
export function rewriteModuleStatementsAndPrepareHeader(
path: NodePath,
{
// TODO(Babel 8): Remove this
loose,

exportName,
strict,
allowTopLevelThis,
strictMode,
loose,
noInterop,
lazy,
esNamespaceOnly,

constantReexports = loose,
enumerableModuleMeta = loose,
},
) {
assert(isModule(path), "Cannot process module statements in a script");
path.node.sourceType = "script";

const meta = normalizeAndLoadModuleMetadata(path, exportName, {
noInterop,
loose,
initializeReexports: constantReexports,
lazy,
esNamespaceOnly,
});
Expand All @@ -67,7 +72,7 @@ export function rewriteModuleStatementsAndPrepareHeader(

const headers = [];
if (hasExports(meta) && !strict) {
headers.push(buildESModuleHeader(meta, loose /* enumerable */));
headers.push(buildESModuleHeader(meta, enumerableModuleMeta));
}

const nameList = buildExportNameListDeclaration(path, meta);
Expand All @@ -78,7 +83,9 @@ export function rewriteModuleStatementsAndPrepareHeader(
}

// Create all of the statically known named exports.
headers.push(...buildExportInitializationStatements(path, meta, loose));
headers.push(
...buildExportInitializationStatements(path, meta, constantReexports),
);

return { meta, headers };
}
Expand Down Expand Up @@ -128,7 +135,7 @@ export function wrapInterop(
export function buildNamespaceInitStatements(
metadata: ModuleMetadata,
sourceMetadata: SourceModuleMetadata,
loose: boolean = false,
constantReexports: boolean = false,
) {
const statements = [];

Expand All @@ -146,8 +153,8 @@ export function buildNamespaceInitStatements(
}),
);
}
if (loose) {
statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, loose));
if (constantReexports) {
statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, true));
}
for (const exportName of sourceMetadata.reexportNamespace) {
// Assign export to namespace object.
Expand All @@ -172,7 +179,7 @@ export function buildNamespaceInitStatements(
const statement = buildNamespaceReexport(
metadata,
t.cloneNode(srcNamespace),
loose,
constantReexports,
);
statement.loc = sourceMetadata.reexportAll.loc;

Expand All @@ -183,8 +190,8 @@ export function buildNamespaceInitStatements(
}

const ReexportTemplate = {
loose: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
looseComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
constant: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
constantComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
spec: template`
Object.defineProperty(EXPORTS, "EXPORT_NAME", {
enumerable: true,
Expand All @@ -198,7 +205,7 @@ const ReexportTemplate = {
const buildReexportsFromMeta = (
meta: ModuleMetadata,
metadata: SourceModuleMetadata,
loose,
constantReexports: boolean,
) => {
const namespace = metadata.lazy
? t.callExpression(t.identifier(metadata.name), [])
Expand All @@ -224,11 +231,11 @@ const buildReexportsFromMeta = (
EXPORT_NAME: exportName,
NAMESPACE_IMPORT,
};
if (loose) {
if (constantReexports) {
if (stringSpecifiers.has(exportName)) {
return ReexportTemplate.looseComputed(astNodes);
return ReexportTemplate.constantComputed(astNodes);
} else {
return ReexportTemplate.loose(astNodes);
return ReexportTemplate.constant(astNodes);
}
} else {
return ReexportTemplate.spec(astNodes);
Expand All @@ -241,9 +248,9 @@ const buildReexportsFromMeta = (
*/
function buildESModuleHeader(
metadata: ModuleMetadata,
enumerable: boolean = false,
enumerableModuleMeta: boolean = false,
) {
return (enumerable
return (enumerableModuleMeta
? template.statement`
EXPORTS.__esModule = true;
`
Expand All @@ -257,8 +264,8 @@ function buildESModuleHeader(
/**
* Create a re-export initialization loop for a specific imported namespace.
*/
function buildNamespaceReexport(metadata, namespace, loose) {
return (loose
function buildNamespaceReexport(metadata, namespace, constantReexports) {
return (constantReexports
? template.statement`
Object.keys(NAMESPACE).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
Expand Down Expand Up @@ -347,7 +354,7 @@ function buildExportNameListDeclaration(
function buildExportInitializationStatements(
programPath: NodePath,
metadata: ModuleMetadata,
loose: boolean = false,
constantReexports: boolean = false,
) {
const initStatements = [];

Expand All @@ -365,8 +372,8 @@ function buildExportInitializationStatements(
}

for (const data of metadata.source.values()) {
if (!loose) {
initStatements.push(...buildReexportsFromMeta(metadata, data, loose));
if (!constantReexports) {
initStatements.push(...buildReexportsFromMeta(metadata, data, false));
}
for (const exportName of data.reexportNamespace) {
exportNames.push(exportName);
Expand Down
Expand Up @@ -86,7 +86,7 @@ export default function normalizeModuleAndLoadMetadata(
exportName?: string,
{
noInterop = false,
loose = false,
initializeReexports = false,
lazy = false,
esNamespaceOnly = false,
} = {},
Expand All @@ -100,10 +100,7 @@ export default function normalizeModuleAndLoadMetadata(

const { local, source, hasExports } = getModuleMetadata(
programPath,
{
loose,
lazy,
},
{ initializeReexports, lazy },
stringSpecifiers,
);

Expand Down Expand Up @@ -170,12 +167,15 @@ function getExportSpecifierName(
*/
function getModuleMetadata(
programPath: NodePath,
{ loose, lazy }: { loose: boolean, lazy: boolean },
{
lazy,
initializeReexports,
}: { lazy: boolean, initializeReexports: boolean },
stringSpecifiers: Set<string>,
) {
const localData = getLocalExportMetadata(
programPath,
loose,
initializeReexports,
stringSpecifiers,
);

Expand Down Expand Up @@ -361,7 +361,7 @@ function getModuleMetadata(
*/
function getLocalExportMetadata(
programPath: NodePath,
loose: boolean,
initializeReexports: boolean,
stringSpecifiers: Set<string>,
): Map<string, LocalExportMetadata> {
const bindingKindLookup = new Map();
Expand All @@ -376,7 +376,7 @@ function getLocalExportMetadata(
if (child.node.declaration) {
child = child.get("declaration");
} else if (
loose &&
initializeReexports &&
child.node.source &&
child.get("source").isStringLiteral()
) {
Expand Down Expand Up @@ -429,7 +429,10 @@ function getLocalExportMetadata(
};

programPath.get("body").forEach(child => {
if (child.isExportNamedDeclaration() && (loose || !child.node.source)) {
if (
child.isExportNamedDeclaration() &&
(initializeReexports || !child.node.source)
) {
if (child.node.declaration) {
const declaration = child.get("declaration");
const ids = declaration.getOuterBindingIdentifierPaths();
Expand Down
17 changes: 14 additions & 3 deletions packages/babel-plugin-transform-modules-amd/src/index.js
Expand Up @@ -38,7 +38,13 @@ function injectWrapper(path, wrapper) {
export default declare((api, options) => {
api.assertVersion(7);

const { loose, allowTopLevelThis, strict, strictMode, noInterop } = options;
const { allowTopLevelThis, strict, strictMode, noInterop } = options;

const constantReexports =
api.assumption("constantReexports") ?? options.loose;
const enumerableModuleMeta =
api.assumption("enumerableModuleMeta") ?? options.loose;

return {
name: "transform-modules-amd",

Expand Down Expand Up @@ -103,7 +109,8 @@ export default declare((api, options) => {
const { meta, headers } = rewriteModuleStatementsAndPrepareHeader(
path,
{
loose,
enumerableModuleMeta,
constantReexports,
strict,
strictMode,
allowTopLevelThis,
Expand Down Expand Up @@ -141,7 +148,11 @@ export default declare((api, options) => {
}

headers.push(
...buildNamespaceInitStatements(meta, metadata, loose),
...buildNamespaceInitStatements(
meta,
metadata,
constantReexports,
),
);
}

Expand Down
@@ -0,0 +1 @@
export {foo as default} from "foo";
@@ -0,0 +1,9 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.default = void 0;
_exports.default = _foo.foo;
});
@@ -0,0 +1 @@
export {foo as default, bar} from "foo";
@@ -0,0 +1,10 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.default = void 0;
_exports.default = _foo.foo;
_exports.bar = _foo.bar;
});
@@ -0,0 +1 @@
export {foo as bar} from "foo";
@@ -0,0 +1,9 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = void 0;
_exports.bar = _foo.foo;
});
@@ -0,0 +1 @@
export {foo, bar} from "foo";
@@ -0,0 +1,10 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.bar = _exports.foo = void 0;
_exports.foo = _foo.foo;
_exports.bar = _foo.bar;
});
@@ -0,0 +1 @@
export * from "foo";
@@ -0,0 +1,12 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
Object.keys(_foo).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in _exports && _exports[key] === _foo[key]) return;
_exports[key] = _foo[key];
});
});
@@ -0,0 +1 @@
export {foo} from "foo";
@@ -0,0 +1,9 @@
define(["exports", "foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.foo = void 0;
_exports.foo = _foo.foo;
});
@@ -0,0 +1,3 @@
import { foo } from "./foo";

export { foo };
@@ -0,0 +1,8 @@
define(["exports", "./foo"], function (_exports, _foo) {
"use strict";

Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.foo = _foo.foo;
});
@@ -0,0 +1,6 @@
{
"assumptions": {
"constantReexports": true
},
"plugins": ["external-helpers", "transform-modules-amd"]
}
@@ -0,0 +1 @@
export var foo = 2;
@@ -0,0 +1,8 @@
define(["exports"], function (_exports) {
"use strict";

_exports.__esModule = true;
_exports.foo = void 0;
var foo = 2;
_exports.foo = foo;
});
@@ -0,0 +1,6 @@
{
"assumptions": {
"enumerableModuleMeta": true
},
"plugins": ["external-helpers", "transform-modules-amd"]
}

0 comments on commit 5323795

Please sign in to comment.