Skip to content

Commit

Permalink
refactor: improve internal babel types (#271)
Browse files Browse the repository at this point in the history
  • Loading branch information
aryaemami59 committed Jul 26, 2024
1 parent b90874f commit fb53cbc
Show file tree
Hide file tree
Showing 21 changed files with 451 additions and 59 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"test:bun": "bun --bun test test/bun"
},
"devDependencies": {
"@babel/helper-module-imports": "^7.24.7",
"@babel/core": "^7.24.9",
"@babel/helper-module-transforms": "^7.24.9",
"@babel/helper-plugin-utils": "^7.24.8",
Expand All @@ -59,9 +60,13 @@
"@babel/plugin-transform-typescript": "^7.24.8",
"@babel/preset-typescript": "^7.24.7",
"@babel/template": "^7.24.7",
"@babel/traverse": "^7.24.7",
"@babel/types": "^7.24.9",
"@types/babel__core": "^7.20.5",
"@types/babel__helper-module-imports": "^7.18.3",
"@types/babel__helper-plugin-utils": "^7.10.3",
"@types/babel__template": "^7.4.4",
"@types/babel__traverse": "^7.20.6",
"@types/node": "^20.14.12",
"@vitest/coverage-v8": "^2.0.4",
"acorn": "^8.12.1",
Expand Down
30 changes: 30 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/_types/babel-core.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { HubInterface } from "@babel/traverse";

declare module "@babel/core" {
export interface BabelFile
extends HubInterface,
Pick<PluginPass, "get" | "set"> {}
}

export {};
203 changes: 203 additions & 0 deletions src/_types/babel-helper-module-transforms.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
declare module "@babel/helper-module-transforms" {
import type { NodePath } from "@babel/core";
import { types as t } from "@babel/core";

interface LocalExportMetadata {
/**
* names of exports
*/
names: string[];
kind: "import" | "hoisted" | "block" | "var";
}

type InteropType =
/**
* Babel interop for default-only imports
*/
| "default"
/**
* Babel interop for namespace or default+named imports
*/
| "namespace"
/**
* Node.js interop for default-only imports
*/
| "node-default"
/**
* Node.js interop for namespace or default+named imports
*/
| "node-namespace"
/**
* No interop, or named-only imports
*/
| "none";

interface SourceModuleMetadata {
/**
* A unique variable name to use for this namespace object.
* Centralized for simplicity.
*/
name: string;
loc: t.SourceLocation | undefined | null;
interop: InteropType;
/**
* Local binding to reference from this source namespace.
* Key: Local name, value: Import name
*/
imports: Map<string, string>;
/**
* Local names that reference namespace object.
*/
importsNamespace: Set<string>;
/**
* Reexports to create for namespace. Key: Export name, value: Import name
*/
reexports: Map<string, string>;
/**
* List of names to re-export namespace as.
*/
reexportNamespace: Set<string>;
/**
* Tracks if the source should be re-exported.
*/
reexportAll: null | {
loc: t.SourceLocation | undefined | null;
};
wrap?: unknown;
referenced: boolean;
}

interface ModuleMetadata {
exportName: string;
/**
* The name of the variable that will reference an object
* containing export names.
*/
exportNameListName: null | string;
hasExports: boolean;
/**
* Lookup from local binding to export information.
*/
local: Map<string, LocalExportMetadata>;
/**
* Lookup of source file to source file metadata.
*/
source: Map<string, SourceModuleMetadata>;
/**
* List of names that should only be printed as string literals.
* i.e. `import { "any unicode" as foo } from "some-module"`
* `stringSpecifiers` is `Set(1) ["any unicode"]`
* In most cases `stringSpecifiers` is an empty Set
*/
stringSpecifiers: Set<string>;
}

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

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

type RootOptions = {
filename?: string | null;
filenameRelative?: string | null;
sourceRoot?: string | null;
};

export type PluginOptions = {
moduleId?: string;
moduleIds?: boolean;
getModuleId?: (moduleName: string) => string | null | undefined;
moduleRoot?: string;
};

export function getModuleName(
rootOpts: RootOptions,
pluginOpts: PluginOptions,
): string | null;

export interface RewriteModuleStatementsAndPrepareHeaderOptions {
exportName?: string;
strict?: boolean;
allowTopLevelThis?: boolean;
strictMode?: boolean;
loose?: boolean;
importInterop?: ImportInterop;
noInterop?: boolean;
lazy?: Lazy;
getWrapperPayload?: (
source: string,
metadata: SourceModuleMetadata,
importNodes: t.Node[],
) => unknown;
wrapReference?: (
ref: t.Expression,
payload: unknown,
) => t.Expression | null | undefined;
esNamespaceOnly?: boolean;
filename: string | undefined | null;
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
* program to reference the modules described by the returned metadata,
* and returns a list of statements for use when initializing the module.
*/
export function rewriteModuleStatementsAndPrepareHeader(
path: NodePath<t.Program>,
options: RewriteModuleStatementsAndPrepareHeaderOptions,
): {
meta: ModuleMetadata;
headers: t.Statement[];
};

/**
* Check if a given source is an anonymous import, e.g. `import 'foo';`
*/
export function isSideEffectImport(source: SourceModuleMetadata): boolean;

/**
* Create the runtime initialization statements for a given requested source.
* These will initialize all of the runtime import/export logic that
* can't be handled statically by the statements created by
* `buildExportInitializationStatements()`.
*/
export function buildNamespaceInitStatements(
metadata: ModuleMetadata,
sourceMetadata: SourceModuleMetadata,
constantReexports?: boolean | void,
wrapReference?: (
ref: t.Identifier,
payload: unknown,
) => t.Expression | null | undefined,
): t.Statement[];

/**
* Flag a set of statements as hoisted above all else so that module init
* statements all run before user code.
*/
export function ensureStatementsHoisted(statements: t.Statement[]): void;

/**
* Given an expression for a standard import object, like `require('foo')`,
* wrap it in a call to the interop helpers based on the type.
*/
export function wrapInterop(
programPath: NodePath<t.Program>,
expr: t.Expression,
type: InteropType,
): t.CallExpression;

export function buildDynamicImport(
node: t.CallExpression | t.ImportExpression,
deferToThen: boolean,
wrapWithPromise: boolean,
builder: (specifier: t.Expression) => t.Expression,
): t.Expression;
}
64 changes: 64 additions & 0 deletions src/_types/babel-helper-plugin-utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { ConfigAPI } from "@babel/core";

declare module "@babel/helper-plugin-utils" {
const knownAssumptions: readonly [
"arrayLikeIsIterable",
"constantReexports",
"constantSuper",
"enumerableModuleMeta",
"ignoreFunctionLength",
"ignoreToPrimitiveHint",
"iterableIsArray",
"mutableTemplateObject",
"noClassCalls",
"noDocumentAll",
"noIncompleteNsImportDetection",
"noNewArrows",
"noUninitializedPrivateFieldAccess",
"objectRestNoSymbols",
"privateFieldsAsSymbols",
"privateFieldsAsProperties",
"pureGetters",
"setClassMethods",
"setComputedProperties",
"setPublicClassFields",
"setSpreadProperties",
"skipForOfIteratorClosing",
"superIsCallableConstructor",
];

export type AssumptionName = (typeof knownAssumptions)[number];

type AssumptionFunction = (name: AssumptionName) => boolean | undefined;

export type Target =
| "node"
| "deno"
| "chrome"
| "opera"
| "edge"
| "firefox"
| "safari"
| "ie"
| "ios"
| "android"
| "electron"
| "samsung"
| "opera_mobile";

export type Targets = {
[target in Target]?: string;
};

type TargetsFunction = () => Targets;

export type PresetAPI = {
targets: TargetsFunction;
addExternalDependency: (ref: string) => void;
} & ConfigAPI;

export type PluginAPI = {
assumption: AssumptionFunction;
} & PresetAPI &
BabelAPI;
}
9 changes: 9 additions & 0 deletions src/_types/babel-helper-simple-access.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare module "@babel/helper-simple-access" {
import type { NodePath } from "@babel/traverse";

export default function simplifyAccess(
path: NodePath,
bindingNames: Set<string>,
includeUpdateExpression?: boolean,
): void;
}
5 changes: 5 additions & 0 deletions src/_types/babel-plugin-parameter-decorator.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module "babel-plugin-parameter-decorator" {
import type { declare } from "@babel/helper-plugin-utils";
const parameterDecoratorPlugin: ReturnType<typeof declare>;
export default parameterDecoratorPlugin;
}
14 changes: 14 additions & 0 deletions src/_types/babel-plugin-proposal-decorators.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare module "@babel/plugin-proposal-decorators" {
import type { declare } from "@babel/helper-plugin-utils";
import type { Options as SyntaxOptions } from "@babel/plugin-syntax-decorators";

export interface Options extends SyntaxOptions {
/**
* @deprecated use `constantSuper` assumption instead. Only supported in 2021-12 version.
*/
loose?: boolean;
}

const proposalDecoratorsPlugin: ReturnType<typeof declare<Options>>;
export default proposalDecoratorsPlugin;
}
Loading

0 comments on commit fb53cbc

Please sign in to comment.