+48
-51
@@ -16,2 +16,5 @@ import { ParseError, ParseResult, ParserOptions } from "@babel/parser"; | ||
| */ | ||
| /** | ||
| * All possible node types. | ||
| */ | ||
| type NodeType = t$7.Node["type"] | "Function" | "Literal" | "Expression"; | ||
@@ -22,3 +25,3 @@ /** | ||
| type GetNode<K extends NodeType> = K extends "Function" ? t$7.Function : K extends "Literal" ? t$7.Literal : Extract<t$7.Node, { | ||
| type: K | ||
| type: K; | ||
| }>; | ||
@@ -191,4 +194,7 @@ /** | ||
| */ | ||
| declare function babelParse(code: string, lang?: string, { cache,...options }?: ParserOptions & { | ||
| cache?: boolean | ||
| declare function babelParse(code: string, lang?: string, { | ||
| cache, | ||
| ...options | ||
| }?: ParserOptions & { | ||
| cache?: boolean; | ||
| }): t$3.Program & Omit<ParseResult<t$3.File>, "type" | "program">; | ||
@@ -206,3 +212,3 @@ declare const parseCache: Map<string, ParseResult<t$3.File>>; | ||
| declare function babelParseExpression<T extends t$3.Node = t$3.Expression>(code: string, lang?: string, options?: ParserOptions): T & { | ||
| errors: null | ParseError[] | ||
| errors: null | ParseError[]; | ||
| }; | ||
@@ -252,12 +258,12 @@ | ||
| interface AttachedScope { | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean | ||
| }; | ||
| addDeclaration: (node: Node, isBlockDeclaration: boolean, isVar: boolean) => void; | ||
| contains: (name: string) => boolean; | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean; | ||
| }; | ||
| addDeclaration: (node: Node, isBlockDeclaration: boolean, isVar: boolean) => void; | ||
| contains: (name: string) => boolean; | ||
| } | ||
| type WithScope<T> = T & { | ||
| scope?: AttachedScope | ||
| scope?: AttachedScope; | ||
| }; | ||
@@ -268,5 +274,5 @@ /** | ||
| interface ScopeOptions { | ||
| parent?: AttachedScope; | ||
| block?: boolean; | ||
| params?: Node[]; | ||
| parent?: AttachedScope; | ||
| block?: boolean; | ||
| params?: Node[]; | ||
| } | ||
@@ -277,10 +283,10 @@ /** | ||
| declare class Scope implements AttachedScope { | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean | ||
| }; | ||
| constructor(options?: ScopeOptions); | ||
| addDeclaration(node: Node, isBlockDeclaration: boolean, isVar: boolean): void; | ||
| contains(name: string): boolean; | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean; | ||
| }; | ||
| constructor(options?: ScopeOptions); | ||
| addDeclaration(node: Node, isBlockDeclaration: boolean, isVar: boolean): void; | ||
| contains(name: string): boolean; | ||
| } | ||
@@ -301,6 +307,3 @@ /** | ||
| */ | ||
| type LiteralUnion< | ||
| LiteralType, | ||
| BaseType extends null | undefined | string | number | boolean | symbol | bigint = string | ||
| > = LiteralType | (BaseType & Record<never, never>); | ||
| type LiteralUnion<LiteralType, BaseType extends null | undefined | string | number | boolean | symbol | bigint = string> = LiteralType | (BaseType & Record<never, never>); | ||
@@ -327,16 +330,10 @@ //#endregion | ||
| interface WalkThis<T> { | ||
| skip: () => void; | ||
| remove: () => void; | ||
| replace: (node: T) => void; | ||
| skip: () => void; | ||
| remove: () => void; | ||
| replace: (node: T) => void; | ||
| } | ||
| type WalkCallback< | ||
| T, | ||
| R | ||
| > = (this: WalkThis<T>, node: T, parent: T | null | undefined, key: string | null | undefined, index: number | null | undefined) => R; | ||
| interface WalkHandlers< | ||
| T, | ||
| R | ||
| > { | ||
| enter?: WalkCallback<T, R>; | ||
| leave?: WalkCallback<T, R>; | ||
| type WalkCallback<T, R> = (this: WalkThis<T>, node: T, parent: T | null | undefined, key: string | null | undefined, index: number | null | undefined) => R; | ||
| interface WalkHandlers<T, R> { | ||
| enter?: WalkCallback<T, R>; | ||
| leave?: WalkCallback<T, R>; | ||
| } | ||
@@ -363,7 +360,7 @@ /** | ||
| interface ImportBinding { | ||
| local: string; | ||
| imported: LiteralUnion<"*" | "default">; | ||
| source: string; | ||
| specifier: t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier; | ||
| isType: boolean; | ||
| local: string; | ||
| imported: LiteralUnion<"*" | "default">; | ||
| source: string; | ||
| specifier: t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier; | ||
| isType: boolean; | ||
| } | ||
@@ -381,8 +378,8 @@ /** | ||
| interface ExportBinding { | ||
| local: string; | ||
| exported: LiteralUnion<"*" | "default">; | ||
| isType: boolean; | ||
| source: string | null; | ||
| specifier: t.ExportSpecifier | t.ExportDefaultSpecifier | t.ExportNamespaceSpecifier | null; | ||
| declaration: t.Declaration | t.ExportDefaultDeclaration["declaration"] | null; | ||
| local: string; | ||
| exported: LiteralUnion<"*" | "default">; | ||
| isType: boolean; | ||
| source: string | null; | ||
| specifier: t.ExportSpecifier | t.ExportDefaultSpecifier | t.ExportNamespaceSpecifier | null; | ||
| declaration: t.Declaration | t.ExportDefaultDeclaration["declaration"] | null; | ||
| } | ||
@@ -389,0 +386,0 @@ /** |
+0
-3
@@ -975,5 +975,2 @@ import { extname } from "pathe"; | ||
| var Scope = class { | ||
| parent; | ||
| isBlockScope; | ||
| declarations; | ||
| constructor(options = {}) { | ||
@@ -980,0 +977,0 @@ this.parent = options.parent; |
+13
-16
| { | ||
| "name": "ast-kit", | ||
| "version": "1.4.3", | ||
| "version": "2.0.0", | ||
| "description": "A toolkit for easy Babel AST generation and manipulation.", | ||
@@ -24,6 +24,3 @@ "type": "module", | ||
| "exports": { | ||
| ".": { | ||
| "require": "./dist/index.cjs", | ||
| "import": "./dist/index.js" | ||
| }, | ||
| ".": "./dist/index.js", | ||
| "./package.json": "./package.json" | ||
@@ -35,24 +32,24 @@ }, | ||
| "dependencies": { | ||
| "@babel/parser": "^7.27.0", | ||
| "@babel/parser": "^7.27.2", | ||
| "pathe": "^2.0.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@babel/types": "^7.27.0", | ||
| "@sxzz/eslint-config": "^6.1.2", | ||
| "@babel/types": "^7.27.1", | ||
| "@sxzz/eslint-config": "^7.0.0", | ||
| "@sxzz/prettier-config": "^2.2.1", | ||
| "@types/node": "^22.14.1", | ||
| "@vitest/coverage-v8": "^3.1.1", | ||
| "@vitest/ui": "^3.1.1", | ||
| "@types/node": "^22.15.17", | ||
| "@vitest/coverage-v8": "^3.1.3", | ||
| "@vitest/ui": "^3.1.3", | ||
| "bumpp": "^10.1.0", | ||
| "eslint": "^9.25.0", | ||
| "eslint": "^9.26.0", | ||
| "estree-walker": "^3.0.3", | ||
| "fast-glob": "^3.3.3", | ||
| "prettier": "^3.5.3", | ||
| "tsdown": "^0.9.3", | ||
| "tsx": "^4.19.3", | ||
| "tsdown": "^0.11.1", | ||
| "tsx": "^4.19.4", | ||
| "typescript": "5.8.3", | ||
| "vitest": "^3.1.1" | ||
| "vitest": "^3.1.3" | ||
| }, | ||
| "engines": { | ||
| "node": ">=16.14.0" | ||
| "node": ">=20.18.0" | ||
| }, | ||
@@ -59,0 +56,0 @@ "prettier": "@sxzz/prettier-config", |
-1152
| "use strict"; | ||
| //#region rolldown:runtime | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| const pathe = __toESM(require("pathe")); | ||
| const __babel_parser = __toESM(require("@babel/parser")); | ||
| //#region src/check.ts | ||
| /** | ||
| * Checks if the given node matches the specified type(s). | ||
| * | ||
| * @param node - The node to check. | ||
| * @param types - The type(s) to match against. It can be a single type or an array of types. | ||
| * @returns True if the node matches the specified type(s), false otherwise. | ||
| */ | ||
| function isTypeOf(node, types) { | ||
| if (!node) return false; | ||
| return [].concat(types).some((type) => { | ||
| if (type === "Function") return isFunctionType(node); | ||
| else if (type === "Literal") return isLiteralType(node); | ||
| else if (type === "Expression") return isExpressionType(node); | ||
| else return node.type === type; | ||
| }); | ||
| } | ||
| /** | ||
| * Checks if the given node is a CallExpression with the specified callee. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The callee to compare against. It can be a string, an array of strings, or a function that takes a string and returns a boolean. | ||
| * @returns True if the node is a CallExpression with the specified callee, false otherwise. | ||
| */ | ||
| function isCallOf(node, test) { | ||
| return !!node && node.type === "CallExpression" && isIdentifierOf(node.callee, test); | ||
| } | ||
| /** | ||
| * Checks if the given node is a TaggedTemplateExpression with the specified callee. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The callee to compare against. It can be a string, an array of strings, or a function that takes a string and returns a boolean. | ||
| * @returns True if the node is a TaggedTemplateExpression with the specified callee, false otherwise. | ||
| */ | ||
| function isTaggedFunctionCallOf(node, test) { | ||
| return !!node && node.type === "TaggedTemplateExpression" && isIdentifierOf(node.tag, test); | ||
| } | ||
| /** | ||
| * Checks if the given node is an Identifier with the specified name. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The name to compare against. It can be a string or an array of strings. | ||
| * @returns True if the node is an Identifier with the specified name, false otherwise. | ||
| */ | ||
| function isIdentifierOf(node, test) { | ||
| return !!node && node.type === "Identifier" && match(node.name, test); | ||
| } | ||
| /** | ||
| * Checks if the given node is a literal type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a literal type, false otherwise. | ||
| */ | ||
| function isLiteralType(node) { | ||
| return !!node && node.type.endsWith("Literal"); | ||
| } | ||
| /** | ||
| * Checks if the given node is a function type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a function type, false otherwise. | ||
| */ | ||
| function isFunctionType(node) { | ||
| return !!node && !node.type.startsWith("TS") && /Function(?:Expression|Declaration)$|Method$/.test(node.type); | ||
| } | ||
| /** | ||
| * Checks if the given node is a declaration type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a declaration type, false otherwise. | ||
| */ | ||
| function isDeclarationType(node) { | ||
| if (!node) return false; | ||
| switch (node.type) { | ||
| case "FunctionDeclaration": | ||
| case "VariableDeclaration": | ||
| case "ClassDeclaration": | ||
| case "ExportAllDeclaration": | ||
| case "ExportDefaultDeclaration": | ||
| case "ExportNamedDeclaration": | ||
| case "ImportDeclaration": | ||
| case "DeclareClass": | ||
| case "DeclareFunction": | ||
| case "DeclareInterface": | ||
| case "DeclareModule": | ||
| case "DeclareModuleExports": | ||
| case "DeclareTypeAlias": | ||
| case "DeclareOpaqueType": | ||
| case "DeclareVariable": | ||
| case "DeclareExportDeclaration": | ||
| case "DeclareExportAllDeclaration": | ||
| case "InterfaceDeclaration": | ||
| case "OpaqueType": | ||
| case "TypeAlias": | ||
| case "EnumDeclaration": | ||
| case "TSDeclareFunction": | ||
| case "TSInterfaceDeclaration": | ||
| case "TSTypeAliasDeclaration": | ||
| case "TSEnumDeclaration": | ||
| case "TSModuleDeclaration": return true; | ||
| case "Placeholder": if (node.expectedNode === "Declaration") return true; | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * Checks if the given node is an expression type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is an expression type, false otherwise. | ||
| */ | ||
| function isExpressionType(node) { | ||
| return !!node && (node.type.endsWith("Expression") || isLiteralType(node) || [ | ||
| "Identifier", | ||
| "MetaProperty", | ||
| "Super", | ||
| "Import", | ||
| "JSXElement", | ||
| "JSXFragment", | ||
| "TopicReference", | ||
| "PipelineBareFunction", | ||
| "PipelinePrimaryTopicReference", | ||
| "TSTypeAssertion" | ||
| ].includes(node.type)); | ||
| } | ||
| function match(value, test) { | ||
| if (Array.isArray(test)) return test.includes(value); | ||
| if (typeof test === "function") return test(value); | ||
| return value === test; | ||
| } | ||
| /* v8 ignore start */ | ||
| /** | ||
| * Checks if the input `node` is a reference to a bound variable. | ||
| * | ||
| * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts | ||
| * | ||
| * To avoid runtime dependency on `@babel/types` (which includes process references) | ||
| * This file should not change very often in babel but we may need to keep it | ||
| * up-to-date from time to time. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param parent - The parent node of the input `node`. | ||
| * @param grandparent - The grandparent node of the input `node`. | ||
| * @returns True if the input `node` is a reference to a bound variable, false otherwise. | ||
| */ | ||
| function isReferenced(node, parent, grandparent) { | ||
| switch (parent.type) { | ||
| case "MemberExpression": | ||
| case "OptionalMemberExpression": | ||
| if (parent.property === node) return !!parent.computed; | ||
| return parent.object === node; | ||
| case "JSXMemberExpression": return parent.object === node; | ||
| case "VariableDeclarator": return parent.init === node; | ||
| case "ArrowFunctionExpression": return parent.body === node; | ||
| case "PrivateName": return false; | ||
| case "ClassMethod": | ||
| case "ClassPrivateMethod": | ||
| case "ObjectMethod": | ||
| if (parent.key === node) return !!parent.computed; | ||
| return false; | ||
| case "ObjectProperty": | ||
| if (parent.key === node) return !!parent.computed; | ||
| return !grandparent || grandparent.type !== "ObjectPattern"; | ||
| case "ClassProperty": | ||
| case "ClassAccessorProperty": | ||
| if (parent.key === node) return !!parent.computed; | ||
| return true; | ||
| case "ClassPrivateProperty": return parent.key !== node; | ||
| case "ClassDeclaration": | ||
| case "ClassExpression": return parent.superClass === node; | ||
| case "AssignmentExpression": return parent.right === node; | ||
| case "AssignmentPattern": return parent.right === node; | ||
| case "LabeledStatement": return false; | ||
| case "CatchClause": return false; | ||
| case "RestElement": return false; | ||
| case "BreakStatement": | ||
| case "ContinueStatement": return false; | ||
| case "FunctionDeclaration": | ||
| case "FunctionExpression": return false; | ||
| case "ExportNamespaceSpecifier": | ||
| case "ExportDefaultSpecifier": return false; | ||
| case "ExportSpecifier": | ||
| if (grandparent?.source) return false; | ||
| return parent.local === node; | ||
| case "ImportDefaultSpecifier": | ||
| case "ImportNamespaceSpecifier": | ||
| case "ImportSpecifier": return false; | ||
| case "ImportAttribute": return false; | ||
| case "JSXAttribute": return false; | ||
| case "ObjectPattern": | ||
| case "ArrayPattern": return false; | ||
| case "MetaProperty": return false; | ||
| case "ObjectTypeProperty": return parent.key !== node; | ||
| case "TSEnumMember": return parent.id !== node; | ||
| case "TSPropertySignature": | ||
| if (parent.key === node) return !!parent.computed; | ||
| return true; | ||
| } | ||
| return true; | ||
| } | ||
| /* v8 ignore end */ | ||
| //#endregion | ||
| //#region src/create.ts | ||
| /** | ||
| * Creates a string literal AST node. | ||
| * | ||
| * @param value - The value of the string literal. | ||
| * @returns The string literal AST node. | ||
| */ | ||
| function createStringLiteral(value) { | ||
| return { | ||
| type: "StringLiteral", | ||
| value, | ||
| extra: { | ||
| rawValue: value, | ||
| raw: JSON.stringify(value) | ||
| } | ||
| }; | ||
| } | ||
| /** | ||
| * Creates a TypeScript union type AST node. | ||
| * | ||
| * @param types - An array of TypeScript types. | ||
| * @returns The TypeScript union type AST node. | ||
| */ | ||
| function createTSUnionType(types) { | ||
| return { | ||
| type: "TSUnionType", | ||
| types | ||
| }; | ||
| } | ||
| /** | ||
| * Creates a TypeScript literal type AST node. | ||
| * | ||
| * @param literal - The literal value. | ||
| * @returns The TypeScript literal type AST node. | ||
| */ | ||
| function createTSLiteralType(literal) { | ||
| return { | ||
| type: "TSLiteralType", | ||
| literal | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/extract.ts | ||
| /** | ||
| * Extract identifiers of the given node. | ||
| * @param node The node to extract. | ||
| * @param identifiers The array to store the extracted identifiers. | ||
| * @see https://github.com/vuejs/core/blob/1f6a1102aa09960f76a9af2872ef01e7da8538e3/packages/compiler-core/src/babelUtils.ts#L208 | ||
| */ | ||
| function extractIdentifiers(node, identifiers = []) { | ||
| switch (node.type) { | ||
| case "Identifier": | ||
| identifiers.push(node); | ||
| break; | ||
| case "MemberExpression": { | ||
| let object = node; | ||
| while (object.type === "MemberExpression") object = object.object; | ||
| identifiers.push(object); | ||
| break; | ||
| } | ||
| case "ObjectPattern": | ||
| for (const prop of node.properties) if (prop.type === "RestElement") extractIdentifiers(prop.argument, identifiers); | ||
| else extractIdentifiers(prop.value, identifiers); | ||
| break; | ||
| case "ArrayPattern": | ||
| node.elements.forEach((element) => { | ||
| element && extractIdentifiers(element, identifiers); | ||
| }); | ||
| break; | ||
| case "RestElement": | ||
| extractIdentifiers(node.argument, identifiers); | ||
| break; | ||
| case "AssignmentPattern": | ||
| extractIdentifiers(node.left, identifiers); | ||
| break; | ||
| } | ||
| return identifiers; | ||
| } | ||
| //#endregion | ||
| //#region src/lang.ts | ||
| const REGEX_DTS = /\.d\.[cm]?ts(\?.*)?$/; | ||
| const REGEX_LANG_TS = /^[cm]?tsx?$/; | ||
| const REGEX_LANG_JSX = /^[cm]?[jt]sx$/; | ||
| /** | ||
| * Returns the language (extension name) of a given filename. | ||
| * @param filename - The name of the file. | ||
| * @returns The language of the file. | ||
| */ | ||
| function getLang(filename) { | ||
| if (isDts(filename)) return "dts"; | ||
| return (0, pathe.extname)(filename).replace(/^\./, "").replace(/\?.*$/, ""); | ||
| } | ||
| /** | ||
| * Checks if a filename represents a TypeScript declaration file (.d.ts). | ||
| * @param filename - The name of the file to check. | ||
| * @returns A boolean value indicating whether the filename is a TypeScript declaration file. | ||
| */ | ||
| function isDts(filename) { | ||
| return REGEX_DTS.test(filename); | ||
| } | ||
| /** | ||
| * Checks if the given language (ts, mts, cjs, dts, tsx...) is TypeScript. | ||
| * @param lang - The language to check. | ||
| * @returns A boolean indicating whether the language is TypeScript. | ||
| */ | ||
| function isTs(lang) { | ||
| return !!lang && (lang === "dts" || REGEX_LANG_TS.test(lang)); | ||
| } | ||
| //#endregion | ||
| //#region src/loc.ts | ||
| /** | ||
| * Locates the trailing comma in the given code within the specified range. | ||
| * | ||
| * @param code - The code to search for the trailing comma. | ||
| * @param start - The start index of the range to search within. | ||
| * @param end - The end index of the range to search within. | ||
| * @param comments - Optional array of comments to exclude from the search range. | ||
| * @returns The index of the trailing comma, or -1 if not found. | ||
| */ | ||
| function locateTrailingComma(code, start, end, comments = []) { | ||
| let i = start; | ||
| while (i < end) { | ||
| if (comments.some((c) => i >= c.start && i < c.end)) { | ||
| i++; | ||
| continue; | ||
| } | ||
| const char = code[i]; | ||
| if (["}", ")"].includes(char)) return -1; | ||
| if (char === ",") return i; | ||
| i++; | ||
| } | ||
| return -1; | ||
| } | ||
| //#endregion | ||
| //#region src/parse.ts | ||
| function hasPlugin(plugins, plugin) { | ||
| return plugins.some((p) => (Array.isArray(p) ? p[0] : p) === plugin); | ||
| } | ||
| /** | ||
| * Gets the Babel parser options for the given language. | ||
| * @param lang - The language of the code (optional). | ||
| * @param options - The parser options (optional). | ||
| * @returns The Babel parser options for the given language. | ||
| */ | ||
| function getBabelParserOptions(lang, options = {}) { | ||
| const plugins = [...options.plugins || []]; | ||
| if (isTs(lang)) { | ||
| if (!hasPlugin(plugins, "typescript")) plugins.push(lang === "dts" ? ["typescript", { dts: true }] : "typescript"); | ||
| if (!hasPlugin(plugins, "decorators") && !hasPlugin(plugins, "decorators-legacy")) plugins.push("decorators-legacy"); | ||
| if (!hasPlugin(plugins, "importAttributes") && !hasPlugin(plugins, "importAssertions") && !hasPlugin(plugins, "deprecatedImportAssert")) plugins.push("importAttributes", "deprecatedImportAssert"); | ||
| if (!hasPlugin(plugins, "explicitResourceManagement")) plugins.push("explicitResourceManagement"); | ||
| if (REGEX_LANG_JSX.test(lang) && !hasPlugin(plugins, "jsx")) plugins.push("jsx"); | ||
| } else if (!hasPlugin(plugins, "jsx")) plugins.push("jsx"); | ||
| return { | ||
| sourceType: "module", | ||
| ...options, | ||
| plugins | ||
| }; | ||
| } | ||
| /** | ||
| * Parses the given code using Babel parser. | ||
| * | ||
| * @param code - The code to parse. | ||
| * @param lang - The language of the code (optional). | ||
| * @param options - The parser options (optional). | ||
| * @param options.cache - Whether to cache the result (optional). | ||
| * @returns The parse result, including the program, errors, and comments. | ||
| */ | ||
| function babelParse(code, lang, { cache,...options } = {}) { | ||
| let result; | ||
| if (cache) result = parseCache.get(code); | ||
| if (!result) { | ||
| result = (0, __babel_parser.parse)(code, getBabelParserOptions(lang, options)); | ||
| if (cache) parseCache.set(code, result); | ||
| } | ||
| const { program, type,...rest } = result; | ||
| return { | ||
| ...program, | ||
| ...rest | ||
| }; | ||
| } | ||
| const parseCache = new Map(); | ||
| /** | ||
| * Parses the given code using the Babel parser as an expression. | ||
| * | ||
| * @template T - The type of the parsed AST node. | ||
| * @param {string} code - The code to parse. | ||
| * @param {string} [lang] - The language to parse. Defaults to undefined. | ||
| * @param {ParserOptions} [options] - The options to configure the parser. Defaults to an empty object. | ||
| * @returns {ParseResult<T>} - The result of the parsing operation. | ||
| */ | ||
| function babelParseExpression(code, lang, options = {}) { | ||
| return (0, __babel_parser.parseExpression)(code, getBabelParserOptions(lang, options)); | ||
| } | ||
| //#endregion | ||
| //#region src/resolve.ts | ||
| /** | ||
| * Resolves a string representation of the given node. | ||
| * @param node The node to resolve. | ||
| * @param computed Whether the node is computed or not. | ||
| * @returns The resolved string representation of the node. | ||
| */ | ||
| function resolveString(node, computed = false) { | ||
| if (typeof node === "string") return node; | ||
| else if (node.type === "Identifier") { | ||
| if (computed) throw new TypeError("Invalid Identifier"); | ||
| return node.name; | ||
| } else if (node.type === "PrivateName") return `#${node.id.name}`; | ||
| else if (node.type === "ThisExpression") return "this"; | ||
| else if (node.type === "Super") return "super"; | ||
| return String(resolveLiteral(node)); | ||
| } | ||
| /** | ||
| * Resolves the value of a literal node. | ||
| * @param node The literal node to resolve. | ||
| * @returns The resolved value of the literal node. | ||
| */ | ||
| function resolveLiteral(node) { | ||
| switch (node.type) { | ||
| case "TemplateLiteral": return resolveTemplateLiteral(node); | ||
| case "NullLiteral": return null; | ||
| case "BigIntLiteral": return BigInt(node.value); | ||
| case "RegExpLiteral": return new RegExp(node.pattern, node.flags); | ||
| case "BooleanLiteral": | ||
| case "NumericLiteral": | ||
| case "StringLiteral": return node.value; | ||
| case "DecimalLiteral": return Number(node.value); | ||
| } | ||
| } | ||
| /** | ||
| * Resolves a template literal node into a string. | ||
| * @param node The template literal node to resolve. | ||
| * @returns The resolved string representation of the template literal. | ||
| */ | ||
| function resolveTemplateLiteral(node) { | ||
| return node.quasis.reduce((prev, curr, idx) => { | ||
| const expr = node.expressions[idx]; | ||
| if (expr) { | ||
| if (!isLiteralType(expr)) throw new TypeError("TemplateLiteral expression must be a literal"); | ||
| return prev + curr.value.cooked + resolveLiteral(expr); | ||
| } | ||
| return prev + curr.value.cooked; | ||
| }, ""); | ||
| } | ||
| /** | ||
| * Resolves the identifier node into an array of strings. | ||
| * @param node The identifier node to resolve. | ||
| * @returns An array of resolved strings representing the identifier. | ||
| * @throws TypeError If the identifier is invalid. | ||
| */ | ||
| function resolveIdentifier(node) { | ||
| if (isTypeOf(node, [ | ||
| "Identifier", | ||
| "PrivateName", | ||
| "ThisExpression", | ||
| "Super" | ||
| ])) return [resolveString(node)]; | ||
| const left = node.type === "TSQualifiedName" ? node.left : node.object; | ||
| const right = node.type === "TSQualifiedName" ? node.right : node.property; | ||
| const computed = node.type === "TSQualifiedName" ? false : node.computed; | ||
| if (isTypeOf(left, [ | ||
| "Identifier", | ||
| "MemberExpression", | ||
| "ThisExpression", | ||
| "Super", | ||
| "TSQualifiedName" | ||
| ])) { | ||
| const keys = resolveIdentifier(left); | ||
| if (isTypeOf(right, [ | ||
| "Identifier", | ||
| "PrivateName", | ||
| "Literal" | ||
| ])) keys.push(resolveString(right, computed)); | ||
| else throw new TypeError("Invalid Identifier"); | ||
| return keys; | ||
| } | ||
| throw new TypeError("Invalid Identifier"); | ||
| } | ||
| function tryResolveIdentifier(...args) { | ||
| try { | ||
| return resolveIdentifier(...args); | ||
| } catch { | ||
| return; | ||
| } | ||
| } | ||
| function resolveObjectKey(node, raw = false) { | ||
| const { key, computed } = node; | ||
| switch (key.type) { | ||
| case "StringLiteral": | ||
| case "NumericLiteral": return raw ? key.extra.raw : key.value; | ||
| case "Identifier": | ||
| if (!computed) return raw ? `"${key.name}"` : key.name; | ||
| throw "Cannot resolve computed Identifier"; | ||
| default: throw new SyntaxError(`Unexpected node type: ${key.type}`); | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js | ||
| /** | ||
| * @typedef { import('estree').Node} Node | ||
| * @typedef {{ | ||
| * skip: () => void; | ||
| * remove: () => void; | ||
| * replace: (node: Node) => void; | ||
| * }} WalkerContext | ||
| */ | ||
| var WalkerBase = class { | ||
| constructor() { | ||
| /** @type {boolean} */ | ||
| this.should_skip = false; | ||
| /** @type {boolean} */ | ||
| this.should_remove = false; | ||
| /** @type {Node | null} */ | ||
| this.replacement = null; | ||
| /** @type {WalkerContext} */ | ||
| this.context = { | ||
| skip: () => this.should_skip = true, | ||
| remove: () => this.should_remove = true, | ||
| replace: (node) => this.replacement = node | ||
| }; | ||
| } | ||
| /** | ||
| * @template {Node} Parent | ||
| * @param {Parent | null | undefined} parent | ||
| * @param {keyof Parent | null | undefined} prop | ||
| * @param {number | null | undefined} index | ||
| * @param {Node} node | ||
| */ | ||
| replace(parent, prop, index, node) { | ||
| if (parent && prop) if (index != null) | ||
| /** @type {Array<Node>} */ parent[prop][index] = node; | ||
| else | ||
| /** @type {Node} */ parent[prop] = node; | ||
| } | ||
| /** | ||
| * @template {Node} Parent | ||
| * @param {Parent | null | undefined} parent | ||
| * @param {keyof Parent | null | undefined} prop | ||
| * @param {number | null | undefined} index | ||
| */ | ||
| remove(parent, prop, index) { | ||
| if (parent && prop) if (index !== null && index !== void 0) | ||
| /** @type {Array<Node>} */ parent[prop].splice(index, 1); | ||
| else delete parent[prop]; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/sync.js | ||
| /** | ||
| * @typedef { import('estree').Node} Node | ||
| * @typedef { import('./walker.js').WalkerContext} WalkerContext | ||
| * @typedef {( | ||
| * this: WalkerContext, | ||
| * node: Node, | ||
| * parent: Node | null, | ||
| * key: string | number | symbol | null | undefined, | ||
| * index: number | null | undefined | ||
| * ) => void} SyncHandler | ||
| */ | ||
| var SyncWalker = class extends WalkerBase { | ||
| /** | ||
| * | ||
| * @param {SyncHandler} [enter] | ||
| * @param {SyncHandler} [leave] | ||
| */ | ||
| constructor(enter, leave) { | ||
| super(); | ||
| /** @type {boolean} */ | ||
| this.should_skip = false; | ||
| /** @type {boolean} */ | ||
| this.should_remove = false; | ||
| /** @type {Node | null} */ | ||
| this.replacement = null; | ||
| /** @type {WalkerContext} */ | ||
| this.context = { | ||
| skip: () => this.should_skip = true, | ||
| remove: () => this.should_remove = true, | ||
| replace: (node) => this.replacement = node | ||
| }; | ||
| /** @type {SyncHandler | undefined} */ | ||
| this.enter = enter; | ||
| /** @type {SyncHandler | undefined} */ | ||
| this.leave = leave; | ||
| } | ||
| /** | ||
| * @template {Node} Parent | ||
| * @param {Node} node | ||
| * @param {Parent | null} parent | ||
| * @param {keyof Parent} [prop] | ||
| * @param {number | null} [index] | ||
| * @returns {Node | null} | ||
| */ | ||
| visit(node, parent, prop, index) { | ||
| if (node) { | ||
| if (this.enter) { | ||
| const _should_skip = this.should_skip; | ||
| const _should_remove = this.should_remove; | ||
| const _replacement = this.replacement; | ||
| this.should_skip = false; | ||
| this.should_remove = false; | ||
| this.replacement = null; | ||
| this.enter.call(this.context, node, parent, prop, index); | ||
| if (this.replacement) { | ||
| node = this.replacement; | ||
| this.replace(parent, prop, index, node); | ||
| } | ||
| if (this.should_remove) this.remove(parent, prop, index); | ||
| const skipped = this.should_skip; | ||
| const removed = this.should_remove; | ||
| this.should_skip = _should_skip; | ||
| this.should_remove = _should_remove; | ||
| this.replacement = _replacement; | ||
| if (skipped) return node; | ||
| if (removed) return null; | ||
| } | ||
| /** @type {keyof Node} */ | ||
| let key; | ||
| for (key in node) { | ||
| /** @type {unknown} */ | ||
| const value = node[key]; | ||
| if (value && typeof value === "object") { | ||
| if (Array.isArray(value)) { | ||
| const nodes = value; | ||
| for (let i = 0; i < nodes.length; i += 1) { | ||
| const item = nodes[i]; | ||
| if (isNode$1(item)) { | ||
| if (!this.visit(item, node, key, i)) i--; | ||
| } | ||
| } | ||
| } else if (isNode$1(value)) this.visit(value, node, key, null); | ||
| } | ||
| } | ||
| if (this.leave) { | ||
| const _replacement = this.replacement; | ||
| const _should_remove = this.should_remove; | ||
| this.replacement = null; | ||
| this.should_remove = false; | ||
| this.leave.call(this.context, node, parent, prop, index); | ||
| if (this.replacement) { | ||
| node = this.replacement; | ||
| this.replace(parent, prop, index, node); | ||
| } | ||
| if (this.should_remove) this.remove(parent, prop, index); | ||
| const removed = this.should_remove; | ||
| this.replacement = _replacement; | ||
| this.should_remove = _should_remove; | ||
| if (removed) return null; | ||
| } | ||
| } | ||
| return node; | ||
| } | ||
| }; | ||
| /** | ||
| * Ducktype a node. | ||
| * | ||
| * @param {unknown} value | ||
| * @returns {value is Node} | ||
| */ | ||
| function isNode$1(value) { | ||
| return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string"; | ||
| } | ||
| //#endregion | ||
| //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/async.js | ||
| /** | ||
| * @typedef { import('estree').Node} Node | ||
| * @typedef { import('./walker.js').WalkerContext} WalkerContext | ||
| * @typedef {( | ||
| * this: WalkerContext, | ||
| * node: Node, | ||
| * parent: Node | null, | ||
| * key: string | number | symbol | null | undefined, | ||
| * index: number | null | undefined | ||
| * ) => Promise<void>} AsyncHandler | ||
| */ | ||
| var AsyncWalker = class extends WalkerBase { | ||
| /** | ||
| * | ||
| * @param {AsyncHandler} [enter] | ||
| * @param {AsyncHandler} [leave] | ||
| */ | ||
| constructor(enter, leave) { | ||
| super(); | ||
| /** @type {boolean} */ | ||
| this.should_skip = false; | ||
| /** @type {boolean} */ | ||
| this.should_remove = false; | ||
| /** @type {Node | null} */ | ||
| this.replacement = null; | ||
| /** @type {WalkerContext} */ | ||
| this.context = { | ||
| skip: () => this.should_skip = true, | ||
| remove: () => this.should_remove = true, | ||
| replace: (node) => this.replacement = node | ||
| }; | ||
| /** @type {AsyncHandler | undefined} */ | ||
| this.enter = enter; | ||
| /** @type {AsyncHandler | undefined} */ | ||
| this.leave = leave; | ||
| } | ||
| /** | ||
| * @template {Node} Parent | ||
| * @param {Node} node | ||
| * @param {Parent | null} parent | ||
| * @param {keyof Parent} [prop] | ||
| * @param {number | null} [index] | ||
| * @returns {Promise<Node | null>} | ||
| */ | ||
| async visit(node, parent, prop, index) { | ||
| if (node) { | ||
| if (this.enter) { | ||
| const _should_skip = this.should_skip; | ||
| const _should_remove = this.should_remove; | ||
| const _replacement = this.replacement; | ||
| this.should_skip = false; | ||
| this.should_remove = false; | ||
| this.replacement = null; | ||
| await this.enter.call(this.context, node, parent, prop, index); | ||
| if (this.replacement) { | ||
| node = this.replacement; | ||
| this.replace(parent, prop, index, node); | ||
| } | ||
| if (this.should_remove) this.remove(parent, prop, index); | ||
| const skipped = this.should_skip; | ||
| const removed = this.should_remove; | ||
| this.should_skip = _should_skip; | ||
| this.should_remove = _should_remove; | ||
| this.replacement = _replacement; | ||
| if (skipped) return node; | ||
| if (removed) return null; | ||
| } | ||
| /** @type {keyof Node} */ | ||
| let key; | ||
| for (key in node) { | ||
| /** @type {unknown} */ | ||
| const value = node[key]; | ||
| if (value && typeof value === "object") { | ||
| if (Array.isArray(value)) { | ||
| const nodes = value; | ||
| for (let i = 0; i < nodes.length; i += 1) { | ||
| const item = nodes[i]; | ||
| if (isNode(item)) { | ||
| if (!await this.visit(item, node, key, i)) i--; | ||
| } | ||
| } | ||
| } else if (isNode(value)) await this.visit(value, node, key, null); | ||
| } | ||
| } | ||
| if (this.leave) { | ||
| const _replacement = this.replacement; | ||
| const _should_remove = this.should_remove; | ||
| this.replacement = null; | ||
| this.should_remove = false; | ||
| await this.leave.call(this.context, node, parent, prop, index); | ||
| if (this.replacement) { | ||
| node = this.replacement; | ||
| this.replace(parent, prop, index, node); | ||
| } | ||
| if (this.should_remove) this.remove(parent, prop, index); | ||
| const removed = this.should_remove; | ||
| this.replacement = _replacement; | ||
| this.should_remove = _should_remove; | ||
| if (removed) return null; | ||
| } | ||
| } | ||
| return node; | ||
| } | ||
| }; | ||
| /** | ||
| * Ducktype a node. | ||
| * | ||
| * @param {unknown} value | ||
| * @returns {value is Node} | ||
| */ | ||
| function isNode(value) { | ||
| return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string"; | ||
| } | ||
| //#endregion | ||
| //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/index.js | ||
| /** | ||
| * @typedef {import('estree').Node} Node | ||
| * @typedef {import('./sync.js').SyncHandler} SyncHandler | ||
| * @typedef {import('./async.js').AsyncHandler} AsyncHandler | ||
| */ | ||
| /** | ||
| * @param {Node} ast | ||
| * @param {{ | ||
| * enter?: SyncHandler | ||
| * leave?: SyncHandler | ||
| * }} walker | ||
| * @returns {Node | null} | ||
| */ | ||
| function walk(ast, { enter, leave }) { | ||
| const instance = new SyncWalker(enter, leave); | ||
| return instance.visit(ast, null); | ||
| } | ||
| /** | ||
| * @param {Node} ast | ||
| * @param {{ | ||
| * enter?: AsyncHandler | ||
| * leave?: AsyncHandler | ||
| * }} walker | ||
| * @returns {Promise<Node | null>} | ||
| */ | ||
| async function asyncWalk(ast, { enter, leave }) { | ||
| const instance = new AsyncWalker(enter, leave); | ||
| return await instance.visit(ast, null); | ||
| } | ||
| //#endregion | ||
| //#region src/walk.ts | ||
| /** | ||
| * Walks the AST and applies the provided handlers. | ||
| * | ||
| * @template T - The type of the AST node. | ||
| * @param {T} node - The root node of the AST. | ||
| * @param {WalkHandlers<T, void>} hooks - The handlers to be applied during the walk. | ||
| * @returns {T | null} - The modified AST node or null if the node is removed. | ||
| */ | ||
| const walkAST = walk; | ||
| /** | ||
| * Asynchronously walks the AST starting from the given node, | ||
| * applying the provided handlers to each node encountered. | ||
| * | ||
| * @template T - The type of the AST node. | ||
| * @param {T} node - The root node of the AST. | ||
| * @param {WalkHandlers<T, Promise<void>>} handlers - The handlers to be applied to each node. | ||
| * @returns {Promise<T | null>} - A promise that resolves to the modified AST or null if the AST is empty. | ||
| */ | ||
| const walkASTAsync = asyncWalk; | ||
| /** | ||
| * Walks through an ImportDeclaration node and populates the provided imports object. | ||
| * | ||
| * @param imports - The object to store the import bindings. | ||
| * @param node - The ImportDeclaration node to walk through. | ||
| */ | ||
| function walkImportDeclaration(imports, node) { | ||
| if (node.importKind === "type") return; | ||
| const source = node.source.value; | ||
| for (const specifier of node.specifiers) { | ||
| const isType = specifier.type === "ImportSpecifier" && specifier.importKind === "type"; | ||
| const local = specifier.local.name; | ||
| const imported = specifier.type === "ImportSpecifier" ? resolveString(specifier.imported) : specifier.type === "ImportNamespaceSpecifier" ? "*" : "default"; | ||
| imports[local] = { | ||
| source, | ||
| local, | ||
| imported, | ||
| specifier, | ||
| isType | ||
| }; | ||
| } | ||
| } | ||
| /** | ||
| * Walks through an ExportDeclaration node and populates the exports object with the relevant information. | ||
| * @param exports - The object to store the export information. | ||
| * @param node - The ExportDeclaration node to process. | ||
| */ | ||
| function walkExportDeclaration(exports$1, node) { | ||
| let local; | ||
| let exported; | ||
| let isType; | ||
| let source; | ||
| let specifier; | ||
| let declaration; | ||
| function setExport() { | ||
| exports$1[exported] = { | ||
| source, | ||
| local, | ||
| exported, | ||
| specifier, | ||
| isType, | ||
| declaration | ||
| }; | ||
| } | ||
| if (node.type === "ExportNamedDeclaration") { | ||
| if (node.specifiers.length > 0) for (const s of node.specifiers) { | ||
| const isExportSpecifier = s.type === "ExportSpecifier"; | ||
| isType = node.exportKind === "type" || isExportSpecifier && s.exportKind === "type"; | ||
| local = isExportSpecifier ? s.local.name : s.type === "ExportNamespaceSpecifier" ? "*" : "default"; | ||
| source = node.source ? node.source.value : null; | ||
| exported = isExportSpecifier ? resolveString(s.exported) : s.exported.name; | ||
| declaration = null; | ||
| specifier = s; | ||
| setExport(); | ||
| } | ||
| else if (node.specifiers.length === 0 && !!node.declaration) { | ||
| if (node.declaration.type === "VariableDeclaration") for (const decl of node.declaration.declarations) { | ||
| /* c8 ignore next 4 */ | ||
| if (decl.id.type !== "Identifier") continue; | ||
| local = resolveString(decl.id); | ||
| source = null; | ||
| exported = local; | ||
| isType = node.exportKind === "type"; | ||
| declaration = node.declaration; | ||
| specifier = null; | ||
| setExport(); | ||
| } | ||
| else if ("id" in node.declaration && node.declaration.id && node.declaration.id.type === "Identifier") { | ||
| local = resolveString(node.declaration.id); | ||
| source = null; | ||
| exported = local; | ||
| isType = node.exportKind === "type"; | ||
| declaration = node.declaration; | ||
| specifier = null; | ||
| setExport(); | ||
| } | ||
| } | ||
| return; | ||
| } else if (node.type === "ExportDefaultDeclaration") { | ||
| if (isExpressionType(node.declaration)) local = "name" in node.declaration ? node.declaration.name : "default"; | ||
| else local = resolveString(node.declaration.id || "default"); | ||
| source = null; | ||
| exported = "default"; | ||
| isType = false; | ||
| declaration = node.declaration; | ||
| specifier = null; | ||
| } else { | ||
| local = "*"; | ||
| source = resolveString(node.source); | ||
| exported = "*"; | ||
| isType = node.exportKind === "type"; | ||
| specifier = null; | ||
| declaration = null; | ||
| } | ||
| setExport(); | ||
| } | ||
| //#endregion | ||
| //#region src/scope.ts | ||
| const extractors = { | ||
| ArrayPattern(names, param) { | ||
| for (const element of param.elements) if (element) extractors[element.type](names, element); | ||
| }, | ||
| AssignmentPattern(names, param) { | ||
| extractors[param.left.type](names, param.left); | ||
| }, | ||
| Identifier(names, param) { | ||
| names.push(param.name); | ||
| }, | ||
| MemberExpression() {}, | ||
| ObjectPattern(names, param) { | ||
| for (const prop of param.properties) if (prop.type === "RestElement") extractors.RestElement(names, prop); | ||
| else extractors[prop.value.type](names, prop.value); | ||
| }, | ||
| RestElement(names, param) { | ||
| extractors[param.argument.type](names, param.argument); | ||
| } | ||
| }; | ||
| function extractAssignedNames(param) { | ||
| const names = []; | ||
| extractors[param.type](names, param); | ||
| return names; | ||
| } | ||
| const blockDeclarations = { | ||
| const: true, | ||
| let: true | ||
| }; | ||
| /** | ||
| * Represents a scope. | ||
| */ | ||
| var Scope = class { | ||
| parent; | ||
| isBlockScope; | ||
| declarations; | ||
| constructor(options = {}) { | ||
| this.parent = options.parent; | ||
| this.isBlockScope = !!options.block; | ||
| this.declarations = Object.create(null); | ||
| if (options.params) options.params.forEach((param) => { | ||
| extractAssignedNames(param).forEach((name) => { | ||
| this.declarations[name] = true; | ||
| }); | ||
| }); | ||
| } | ||
| addDeclaration(node, isBlockDeclaration, isVar) { | ||
| if (!isBlockDeclaration && this.isBlockScope) this.parent.addDeclaration(node, isBlockDeclaration, isVar); | ||
| else if (node.id) extractAssignedNames(node.id).forEach((name) => { | ||
| this.declarations[name] = true; | ||
| }); | ||
| } | ||
| contains(name) { | ||
| return this.declarations[name] || (this.parent ? this.parent.contains(name) : false); | ||
| } | ||
| }; | ||
| /** | ||
| * Attaches scopes to the given AST | ||
| * | ||
| * @param ast - The AST to attach scopes to. | ||
| * @param propertyName - The name of the property to attach the scopes to. Default is 'scope'. | ||
| * @returns The root scope of the AST. | ||
| */ | ||
| function attachScopes(ast, propertyName = "scope") { | ||
| let scope = new Scope(); | ||
| walkAST(ast, { | ||
| enter(node, parent) { | ||
| if (/(?:Function|Class)Declaration/.test(node.type)) scope.addDeclaration(node, false, false); | ||
| if (node.type === "VariableDeclaration") { | ||
| const { kind } = node; | ||
| const isBlockDeclaration = blockDeclarations[kind]; | ||
| node.declarations.forEach((declaration) => { | ||
| scope.addDeclaration(declaration, isBlockDeclaration, true); | ||
| }); | ||
| } | ||
| let newScope; | ||
| if (/Function/.test(node.type)) { | ||
| const func = node; | ||
| newScope = new Scope({ | ||
| parent: scope, | ||
| block: false, | ||
| params: func.params | ||
| }); | ||
| if (func.type === "FunctionExpression" && func.id) newScope.addDeclaration(func, false, false); | ||
| } | ||
| if (/For(?:In|Of)?Statement/.test(node.type)) newScope = new Scope({ | ||
| parent: scope, | ||
| block: true | ||
| }); | ||
| if (node.type === "BlockStatement" && !/Function/.test(parent.type)) newScope = new Scope({ | ||
| parent: scope, | ||
| block: true | ||
| }); | ||
| if (node.type === "CatchClause") newScope = new Scope({ | ||
| parent: scope, | ||
| params: node.param ? [node.param] : [], | ||
| block: true | ||
| }); | ||
| if (newScope) { | ||
| Object.defineProperty(node, propertyName, { | ||
| value: newScope, | ||
| configurable: true | ||
| }); | ||
| scope = newScope; | ||
| } | ||
| }, | ||
| leave(node) { | ||
| if (node[propertyName]) scope = scope.parent; | ||
| } | ||
| }); | ||
| return scope; | ||
| } | ||
| /* c8 ignore stop */ | ||
| //#endregion | ||
| //#region src/utils.ts | ||
| const TS_NODE_TYPES = [ | ||
| "TSAsExpression", | ||
| "TSTypeAssertion", | ||
| "TSNonNullExpression", | ||
| "TSInstantiationExpression", | ||
| "TSSatisfiesExpression" | ||
| ]; | ||
| /** | ||
| * Unwraps a TypeScript node by recursively traversing the AST until a non-TypeScript node is found. | ||
| * @param node - The TypeScript node to unwrap. | ||
| * @returns The unwrapped node. | ||
| */ | ||
| function unwrapTSNode(node) { | ||
| if (isTypeOf(node, TS_NODE_TYPES)) return unwrapTSNode(node.expression); | ||
| else return node; | ||
| } | ||
| /** | ||
| * Escapes a raw key by checking if it needs to be wrapped with quotes or not. | ||
| * | ||
| * @param rawKey - The raw key to escape. | ||
| * @returns The escaped key. | ||
| */ | ||
| function escapeKey(rawKey) { | ||
| if (String(+rawKey) === rawKey) return rawKey; | ||
| try { | ||
| const node = (0, __babel_parser.parseExpression)(`({${rawKey}: 1})`); | ||
| if (node.properties[0].key.type === "Identifier") return rawKey; | ||
| } catch {} | ||
| return JSON.stringify(rawKey); | ||
| } | ||
| //#endregion | ||
| exports.REGEX_DTS = REGEX_DTS | ||
| exports.REGEX_LANG_JSX = REGEX_LANG_JSX | ||
| exports.REGEX_LANG_TS = REGEX_LANG_TS | ||
| exports.Scope = Scope | ||
| exports.TS_NODE_TYPES = TS_NODE_TYPES | ||
| exports.attachScopes = attachScopes | ||
| exports.babelParse = babelParse | ||
| exports.babelParseExpression = babelParseExpression | ||
| exports.createStringLiteral = createStringLiteral | ||
| exports.createTSLiteralType = createTSLiteralType | ||
| exports.createTSUnionType = createTSUnionType | ||
| exports.escapeKey = escapeKey | ||
| exports.extractIdentifiers = extractIdentifiers | ||
| exports.getBabelParserOptions = getBabelParserOptions | ||
| exports.getLang = getLang | ||
| exports.isCallOf = isCallOf | ||
| exports.isDeclarationType = isDeclarationType | ||
| exports.isDts = isDts | ||
| exports.isExpressionType = isExpressionType | ||
| exports.isFunctionType = isFunctionType | ||
| exports.isIdentifierOf = isIdentifierOf | ||
| exports.isLiteralType = isLiteralType | ||
| exports.isReferenced = isReferenced | ||
| exports.isTaggedFunctionCallOf = isTaggedFunctionCallOf | ||
| exports.isTs = isTs | ||
| exports.isTypeOf = isTypeOf | ||
| exports.locateTrailingComma = locateTrailingComma | ||
| exports.parseCache = parseCache | ||
| exports.resolveIdentifier = resolveIdentifier | ||
| exports.resolveLiteral = resolveLiteral | ||
| exports.resolveObjectKey = resolveObjectKey | ||
| exports.resolveString = resolveString | ||
| exports.resolveTemplateLiteral = resolveTemplateLiteral | ||
| exports.tryResolveIdentifier = tryResolveIdentifier | ||
| exports.unwrapTSNode = unwrapTSNode | ||
| exports.walkAST = walkAST | ||
| exports.walkASTAsync = walkASTAsync | ||
| exports.walkExportDeclaration = walkExportDeclaration | ||
| exports.walkImportDeclaration = walkImportDeclaration |
-386
| import * as t$7 from "@babel/types"; | ||
| import * as t$6 from "@babel/types"; | ||
| import * as t$5 from "@babel/types"; | ||
| import * as t$4 from "@babel/types"; | ||
| import * as t$3 from "@babel/types"; | ||
| import * as t$2 from "@babel/types"; | ||
| import * as t$1 from "@babel/types"; | ||
| import * as t from "@babel/types"; | ||
| import { Node } from "@babel/types"; | ||
| import { ParseError, ParseResult, ParserOptions } from "@babel/parser"; | ||
| //#region src/check.d.ts | ||
| /** | ||
| * All possible node types. | ||
| */ | ||
| type NodeType = t$7.Node["type"] | "Function" | "Literal" | "Expression"; | ||
| /** | ||
| * Represents the corresponding node based on the given node type. | ||
| */ | ||
| type GetNode<K extends NodeType> = K extends "Function" ? t$7.Function : K extends "Literal" ? t$7.Literal : Extract<t$7.Node, { | ||
| type: K | ||
| }>; | ||
| /** | ||
| * Checks if the given node matches the specified type(s). | ||
| * | ||
| * @param node - The node to check. | ||
| * @param types - The type(s) to match against. It can be a single type or an array of types. | ||
| * @returns True if the node matches the specified type(s), false otherwise. | ||
| */ | ||
| declare function isTypeOf<K extends NodeType>(node: t$7.Node | undefined | null, types: K | Readonly<K[]>): node is GetNode<K>; | ||
| /** | ||
| * Checks if the given node is a CallExpression with the specified callee. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The callee to compare against. It can be a string, an array of strings, or a function that takes a string and returns a boolean. | ||
| * @returns True if the node is a CallExpression with the specified callee, false otherwise. | ||
| */ | ||
| declare function isCallOf(node: t$7.Node | null | undefined, test: string | string[] | ((id: string) => boolean)): node is t$7.CallExpression; | ||
| /** | ||
| * Checks if the given node is a TaggedTemplateExpression with the specified callee. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The callee to compare against. It can be a string, an array of strings, or a function that takes a string and returns a boolean. | ||
| * @returns True if the node is a TaggedTemplateExpression with the specified callee, false otherwise. | ||
| */ | ||
| declare function isTaggedFunctionCallOf(node: t$7.Node | null | undefined, test: string | string[] | ((id: string) => boolean)): node is t$7.TaggedTemplateExpression; | ||
| /** | ||
| * Checks if the given node is an Identifier with the specified name. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param test - The name to compare against. It can be a string or an array of strings. | ||
| * @returns True if the node is an Identifier with the specified name, false otherwise. | ||
| */ | ||
| declare function isIdentifierOf(node: t$7.Node | undefined | null, test: string | string[] | ((id: string) => boolean)): node is t$7.Identifier; | ||
| /** | ||
| * Checks if the given node is a literal type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a literal type, false otherwise. | ||
| */ | ||
| declare function isLiteralType(node: t$7.Node | undefined | null): node is t$7.Literal; | ||
| /** | ||
| * Checks if the given node is a function type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a function type, false otherwise. | ||
| */ | ||
| declare function isFunctionType(node: t$7.Node | undefined | null): node is t$7.Function; | ||
| /** | ||
| * Checks if the given node is a declaration type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is a declaration type, false otherwise. | ||
| */ | ||
| declare function isDeclarationType(node: t$7.Node | undefined | null): node is t$7.Declaration; | ||
| /** | ||
| * Checks if the given node is an expression type. | ||
| * | ||
| * @param node - The node to check. | ||
| * @returns True if the node is an expression type, false otherwise. | ||
| */ | ||
| declare function isExpressionType(node: t$7.Node | null | undefined): node is t$7.Expression; | ||
| /* v8 ignore start */ | ||
| /** | ||
| * Checks if the input `node` is a reference to a bound variable. | ||
| * | ||
| * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts | ||
| * | ||
| * To avoid runtime dependency on `@babel/types` (which includes process references) | ||
| * This file should not change very often in babel but we may need to keep it | ||
| * up-to-date from time to time. | ||
| * | ||
| * @param node - The node to check. | ||
| * @param parent - The parent node of the input `node`. | ||
| * @param grandparent - The grandparent node of the input `node`. | ||
| * @returns True if the input `node` is a reference to a bound variable, false otherwise. | ||
| */ | ||
| declare function isReferenced(node: t$7.Node, parent: t$7.Node, grandparent?: t$7.Node): boolean; | ||
| //#endregion | ||
| //#region src/create.d.ts | ||
| /** | ||
| * Creates a string literal AST node. | ||
| * | ||
| * @param value - The value of the string literal. | ||
| * @returns The string literal AST node. | ||
| */ | ||
| declare function createStringLiteral(value: string): t$6.StringLiteral; | ||
| /** | ||
| * Creates a TypeScript union type AST node. | ||
| * | ||
| * @param types - An array of TypeScript types. | ||
| * @returns The TypeScript union type AST node. | ||
| */ | ||
| declare function createTSUnionType(types: t$6.TSType[]): t$6.TSUnionType; | ||
| /** | ||
| * Creates a TypeScript literal type AST node. | ||
| * | ||
| * @param literal - The literal value. | ||
| * @returns The TypeScript literal type AST node. | ||
| */ | ||
| declare function createTSLiteralType(literal: t$6.TSLiteralType["literal"]): t$6.TSLiteralType; | ||
| //#endregion | ||
| //#region src/extract.d.ts | ||
| /** | ||
| * Extract identifiers of the given node. | ||
| * @param node The node to extract. | ||
| * @param identifiers The array to store the extracted identifiers. | ||
| * @see https://github.com/vuejs/core/blob/1f6a1102aa09960f76a9af2872ef01e7da8538e3/packages/compiler-core/src/babelUtils.ts#L208 | ||
| */ | ||
| declare function extractIdentifiers(node: t$5.Node, identifiers?: t$5.Identifier[]): t$5.Identifier[]; | ||
| //#endregion | ||
| //#region src/lang.d.ts | ||
| declare const REGEX_DTS: RegExp; | ||
| declare const REGEX_LANG_TS: RegExp; | ||
| declare const REGEX_LANG_JSX: RegExp; | ||
| /** | ||
| * Returns the language (extension name) of a given filename. | ||
| * @param filename - The name of the file. | ||
| * @returns The language of the file. | ||
| */ | ||
| declare function getLang(filename: string): string; | ||
| /** | ||
| * Checks if a filename represents a TypeScript declaration file (.d.ts). | ||
| * @param filename - The name of the file to check. | ||
| * @returns A boolean value indicating whether the filename is a TypeScript declaration file. | ||
| */ | ||
| declare function isDts(filename: string): boolean; | ||
| /** | ||
| * Checks if the given language (ts, mts, cjs, dts, tsx...) is TypeScript. | ||
| * @param lang - The language to check. | ||
| * @returns A boolean indicating whether the language is TypeScript. | ||
| */ | ||
| declare function isTs(lang?: string): boolean; | ||
| //#endregion | ||
| //#region src/loc.d.ts | ||
| /** | ||
| * Locates the trailing comma in the given code within the specified range. | ||
| * | ||
| * @param code - The code to search for the trailing comma. | ||
| * @param start - The start index of the range to search within. | ||
| * @param end - The end index of the range to search within. | ||
| * @param comments - Optional array of comments to exclude from the search range. | ||
| * @returns The index of the trailing comma, or -1 if not found. | ||
| */ | ||
| declare function locateTrailingComma(code: string, start: number, end: number, comments?: t$4.Comment[]): number; | ||
| //#endregion | ||
| //#region src/parse.d.ts | ||
| /** | ||
| * Gets the Babel parser options for the given language. | ||
| * @param lang - The language of the code (optional). | ||
| * @param options - The parser options (optional). | ||
| * @returns The Babel parser options for the given language. | ||
| */ | ||
| declare function getBabelParserOptions(lang?: string, options?: ParserOptions): ParserOptions; | ||
| /** | ||
| * Parses the given code using Babel parser. | ||
| * | ||
| * @param code - The code to parse. | ||
| * @param lang - The language of the code (optional). | ||
| * @param options - The parser options (optional). | ||
| * @param options.cache - Whether to cache the result (optional). | ||
| * @returns The parse result, including the program, errors, and comments. | ||
| */ | ||
| declare function babelParse(code: string, lang?: string, { cache,...options }?: ParserOptions & { | ||
| cache?: boolean | ||
| }): t$3.Program & Omit<ParseResult<t$3.File>, "type" | "program">; | ||
| declare const parseCache: Map<string, ParseResult<t$3.File>>; | ||
| /** | ||
| * Parses the given code using the Babel parser as an expression. | ||
| * | ||
| * @template T - The type of the parsed AST node. | ||
| * @param {string} code - The code to parse. | ||
| * @param {string} [lang] - The language to parse. Defaults to undefined. | ||
| * @param {ParserOptions} [options] - The options to configure the parser. Defaults to an empty object. | ||
| * @returns {ParseResult<T>} - The result of the parsing operation. | ||
| */ | ||
| declare function babelParseExpression<T extends t$3.Node = t$3.Expression>(code: string, lang?: string, options?: ParserOptions): T & { | ||
| errors: null | ParseError[] | ||
| }; | ||
| //#endregion | ||
| //#region src/resolve.d.ts | ||
| /** | ||
| * Resolves a string representation of the given node. | ||
| * @param node The node to resolve. | ||
| * @param computed Whether the node is computed or not. | ||
| * @returns The resolved string representation of the node. | ||
| */ | ||
| declare function resolveString(node: string | t$2.Identifier | t$2.Literal | t$2.PrivateName | t$2.ThisExpression | t$2.Super, computed?: boolean): string; | ||
| /** | ||
| * Resolves the value of a literal node. | ||
| * @param node The literal node to resolve. | ||
| * @returns The resolved value of the literal node. | ||
| */ | ||
| declare function resolveLiteral(node: t$2.Literal): string | number | boolean | null | RegExp | bigint; | ||
| /** | ||
| * Resolves a template literal node into a string. | ||
| * @param node The template literal node to resolve. | ||
| * @returns The resolved string representation of the template literal. | ||
| */ | ||
| declare function resolveTemplateLiteral(node: t$2.TemplateLiteral): string; | ||
| /** | ||
| * Resolves the identifier node into an array of strings. | ||
| * @param node The identifier node to resolve. | ||
| * @returns An array of resolved strings representing the identifier. | ||
| * @throws TypeError If the identifier is invalid. | ||
| */ | ||
| declare function resolveIdentifier(node: t$2.Identifier | t$2.PrivateName | t$2.MemberExpression | t$2.ThisExpression | t$2.Super | t$2.TSEntityName): string[]; | ||
| declare function tryResolveIdentifier(...args: Parameters<typeof resolveIdentifier>): string[] | undefined; | ||
| type ObjectPropertyLike = t$2.ObjectMethod | t$2.ObjectProperty | t$2.TSMethodSignature | t$2.TSPropertySignature | t$2.ImportAttribute; | ||
| /** | ||
| * Resolves the key of an object property-like node. | ||
| * @param node The object property-like node to resolve. | ||
| * @param raw Whether to return the raw value of the key or not. | ||
| * @returns The resolved key of the object property-like node. | ||
| */ | ||
| declare function resolveObjectKey(node: ObjectPropertyLike, raw?: false): string | number; | ||
| declare function resolveObjectKey(node: ObjectPropertyLike, raw: true): string; | ||
| //#endregion | ||
| //#region src/scope.d.ts | ||
| interface AttachedScope { | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean | ||
| }; | ||
| addDeclaration: (node: Node, isBlockDeclaration: boolean, isVar: boolean) => void; | ||
| contains: (name: string) => boolean; | ||
| } | ||
| type WithScope<T> = T & { | ||
| scope?: AttachedScope | ||
| }; | ||
| /** | ||
| * Options for creating a new scope. | ||
| */ | ||
| interface ScopeOptions { | ||
| parent?: AttachedScope; | ||
| block?: boolean; | ||
| params?: Node[]; | ||
| } | ||
| /** | ||
| * Represents a scope. | ||
| */ | ||
| declare class Scope implements AttachedScope { | ||
| parent?: AttachedScope; | ||
| isBlockScope: boolean; | ||
| declarations: { | ||
| [key: string]: boolean | ||
| }; | ||
| constructor(options?: ScopeOptions); | ||
| addDeclaration(node: Node, isBlockDeclaration: boolean, isVar: boolean): void; | ||
| contains(name: string): boolean; | ||
| } | ||
| /** | ||
| * Attaches scopes to the given AST | ||
| * | ||
| * @param ast - The AST to attach scopes to. | ||
| * @param propertyName - The name of the property to attach the scopes to. Default is 'scope'. | ||
| * @returns The root scope of the AST. | ||
| */ | ||
| declare function attachScopes(ast: Node, propertyName?: string): Scope; | ||
| //#endregion | ||
| //#region src/types.d.ts | ||
| /** | ||
| * A type that represents a literal union. | ||
| */ | ||
| type LiteralUnion< | ||
| LiteralType, | ||
| BaseType extends null | undefined | string | number | boolean | symbol | bigint = string | ||
| > = LiteralType | (BaseType & Record<never, never>); | ||
| //#endregion | ||
| //#region src/utils.d.ts | ||
| declare const TS_NODE_TYPES: readonly ["TSAsExpression", "TSTypeAssertion", "TSNonNullExpression", "TSInstantiationExpression", "TSSatisfiesExpression"]; | ||
| /** | ||
| * Unwraps a TypeScript node by recursively traversing the AST until a non-TypeScript node is found. | ||
| * @param node - The TypeScript node to unwrap. | ||
| * @returns The unwrapped node. | ||
| */ | ||
| declare function unwrapTSNode(node: t$1.Node): t$1.Node; | ||
| /** | ||
| * Escapes a raw key by checking if it needs to be wrapped with quotes or not. | ||
| * | ||
| * @param rawKey - The raw key to escape. | ||
| * @returns The escaped key. | ||
| */ | ||
| declare function escapeKey(rawKey: string): string; | ||
| //#endregion | ||
| //#region src/walk.d.ts | ||
| interface WalkThis<T> { | ||
| skip: () => void; | ||
| remove: () => void; | ||
| replace: (node: T) => void; | ||
| } | ||
| type WalkCallback< | ||
| T, | ||
| R | ||
| > = (this: WalkThis<T>, node: T, parent: T | null | undefined, key: string | null | undefined, index: number | null | undefined) => R; | ||
| interface WalkHandlers< | ||
| T, | ||
| R | ||
| > { | ||
| enter?: WalkCallback<T, R>; | ||
| leave?: WalkCallback<T, R>; | ||
| } | ||
| /** | ||
| * Walks the AST and applies the provided handlers. | ||
| * | ||
| * @template T - The type of the AST node. | ||
| * @param {T} node - The root node of the AST. | ||
| * @param {WalkHandlers<T, void>} hooks - The handlers to be applied during the walk. | ||
| * @returns {T | null} - The modified AST node or null if the node is removed. | ||
| */ | ||
| declare const walkAST: <T = t.Node>(node: NoInfer<T>, hooks: WalkHandlers<T, void>) => T | null; | ||
| /** | ||
| * Asynchronously walks the AST starting from the given node, | ||
| * applying the provided handlers to each node encountered. | ||
| * | ||
| * @template T - The type of the AST node. | ||
| * @param {T} node - The root node of the AST. | ||
| * @param {WalkHandlers<T, Promise<void>>} handlers - The handlers to be applied to each node. | ||
| * @returns {Promise<T | null>} - A promise that resolves to the modified AST or null if the AST is empty. | ||
| */ | ||
| declare const walkASTAsync: <T = t.Node>(node: NoInfer<T>, handlers: WalkHandlers<T, Promise<void>>) => Promise<T | null>; | ||
| interface ImportBinding { | ||
| local: string; | ||
| imported: LiteralUnion<"*" | "default">; | ||
| source: string; | ||
| specifier: t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier; | ||
| isType: boolean; | ||
| } | ||
| /** | ||
| * Walks through an ImportDeclaration node and populates the provided imports object. | ||
| * | ||
| * @param imports - The object to store the import bindings. | ||
| * @param node - The ImportDeclaration node to walk through. | ||
| */ | ||
| declare function walkImportDeclaration(imports: Record<string, ImportBinding>, node: t.ImportDeclaration): void; | ||
| /** | ||
| * Represents an export binding. | ||
| */ | ||
| interface ExportBinding { | ||
| local: string; | ||
| exported: LiteralUnion<"*" | "default">; | ||
| isType: boolean; | ||
| source: string | null; | ||
| specifier: t.ExportSpecifier | t.ExportDefaultSpecifier | t.ExportNamespaceSpecifier | null; | ||
| declaration: t.Declaration | t.ExportDefaultDeclaration["declaration"] | null; | ||
| } | ||
| /** | ||
| * Walks through an ExportDeclaration node and populates the exports object with the relevant information. | ||
| * @param exports - The object to store the export information. | ||
| * @param node - The ExportDeclaration node to process. | ||
| */ | ||
| declare function walkExportDeclaration(exports: Record<string, ExportBinding>, node: t.ExportDeclaration): void; | ||
| //#endregion | ||
| export { AttachedScope, ExportBinding, GetNode, ImportBinding, LiteralUnion, NodeType, ObjectPropertyLike, REGEX_DTS, REGEX_LANG_JSX, REGEX_LANG_TS, Scope, ScopeOptions, TS_NODE_TYPES, WithScope, attachScopes, babelParse, babelParseExpression, createStringLiteral, createTSLiteralType, createTSUnionType, escapeKey, extractIdentifiers, getBabelParserOptions, getLang, isCallOf, isDeclarationType, isDts, isExpressionType, isFunctionType, isIdentifierOf, isLiteralType, isReferenced, isTaggedFunctionCallOf, isTs, isTypeOf, locateTrailingComma, parseCache, resolveIdentifier, resolveLiteral, resolveObjectKey, resolveString, resolveTemplateLiteral, tryResolveIdentifier, unwrapTSNode, walkAST, walkASTAsync, walkExportDeclaration, walkImportDeclaration }; |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
1
-50%53834
-49.06%5
-28.57%1441
-44.19%Updated