Skip to content

Commit

Permalink
Improve module transform packages typings (#14608)
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed May 30, 2022
1 parent 8f8657a commit 0f63772
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 130 deletions.
55 changes: 34 additions & 21 deletions packages/babel-helper-module-transforms/src/index.ts
Expand Up @@ -27,7 +27,9 @@ import normalizeModuleAndLoadMetadata, {
validateImportInteropOption,
} from "./normalize-and-load-metadata";
import type {
ImportInterop,
InteropType,
Lazy,
ModuleMetadata,
SourceModuleMetadata,
} from "./normalize-and-load-metadata";
Expand All @@ -38,6 +40,22 @@ export type { PluginOptions } from "./get-module-name";

export { hasExports, isSideEffectImport, isModule, rewriteThis };

export interface RewriteModuleStatementsAndPrepareHeaderOptions {
exportName?: string;
strict: boolean;
allowTopLevelThis?: boolean;
strictMode: boolean;
loose?: boolean;
importInterop?: ImportInterop;
noInterop?: boolean;
lazy?: Lazy;
esNamespaceOnly?: boolean;
filename: string | undefined;
constantReexports?: boolean | void;
enumerableModuleMeta?: boolean | void;
noIncompleteNsImportDetection?: boolean | void;
}

/**
* Perform all of the generic ES6 module rewriting needed to handle initial
* module processing. This function will rewrite the majority of the given
Expand All @@ -63,21 +81,7 @@ export function rewriteModuleStatementsAndPrepareHeader(
constantReexports = loose,
enumerableModuleMeta = loose,
noIncompleteNsImportDetection,
}: {
exportName?;
strict;
allowTopLevelThis?;
strictMode;
loose?;
importInterop?: "none" | "babel" | "node";
noInterop?;
lazy?;
esNamespaceOnly?;
filename: string | undefined;
constantReexports?;
enumerableModuleMeta?;
noIncompleteNsImportDetection?: boolean;
},
}: RewriteModuleStatementsAndPrepareHeaderOptions,
) {
validateImportInteropOption(importInterop);
assert(isModule(path), "Cannot process module statements in a script");
Expand Down Expand Up @@ -138,9 +142,10 @@ export function rewriteModuleStatementsAndPrepareHeader(
* Flag a set of statements as hoisted above all else so that module init
* statements all run before user code.
*/
export function ensureStatementsHoisted(statements) {
export function ensureStatementsHoisted(statements: t.Statement[]) {
// Force all of the header fields to be at the top of the file.
statements.forEach(header => {
// @ts-ignore Fixme: handle _blockHoist property
header._blockHoist = 3;
});
}
Expand Down Expand Up @@ -303,7 +308,7 @@ const buildReexportsFromMeta = (
*/
function buildESModuleHeader(
metadata: ModuleMetadata,
enumerableModuleMeta: boolean = false,
enumerableModuleMeta: boolean | void = false,
) {
return (
enumerableModuleMeta
Expand All @@ -321,7 +326,11 @@ function buildESModuleHeader(
/**
* Create a re-export initialization loop for a specific imported namespace.
*/
function buildNamespaceReexport(metadata, namespace, constantReexports) {
function buildNamespaceReexport(
metadata: ModuleMetadata,
namespace: t.Identifier | t.CallExpression,
constantReexports: boolean | void,
) {
return (
constantReexports
? template.statement`
Expand Down Expand Up @@ -413,8 +422,8 @@ function buildExportNameListDeclaration(
function buildExportInitializationStatements(
programPath: NodePath,
metadata: ModuleMetadata,
constantReexports: boolean = false,
noIncompleteNsImportDetection = false,
constantReexports: boolean | void = false,
noIncompleteNsImportDetection: boolean | void = false,
) {
const initStatements: Array<[string, t.Statement | null]> = [];

Expand Down Expand Up @@ -514,7 +523,11 @@ const InitTemplate = {
default: template.expression`EXPORTS.NAME = VALUE`,
};

function buildInitStatement(metadata: ModuleMetadata, exportNames, initExpr) {
function buildInitStatement(
metadata: ModuleMetadata,
exportNames: string[],
initExpr: t.Expression,
) {
const { stringSpecifiers, exportName: EXPORTS } = metadata;
return expressionStatement(
exportNames.reduce((acc, exportName) => {
Expand Down
Expand Up @@ -28,6 +28,14 @@ export type InteropType =
| "node-namespace" // Node.js interop for namespace or default+named imports
| "none"; // No interop, or named-only imports

export type ImportInterop =
| "none"
| "babel"
| "node"
| ((source: string, filename?: string) => "none" | "babel" | "node");

export type Lazy = boolean | string[] | ((source: string) => boolean);

export interface SourceModuleMetadata {
// A unique variable name to use for this namespace object. Centralized for simplicity.
name: string;
Expand All @@ -45,7 +53,7 @@ export interface SourceModuleMetadata {
reexportAll: null | {
loc: t.SourceLocation | undefined | null;
};
lazy?;
lazy?: Lazy;
}

export interface LocalExportMetadata {
Expand Down Expand Up @@ -75,7 +83,7 @@ export function isSideEffectImport(source: SourceModuleMetadata) {

export function validateImportInteropOption(
importInterop: any,
): importInterop is "none" | "babel" | "node" | Function {
): importInterop is ImportInterop {
if (
typeof importInterop !== "function" &&
importInterop !== "none" &&
Expand All @@ -90,8 +98,8 @@ export function validateImportInteropOption(
}

function resolveImportInterop(
importInterop,
source,
importInterop: ImportInterop,
source: string,
filename: string | undefined,
) {
if (typeof importInterop === "function") {
Expand All @@ -113,6 +121,12 @@ export default function normalizeModuleAndLoadMetadata(
lazy = false,
esNamespaceOnly = false,
filename,
}: {
importInterop: ImportInterop;
initializeReexports: boolean | void;
lazy: Lazy;
esNamespaceOnly: boolean;
filename: string;
},
): ModuleMetadata {
if (!exportName) {
Expand Down Expand Up @@ -219,8 +233,8 @@ function getModuleMetadata(
initializeReexports,
}: {
// todo(flow-ts) changed from boolean, to match expected usage inside the function
lazy: boolean | string[] | Function;
initializeReexports: boolean;
lazy: boolean | string[] | ((source: string) => boolean);
initializeReexports: boolean | void;
},
stringSpecifiers: Set<string>,
) {
Expand All @@ -231,7 +245,7 @@ function getModuleMetadata(
);

const sourceData = new Map();
const getData = sourceNode => {
const getData = (sourceNode: t.StringLiteral) => {
const source = sourceNode.value;

let data = sourceData.get(source);
Expand Down Expand Up @@ -409,22 +423,26 @@ function getModuleMetadata(
};
}

type ModuleBindingKind = "import" | "hoisted" | "block" | "var";
/**
* Get metadata about local variables that are exported.
*/
function getLocalExportMetadata(
programPath: NodePath<t.Program>,
initializeReexports: boolean,
initializeReexports: boolean | void,
stringSpecifiers: Set<string>,
): Map<string, LocalExportMetadata> {
const bindingKindLookup = new Map();

programPath.get("body").forEach((child: any) => {
let kind;
programPath.get("body").forEach(child => {
let kind: ModuleBindingKind;
if (child.isImportDeclaration()) {
kind = "import";
} else {
if (child.isExportDefaultDeclaration()) child = child.get("declaration");
if (child.isExportDefaultDeclaration()) {
// @ts-ignore
child = child.get("declaration");
}
if (child.isExportNamedDeclaration()) {
if (child.node.declaration) {
child = child.get("declaration");
Expand Down Expand Up @@ -460,7 +478,7 @@ function getLocalExportMetadata(
});

const localMetadata = new Map();
const getLocalMetadata = idPath => {
const getLocalMetadata = (idPath: NodePath<t.Identifier>) => {
const localName = idPath.node.name;
let metadata = localMetadata.get(localName);

Expand Down
Expand Up @@ -27,24 +27,24 @@ import type { ModuleMetadata } from "./normalize-and-load-metadata";
interface RewriteReferencesVisitorState {
exported: Map<any, any>;
metadata: ModuleMetadata;
requeueInParent: (path) => void;
requeueInParent: (path: NodePath) => void;
scope: Scope;
imported: Map<any, any>;
buildImportReference: (
[source, importName, localName]: readonly [any, any, any],
identNode,
[source, importName, localName]: readonly [string, string, string],
identNode: t.Identifier | t.CallExpression | t.JSXIdentifier,
) => any;
seen: WeakSet<object>;
}

interface RewriteBindingInitVisitorState {
exported: Map<any, any>;
metadata: ModuleMetadata;
requeueInParent: (path) => void;
requeueInParent: (path: NodePath) => void;
scope: Scope;
}

function isInType(path) {
function isInType(path: NodePath) {
do {
switch (path.parent.type) {
case "TSTypeAnnotation":
Expand All @@ -54,7 +54,13 @@ function isInType(path) {
case "TypeAlias":
return true;
case "ExportSpecifier":
return path.parentPath.parent.exportKind === "type";
return (
(
path.parentPath.parent as
| t.ExportDefaultDeclaration
| t.ExportNamedDeclaration
).exportKind === "type"
);
default:
if (path.parentPath.isStatement() || path.parentPath.isExpression()) {
return false;
Expand All @@ -69,7 +75,7 @@ export default function rewriteLiveReferences(
) {
const imported = new Map();
const exported = new Map();
const requeueInParent = path => {
const requeueInParent = (path: NodePath) => {
// Manually re-queue `exports.default =` expressions so that the ES3
// transform has an opportunity to convert them. Ideally this would
// happen automatically from the replaceWith above. See #4140 for
Expand Down Expand Up @@ -127,7 +133,13 @@ export default function rewriteLiveReferences(
const meta = metadata.source.get(source);

if (localName) {
if (meta.lazy) identNode = callExpression(identNode, []);
if (meta.lazy) {
identNode = callExpression(
// @ts-expect-error Fixme: we should handle the case when identNode is a JSXIdentifier
identNode,
[],
);
}
return identNode;
}

Expand Down Expand Up @@ -203,9 +215,9 @@ const rewriteBindingInitVisitor: Visitor<RewriteBindingInitVisitorState> = {
};

const buildBindingExportAssignmentExpression = (
metadata,
exportNames,
localExpr,
metadata: ModuleMetadata,
exportNames: string[],
localExpr: t.Expression,
) => {
return (exportNames || []).reduce((expr, exportName) => {
// class Foo {} export { Foo, Foo as Bar };
Expand All @@ -225,7 +237,7 @@ const buildBindingExportAssignmentExpression = (
}, localExpr);
};

const buildImportThrow = localName => {
const buildImportThrow = (localName: string) => {
return template.expression.ast`
(function() {
throw new Error('"' + '${localName}' + '" is read-only.');
Expand Down Expand Up @@ -403,7 +415,7 @@ const rewriteReferencesVisitor: Visitor<RewriteReferencesVisitorState> = {
const assignment = path.node;

if (importData) {
assignment.left = buildImportReference(importData, assignment.left);
assignment.left = buildImportReference(importData, left.node);

assignment.right = sequenceExpression([
assignment.right,
Expand Down Expand Up @@ -437,7 +449,7 @@ const rewriteReferencesVisitor: Visitor<RewriteReferencesVisitorState> = {

// Complex ({a, b, c} = {}); export { a, c };
// => ({a, b, c} = {}), (exports.a = a, exports.c = c);
const items = [];
const items: t.Expression[] = [];
programScopeIds.forEach(localName => {
const exportedNames = exported.get(localName) || [];
if (exportedNames.length > 0) {
Expand Down
3 changes: 1 addition & 2 deletions packages/babel-helper-module-transforms/src/rewrite-this.ts
@@ -1,7 +1,6 @@
import environmentVisitor from "@babel/helper-environment-visitor";
import traverse from "@babel/traverse";
import { numericLiteral, unaryExpression } from "@babel/types";
import type * as t from "@babel/types";

import type { NodePath, Visitor } from "@babel/traverse";
export default function rewriteThis(programPath: NodePath) {
Expand All @@ -16,7 +15,7 @@ export default function rewriteThis(programPath: NodePath) {
const rewriteThisVisitor: Visitor = traverse.visitors.merge([
environmentVisitor,
{
ThisExpression(path: NodePath<t.ThisExpression>) {
ThisExpression(path) {
path.replaceWith(unaryExpression("void", numericLiteral(0), true));
},
},
Expand Down

0 comments on commit 0f63772

Please sign in to comment.