From dfa26255880ed3bad3d6954f2ba01cd31c5736fb Mon Sep 17 00:00:00 2001 From: Edoardo Cavazza Date: Fri, 8 Mar 2024 18:08:14 +0100 Subject: [PATCH] Migrate to oxc parser --- .changeset/kind-sloths-rush.md | 46 ++ packages/cjs-to-esm/lib/index.js | 170 ++++---- packages/es-dev-server/build.js | 2 +- packages/es-test-runner/build.js | 2 +- packages/esbuild-plugin-html/build.js | 2 +- packages/esbuild-plugin-meta-url/lib/index.js | 385 +++++++---------- .../lib/index.js | 84 ++-- .../esbuild-plugin-unwebpack/lib/index.js | 273 ++++++------ packages/esbuild-plugin-worker/lib/index.js | 409 +++++++++--------- packages/estransform/build.js | 2 +- packages/estransform/lib/helpers.js | 281 ------------ packages/estransform/lib/index.js | 1 - packages/estransform/lib/parser.js | 88 ++-- packages/estransform/lib/types.js | 6 - packages/estransform/modules.d.ts | 23 - packages/estransform/package.json | 4 +- packages/estransform/tsconfig.json | 2 +- packages/rna-dev-server/build.js | 2 +- packages/rna-logger/build.js | 2 +- packages/rna/build.js | 2 +- packages/wds-plugin-hmr/build.js | 2 +- packages/wtr-mocha-reporter/build.js | 2 +- yarn.lock | 173 ++++---- 23 files changed, 786 insertions(+), 1177 deletions(-) create mode 100644 .changeset/kind-sloths-rush.md delete mode 100644 packages/estransform/lib/types.js delete mode 100644 packages/estransform/modules.d.ts diff --git a/.changeset/kind-sloths-rush.md b/.changeset/kind-sloths-rush.md new file mode 100644 index 00000000..a3903b99 --- /dev/null +++ b/.changeset/kind-sloths-rush.md @@ -0,0 +1,46 @@ +--- +"@chialab/esbuild-plugin-require-resolve": minor +"@chialab/esbuild-plugin-unwebpack": minor +"@chialab/esbuild-plugin-meta-url": minor +"@chialab/esbuild-plugin-worker": minor +"@chialab/esbuild-plugin-html": minor +"@chialab/wtr-mocha-reporter": minor +"@chialab/es-test-runner": minor +"@chialab/rna-dev-server": minor +"@chialab/wds-plugin-hmr": minor +"@chialab/es-dev-server": minor +"@chialab/estransform": minor +"@chialab/cjs-to-esm": minor +"@chialab/rna-logger": minor +"@chialab/rna": minor +"@chialab/esbuild-plugin-any-file": minor +"@chialab/esbuild-plugin-babel": minor +"@chialab/esbuild-plugin-commonjs": minor +"@chialab/esbuild-plugin-css-import": minor +"@chialab/esbuild-plugin-env": minor +"@chialab/esbuild-plugin-lightningcss": minor +"@chialab/esbuild-plugin-metadata": minor +"@chialab/esbuild-plugin-postcss": minor +"@chialab/esbuild-plugin-virtual": minor +"@chialab/esbuild-rna": minor +"@chialab/node-resolve": minor +"@chialab/postcss-dart-sass": minor +"@chialab/postcss-preset-chialab": minor +"@chialab/postcss-url-rebase": minor +"@chialab/rna-browser-test-runner": minor +"@chialab/rna-bundler": minor +"@chialab/rna-config-loader": minor +"@chialab/rna-node-test-runner": minor +"@chialab/rna-saucelabs-test-runner": minor +"@chialab/vite-plugin-commonjs": minor +"@chialab/vite-plugin-worker-proxy": minor +"@chialab/vitest-axe": minor +"@chialab/vitest-provider-browserstack": minor +"@chialab/wds-plugin-legacy": minor +"@chialab/wds-plugin-node-resolve": minor +"@chialab/wds-plugin-polyfill": minor +"@chialab/wds-plugin-rna": minor +"@chialab/wtr-coverage-reporter": minor +--- + +Migrate from sucrase to oxc parser. diff --git a/packages/cjs-to-esm/lib/index.js b/packages/cjs-to-esm/lib/index.js index 58c0149b..3ea004b1 100644 --- a/packages/cjs-to-esm/lib/index.js +++ b/packages/cjs-to-esm/lib/index.js @@ -1,13 +1,4 @@ -import { - createEmptySourcemapComment, - getBlock, - getStatement, - parse, - parseCommonjs, - parseEsm, - TokenType, - walk, -} from '@chialab/estransform'; +import { createEmptySourcemapComment, parse, parseCommonjs, parseEsm, walk } from '@chialab/estransform'; export const REQUIRE_REGEX = /([^.\w$]|^)require\s*\((['"])(.*?)\2\)/g; export const UMD_REGEXES = [ @@ -21,7 +12,6 @@ export const ESM_KEYWORDS = /((?:^\s*|;\s*)(\bimport\s*(\{.*?\}\s*from|\s[\w$]+\s+from|\*\s*as\s+[^\s]+\s+from)?\s*['"])|((?:^\s*|;\s*)export(\s+(default|const|var|let|function|class)[^\w$]|\s*\{)))/m; export const EXPORTS_KEYWORDS = /\b(module\.exports\b|exports\b)/; export const CJS_KEYWORDS = /\b(module\.exports\b|exports\b|require[.(])/; -export const THIS_PARAM = /(}\s*\()this(,|\))/g; export const REQUIRE_FUNCTION = '__cjs_default__'; export const HELPER_MODULE = '__cjs_helper__.js'; @@ -156,17 +146,6 @@ export async function maybeMixedModule(code) { return false; } -/** - * Check if an expression is a require call. - * @param {import('@chialab/estransform').TokenProcessor} processor - */ -function isRequireCallExpression(processor) { - return ( - processor.matches4(TokenType.name, TokenType.parenL, TokenType.string, TokenType.parenR) && - processor.identifierNameAtIndex(processor.currentIndex()) === 'require' - ); -} - /** * @typedef {(specifier: string) => boolean|Promise} IgnoreCallback */ @@ -202,74 +181,79 @@ export async function transform( const specs = new Map(); const ns = new Map(); - const { helpers, processor } = await parse(code, source); + const { ast, helpers } = await parse(code, source); const isUmd = UMD_REGEXES.some((regex) => regex.test(code)); let insertHelper = false; if (!isUmd) { /** - * @type {*[]} + * @type {import('@chialab/estransform').Node[]} */ const ignoredExpressions = []; if (ignoreTryCatch) { - let openBlocks = 0; - await walk(processor, (token) => { - if (token.type === TokenType._try) { - openBlocks++; + walk(ast, { + TryStatement(node) { + walk(node.block, { + CallExpression(node) { + if (node.callee.type !== 'Identifier' || node.callee.name !== 'require') { + return; + } + ignoredExpressions.push(node); + }, + }); + }, + }); + } + + /** + * @type {import('@chialab/estransform').Node[]} + */ + const callExpressions = []; + walk(ast, { + CallExpression(node) { + if (node.callee.type !== 'Identifier' || node.callee.name !== 'require') { return; } - if (token.type === TokenType._catch) { - openBlocks--; + if (ignoredExpressions.includes(node)) { return; } - if (openBlocks && isRequireCallExpression(processor)) { - ignoredExpressions.push(processor.currentIndex()); + const specifier = node.arguments[0]; + if (specifier.type === 'StringLiteral') { + callExpressions.push(node); } - }); - } - - await walk(processor, (token, index) => { - if (!isRequireCallExpression(processor) || ignoredExpressions.includes(index)) { - return; - } - - const specifierToken = processor.tokens[index + 2]; - const specifier = processor.stringValueAtIndex(index + 2); + }, + }); - return (async () => { - let spec = specs.get(specifier); + await Promise.all( + callExpressions.map(async (callExp) => { + const specifier = callExp.arguments[0]; + let spec = specs.get(specifier.value); if (!spec) { - let id = `$cjs$${specifier.replace(/[^\w_$]+/g, '_')}`; + let id = `$cjs$${specifier.value.replace(/[^\w_$]+/g, '_')}`; const count = (ns.get(id) || 0) + 1; ns.set(id, count); if (count > 1) { id += count; } - - if (await ignore(specifier)) { + if (await ignore(specifier.value)) { return; } - - spec = { id, specifier }; + spec = { id, specifier: specifier.value }; specs.set(specifier, spec); } insertHelper = true; - - helpers.overwrite(token.start, token.end, REQUIRE_FUNCTION); - processor.nextToken(); - processor.nextToken(); + helpers.overwrite(callExp.callee.start, callExp.callee.end, REQUIRE_FUNCTION); helpers.overwrite( - specifierToken.start, - specifierToken.end, + specifier.start, + specifier.end, `typeof ${spec.id} !== 'undefined' ? ${spec.id} : {}` ); - processor.nextToken(); - })(); - }); + }) + ); } const { exports, reexports } = await parseCommonjs(code); @@ -314,17 +298,6 @@ __umdFunction.prototype = Function.prototype; }).call(__umdRoot, __umdRoot, __umdRoot, __umdRoot, __umdRoot, undefined, undefined, __umdFunction); export default (__umdExports.length !== 1 && __umdRoot[__umdExports[0]] !== __umdRoot[__umdExports[1]] ? __umdRoot : __umdRoot[__umdExports[0]]);`); - - // replace the usage of `this` as global object because is not supported in esm - let thisMatch = THIS_PARAM.exec(code); - while (thisMatch) { - helpers.overwrite( - thisMatch.index, - thisMatch.index + thisMatch[0].length, - `${thisMatch[1]}this || __umdGlobal${thisMatch[2]}` - ); - thisMatch = THIS_PARAM.exec(code); - } } else if (exports.length > 0 || reexports.length > 0) { helpers.prepend(`var global = ${GLOBAL_HELPER}; var exports = {}; @@ -409,34 +382,39 @@ var module = { * @param {{ sourcemap?: boolean, source?: string; sourcesContent?: boolean }} options */ export async function wrapDynamicRequire(code, { sourcemap = true, source, sourcesContent = false } = {}) { - const { helpers, processor } = await parse(code, source); - await walk(processor, (token, index) => { - if ( - !processor.matches5(TokenType._if, TokenType.parenL, TokenType._typeof, TokenType.name, TokenType.equality) - ) { - return; - } - - const identifier = processor.identifierNameAtIndex(index + 3); - if (identifier !== 'require') { - return; - } - - getBlock(processor, TokenType.parenL, TokenType.parenR); - processor.nextToken(); - - const tokens = []; - if (processor.currentToken() && processor.currentToken().type === TokenType.braceL) { - tokens.push(...getBlock(processor).slice(1, -1)); - } else { - tokens.push(...getStatement(processor)); - } - - const startToken = tokens[0]; - const endToken = tokens[tokens.length - 1]; + const { ast, helpers } = await parse(code, source); + walk(ast, { + IfStatement(node) { + if (node.test.type !== 'BinaryExpression') { + return; + } + if (node.test.left.type !== 'UnaryExpression') { + return; + } + if (node.test.left.operator !== 'typeof') { + return; + } + if (node.test.left.argument.type !== 'Identifier') { + return; + } + if (node.test.left.argument.name !== 'require') { + return; + } + if (!['===', '==', '!==', '!='].includes(node.test.operator)) { + return; + } - helpers.prepend('(() => { try { return (() => {', startToken.start); - helpers.append('})(); } catch(err) {} })();', endToken.end); + if (node.consequent.type === 'BlockStatement') { + helpers.prepend('(() => { try { return (() => {', node.consequent.body[0].start); + helpers.append( + '})(); } catch(err) {} })();', + node.consequent.body[node.consequent.body.length - 1].end + ); + } else { + helpers.prepend('(() => { try { return (() => {', node.consequent.start); + helpers.append('})(); } catch(err) {} })();', node.consequent.end); + } + }, }); if (!helpers.isDirty()) { diff --git a/packages/es-dev-server/build.js b/packages/es-dev-server/build.js index 442dd417..3dd6da05 100644 --- a/packages/es-dev-server/build.js +++ b/packages/es-dev-server/build.js @@ -13,7 +13,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/es-test-runner/build.js b/packages/es-test-runner/build.js index b1dffb22..fe2787cc 100644 --- a/packages/es-test-runner/build.js +++ b/packages/es-test-runner/build.js @@ -13,7 +13,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/esbuild-plugin-html/build.js b/packages/esbuild-plugin-html/build.js index 36b6e7b3..236b3879 100644 --- a/packages/esbuild-plugin-html/build.js +++ b/packages/esbuild-plugin-html/build.js @@ -13,7 +13,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/esbuild-plugin-meta-url/lib/index.js b/packages/esbuild-plugin-meta-url/lib/index.js index 9dd26e22..076b4d33 100644 --- a/packages/esbuild-plugin-meta-url/lib/index.js +++ b/packages/esbuild-plugin-meta-url/lib/index.js @@ -3,7 +3,7 @@ import { lstat } from 'fs/promises'; import path from 'path'; import { fileURLToPath, pathToFileURL } from 'url'; import { useRna } from '@chialab/esbuild-rna'; -import { getBlock, getIdentifierValue, getLocation, parse, TokenType, walk } from '@chialab/estransform'; +import { getLocation, parse, walk } from '@chialab/estransform'; import mime from 'mime-types'; /** @@ -27,100 +27,6 @@ export function getHashParam(source) { return new URLSearchParams(source.split('?').slice(1).join('?')).get('hash') || null; } -/** - * @param {import('@chialab/estransform').TokenProcessor} processor Token processor. - * @returns {string|undefined} The path value. - */ -export function getMetaUrl(processor) { - let fnToken; - let iterator = processor.currentIndex(); - if (processor.matches5(TokenType._new, TokenType.name, TokenType.dot, TokenType.name, TokenType.parenL)) { - fnToken = processor.tokenAtRelativeIndex(2); - iterator += 3; - } else if (processor.matches3(TokenType._new, TokenType.name, TokenType.parenL)) { - fnToken = processor.tokenAtRelativeIndex(1); - iterator += 2; - } - - if (!fnToken || processor.identifierNameForToken(fnToken) !== 'URL') { - return; - } - - const args = []; - let currentArg = []; - let currentToken = processor.tokens[++iterator]; - while (currentToken && currentToken.type !== TokenType.parenR) { - if (currentToken.type === TokenType.comma) { - if (!currentArg.length) { - return; - } - - args.push(currentArg); - currentArg = []; - - currentToken = processor.tokens[++iterator]; - continue; - } - - if (args.length === 0) { - // as first argument we accept a string or a member expression - if (currentToken.type !== TokenType.string && currentToken.type !== TokenType.name) { - return; - } - } - - if (args.length === 1) { - if (currentArg.length > 5) { - return; - } - // the second argument must be `import.meta.url` - if ( - currentArg.length === 0 && - (currentToken.type !== TokenType.name || processor.identifierNameForToken(currentToken) !== 'import') - ) { - return; - } - if (currentArg.length === 1 && currentToken.type !== TokenType.dot) { - return; - } - if ( - currentArg.length === 2 && - (currentToken.type !== TokenType.name || processor.identifierNameForToken(currentToken) !== 'meta') - ) { - return; - } - if (currentArg.length === 3 && currentToken.type !== TokenType.dot) { - return; - } - if ( - currentArg.length === 4 && - (currentToken.type !== TokenType.name || processor.identifierNameForToken(currentToken) !== 'url') - ) { - return; - } - } - if (args.length === 2) { - // we dont handle cases with more than 2 arguments. - return; - } - - currentArg.push(currentToken); - currentToken = processor.tokens[++iterator]; - } - - if (args.length !== 1) { - return; - } - - const firstArg = args[0][0]; - - if (firstArg.type !== TokenType.string) { - return getIdentifierValue(processor, firstArg); - } - - return processor.stringValueForToken(firstArg); -} - /** * @typedef {{ emit?: boolean }} PluginOptions */ @@ -163,152 +69,187 @@ export default function ({ emit = true } = {}) { return; } - /** - * @type {Promise[]} - */ - const promises = []; - - const { helpers, processor } = await parse(code, path.relative(workingDir, args.path)); + const { ast, helpers } = await parse(code, path.relative(workingDir, args.path)); /** * @type {import('esbuild').Message[]} */ const warnings = []; - await walk(processor, () => { - const value = getMetaUrl(processor); - if (typeof value !== 'string' || isUrl(value)) { - return; - } - - const id = getHashParam(value); - if (id && build.isEmittedPath(id)) { - return; - } - - const tokens = getBlock(processor, TokenType.parenL, TokenType.parenR); - const startToken = tokens[0]; - const endToken = tokens[tokens.length - 1]; + /** + * @type {{ [key: string]: string }} + */ + const symbols = {}; + walk(ast, { + VariableDeclarator(node) { + if (node.id.type === 'Identifier' && node.init && node.init.type === 'StringLiteral') { + symbols[node.id.name] = node.init.value; + } + }, + }); - promises.push( - Promise.resolve().then(async () => { - const requestName = value.split('?')[0]; - let resolvedPath; - if (requestName.startsWith('./') || requestName.startsWith('../')) { - try { - const resolved = fileURLToPath(new URL(requestName, pathToFileURL(args.path))); - const stat = await lstat(resolved); - if (stat.isDirectory()) { - // ignore directories - return; - } - resolvedPath = resolved; - } catch { - // unable to access file + await walk(ast, { + async NewExpression(node) { + const callee = node.callee; + if (callee.type !== 'Identifier' || callee.name !== 'URL') { + if (callee.type !== 'StaticMemberExpression') { + return; + } + if ( + callee.object.type !== 'Identifier' || + !['window', 'globalThis', 'self', 'global'].includes(callee.object.name) + ) { + return; + } + if (callee.property.type !== 'Identifier' || callee.property.name !== 'URL') { + return; + } + } + + const argument = node.arguments[0]; + const originArgument = node.arguments[1]; + if ( + !originArgument || + originArgument.type !== 'StaticMemberExpression' || + originArgument.object.type !== 'MetaProperty' || + originArgument.object.meta.name !== 'import' || + originArgument.object.property.name !== 'meta' || + originArgument.property.type !== 'Identifier' || + originArgument.property.name !== 'url' + ) { + return; + } + + const value = + argument.type === 'StringLiteral' + ? argument.value + : argument.type === 'Identifier' + ? symbols[argument.name] + : null; + + if (!value || isUrl(argument.value)) { + return; + } + + const id = getHashParam(value); + if (id && build.isEmittedPath(id)) { + return; + } + + const requestName = value.split('?')[0]; + let resolvedPath; + if (requestName.startsWith('./') || requestName.startsWith('../')) { + try { + const resolved = fileURLToPath(new URL(requestName, pathToFileURL(args.path))); + const stat = await lstat(resolved); + if (stat.isDirectory()) { + // ignore directories + return; } - } else { - const resolved = await build.resolve(`./${requestName}`, { - kind: 'dynamic-import', - importer: args.path, - namespace: 'file', - resolveDir: path.dirname(args.path), - pluginData: null, - }); - resolvedPath = resolved.path; + resolvedPath = resolved; + } catch { + // unable to access file } - - if (resolvedPath) { - const entryLoader = build.getLoader(resolvedPath) || 'file'; - const isChunk = entryLoader !== 'file' && entryLoader !== 'json'; - const isIIFE = format === 'iife' && bundle; - const searchParams = new URLSearchParams(); - - let entryPoint = resolvedPath; - if (emit && !isIIFE) { - if (isChunk) { - const chunk = await build.emitChunk({ path: resolvedPath }); - searchParams.set('hash', chunk.id); - entryPoint = chunk.path; - } else { - const file = await build.emitFile(resolvedPath); - searchParams.set('hash', file.id); - entryPoint = file.path; - } + } else { + const resolved = await build.resolve(`./${requestName}`, { + kind: 'dynamic-import', + importer: args.path, + namespace: 'file', + resolveDir: path.dirname(args.path), + pluginData: null, + }); + resolvedPath = resolved.path; + } + + if (resolvedPath) { + const entryLoader = build.getLoader(resolvedPath) || 'file'; + const isChunk = entryLoader !== 'file' && entryLoader !== 'json'; + const isIIFE = format === 'iife' && bundle; + const searchParams = new URLSearchParams(); + + let entryPoint = resolvedPath; + if (emit && !isIIFE) { + if (isChunk) { + const chunk = await build.emitChunk({ path: resolvedPath }); + searchParams.set('hash', chunk.id); + entryPoint = chunk.path; + } else { + const file = await build.emitFile(resolvedPath); + searchParams.set('hash', file.id); + entryPoint = file.path; } + } - if (isIIFE) { - let buffer, mimeType; - if (isChunk) { - const { outputFiles } = await build.emitChunk( - { - path: `./${path.relative(workingDir, resolvedPath)}`, - write: false, - }, - false - ); - if (outputFiles) { - mimeType = mime.lookup(outputFiles[0].path); - buffer = Buffer.from(outputFiles[0].contents); - } - } else { - const result = await build.load({ - pluginData: null, - namespace: 'file', - suffix: '', - path: resolvedPath, - with: {}, - }); - - if (result && result.contents) { - mimeType = mime.lookup(resolvedPath); - buffer = Buffer.from(result.contents); - } + if (isIIFE) { + let buffer, mimeType; + if (isChunk) { + const { outputFiles } = await build.emitChunk( + { + path: `./${path.relative(workingDir, resolvedPath)}`, + write: false, + }, + false + ); + if (outputFiles) { + mimeType = mime.lookup(outputFiles[0].path); + buffer = Buffer.from(outputFiles[0].contents); } - - if (buffer) { - helpers.overwrite( - startToken.start, - endToken.end, - `new URL('data:${mimeType};base64,${buffer.toString('base64')}')` - ); - return; + } else { + const result = await build.load({ + pluginData: null, + namespace: 'file', + suffix: '', + path: resolvedPath, + with: {}, + }); + + if (result && result.contents) { + mimeType = mime.lookup(resolvedPath); + buffer = Buffer.from(result.contents); } } - const outputPath = build.resolveRelativePath(entryPoint); - const searchParamsString = searchParams.toString(); - helpers.overwrite( - startToken.start, - endToken.end, - `new URL('${outputPath}${ - searchParamsString ? `?${searchParamsString}` : '' - }', ${baseUrl})` - ); - return; + if (buffer) { + helpers.overwrite( + node.start, + node.end, + `new URL('data:${mimeType};base64,${buffer.toString('base64')}')` + ); + return; + } } - const location = getLocation(code, startToken.start); - warnings.push({ - id: 'import-meta-reference-not-found', - pluginName: 'meta-url', - text: `Unable to resolve '${requestName}' file.`, - location: { - file: args.path, - namespace: args.namespace, - ...location, - length: endToken.end - startToken.start, - lineText: code.split('\n')[location.line - 1], - suggestion: '', - }, - notes: [], - detail: '', - }); - }) - ); + const outputPath = build.resolveRelativePath(entryPoint); + const searchParamsString = searchParams.toString(); + helpers.overwrite( + node.start, + node.end, + `new URL('${outputPath}${ + searchParamsString ? `?${searchParamsString}` : '' + }', ${baseUrl})` + ); + return; + } + + const location = getLocation(code, node.start); + warnings.push({ + id: 'import-meta-reference-not-found', + pluginName: 'meta-url', + text: `Unable to resolve '${requestName}' file.`, + location: { + file: args.path, + namespace: args.namespace, + ...location, + length: node.end - node.start, + lineText: code.split('\n')[location.line - 1], + suggestion: '', + }, + notes: [], + detail: '', + }); + }, }); - await Promise.all(promises); - if (!helpers.isDirty()) { return { warnings, diff --git a/packages/esbuild-plugin-require-resolve/lib/index.js b/packages/esbuild-plugin-require-resolve/lib/index.js index 8e4029ea..b5e1e6dd 100644 --- a/packages/esbuild-plugin-require-resolve/lib/index.js +++ b/packages/esbuild-plugin-require-resolve/lib/index.js @@ -1,6 +1,6 @@ import path from 'path'; import { useRna } from '@chialab/esbuild-rna'; -import { parse, TokenType, walk } from '@chialab/estransform'; +import { parse, walk } from '@chialab/estransform'; /** * A file loader plugin for esbuild for `require.resolve` statements. @@ -22,63 +22,41 @@ export default function () { return; } - /** - * @type {Promise[]} - */ - const promises = []; + const { ast, helpers } = await parse(args.code, path.relative(workingDir, args.path)); + await walk(ast, { + async CallExpression(node) { + if ( + node.callee.type !== 'StaticMemberExpression' || + node.callee.object.type !== 'Identifier' || + node.callee.object.name !== 'require' || + node.callee.property.type !== 'Identifier' || + node.callee.property.name !== 'resolve' + ) { + return; + } - const { helpers, processor } = await parse(args.code, path.relative(workingDir, args.path)); - await walk(processor, () => { - if ( - !processor.matches5( - TokenType.name, - TokenType.dot, - TokenType.name, - TokenType.parenL, - TokenType.string - ) - ) { - return; - } + const argument = node.arguments[0]; + if (argument.type !== 'StringLiteral') { + return; + } - const nsName = processor.identifierNameForToken(processor.currentToken()); - if (nsName !== 'require') { - return; - } + const fileName = argument.value; + const { path: resolvedFilePath } = await build.resolve(fileName, { + kind: 'require-resolve', + importer: args.path, + resolveDir: path.dirname(args.path), + }); + if (!resolvedFilePath) { + return; + } - processor.nextToken(); - processor.nextToken(); - - const fnName = processor.identifierNameForToken(processor.currentToken()); - if (fnName !== 'resolve') { - return; - } - - processor.nextToken(); - processor.nextToken(); - - const stringToken = processor.currentToken(); - const fileName = processor.stringValueForToken(stringToken); - promises.push( - (async () => { - const { path: resolvedFilePath } = await build.resolve(fileName, { - kind: 'require-resolve', - importer: args.path, - resolveDir: path.dirname(args.path), - }); - if (!resolvedFilePath) { - return; - } - - const emittedFile = await build.emitFile(resolvedFilePath); - const outputFile = build.resolveRelativePath(emittedFile.path); - helpers.overwrite(stringToken.start, stringToken.end, `'${outputFile}'`); - })() - ); + const emittedFile = await build.emitFile(resolvedFilePath); + const outputFile = build.resolveRelativePath(emittedFile.path); + console.log(`'${outputFile}'`); + helpers.overwrite(argument.start, argument.end, `'${outputFile}'`); + }, }); - await Promise.all(promises); - if (!helpers.isDirty()) { return; } diff --git a/packages/esbuild-plugin-unwebpack/lib/index.js b/packages/esbuild-plugin-unwebpack/lib/index.js index e33756fc..1b01db5c 100644 --- a/packages/esbuild-plugin-unwebpack/lib/index.js +++ b/packages/esbuild-plugin-unwebpack/lib/index.js @@ -1,6 +1,6 @@ import path from 'path'; import { useRna } from '@chialab/esbuild-rna'; -import { getBlock, getNodeComments, parse, TokenType, walk } from '@chialab/estransform'; +import { parse, walk } from '@chialab/estransform'; import { glob } from '@chialab/node-resolve'; /** @@ -29,145 +29,146 @@ export default function () { return; } - /** - * @type {Promise[]} - */ - const promises = []; - - const { helpers, processor } = await parse(code, path.relative(workingDir, args.path)); - await walk(processor, (token) => { - if ( - !processor.matches3(TokenType._import, TokenType.parenL, TokenType.backQuote) || - processor.identifierNameForToken(token) !== 'import' - ) { - return; - } - - const block = getBlock(processor, TokenType.parenL, TokenType.parenR); - const start = block[0].start; - const end = block[block.length - 1].end; - const comments = getNodeComments(code, start, end); - const included = comments.find((value) => value.startsWith('webpackInclude:')); - if (!included) { - return; - } - - const excluded = comments.find((value) => value.startsWith('webpackExclude:')); - const include = new RegExp( - included.replace('webpackInclude:', '').trim().replace(/^\//, '').replace(/\/$/, '') - ); - const exclude = - excluded && - new RegExp( - excluded.replace('webpackExclude:', '').trim().replace(/^\//, '').replace(/\/$/, '') + const { + ast, + comments: programComments, + helpers, + } = await parse(code, path.relative(workingDir, args.path)); + await walk(ast, { + async ImportExpression(node) { + if (!node.source || node.source.type !== 'TemplateLiteral') { + return; + } + + const argument = node.source; + /** + * @type {import('@chialab/estransform').Node[]} + */ + const comments = programComments.filter( + /** @param {import('@chialab/estransform').Node} comment */ (comment) => { + if (comment.start < node.start || comment.start > argument.start) { + return false; + } + if (comment.end > argument.start) { + return false; + } + return true; + } ); - const initial = code.substring(block[3].start, block[3].end); - const identifier = processor.identifierNameForToken(block[5]); - - promises.push( - (async () => { - const matched = await glob(`${initial}*`, { - cwd: path.dirname(args.path), - }); - const map = matched - .filter((name) => name.match(include) && (!exclude || !name.match(exclude))) - .reduce((map, name) => { - map[name.replace(include, '')] = `./${name}`; - return map; - }, /** @type {{ [key: string]: string }} */ ({})); - - helpers.overwrite( - start, - end, - `({ ${Object.keys(map) - .map((key) => `'${key}': () => import('${map[key]}')`) - .join(', ')} })[${identifier}]()` + const included = comments.find(({ value }) => value.trim().startsWith('webpackInclude:')); + if (!included) { + return; + } + + const excluded = comments.find(({ value }) => value.trim().startsWith('webpackExclude:')); + const include = new RegExp( + included.value + .trim() + .replace('webpackInclude:', '') + .trim() + .replace(/^\//, '') + .replace(/\/$/, '') + ); + const exclude = + excluded && + new RegExp( + excluded.value + .trim() + .replace('webpackExclude:', '') + .trim() + .replace(/^\//, '') + .replace(/\/$/, '') ); - })() - ); + const matched = await glob(`${argument.quasis[0].value.raw}*`, { + cwd: path.dirname(args.path), + }); + const map = matched + .filter((name) => name.match(include) && (!exclude || !name.match(exclude))) + .reduce((map, name) => { + map[name.replace(include, '')] = `./${name}`; + return map; + }, /** @type {{ [key: string]: string }} */ ({})); + helpers.overwrite( + node.start, + node.end, + `({ ${Object.keys(map) + .map((key) => `'${key}': () => import('${map[key]}')`) + .join(', ')} })[${argument.expressions[0].name}]()` + ); + }, }); - await Promise.all(promises); - - await walk(processor, (token) => { - if (token.type !== TokenType._if) { - return; - } - - const testBlock = getBlock(processor, TokenType.parenL, TokenType.parenR).slice(2, -1); - const bodyBlock = getBlock(processor, TokenType.braceL, TokenType.braceR); - - const start = token.start; - const end = bodyBlock[bodyBlock.length - 1].end; - - // if (module.hot) { - if ( - testBlock.length === 3 && - testBlock[0].type === TokenType.name && - processor.identifierNameForToken(testBlock[0]) === 'module' && - testBlock[1].type === TokenType.dot && - testBlock[2].type === TokenType.name && - processor.identifierNameForToken(testBlock[2]) === 'hot' - ) { - helpers.overwrite(start, end, ''); - return; - } - - // if (import.meta.webpackHot) { - if ( - testBlock.length === 5 && - testBlock[0].type === TokenType.name && - processor.identifierNameForToken(testBlock[0]) === 'import' && - testBlock[1].type === TokenType.dot && - testBlock[2].type === TokenType.name && - processor.identifierNameForToken(testBlock[2]) === 'meta' && - testBlock[3].type === TokenType.dot && - testBlock[4].type === TokenType.name && - processor.identifierNameForToken(testBlock[4]) === 'webpackHot' - ) { - helpers.overwrite(start, end, ''); - return; - } - - // if (module && module.hot) { - if ( - testBlock.length === 5 && - testBlock[0].type === TokenType.name && - processor.identifierNameForToken(testBlock[0]) === 'module' && - testBlock[1].type === TokenType.logicalAND && - testBlock[2].type === TokenType.name && - processor.identifierNameForToken(testBlock[2]) === 'module' && - testBlock[3].type === TokenType.dot && - testBlock[4].type === TokenType.name && - processor.identifierNameForToken(testBlock[4]) === 'hot' - ) { - helpers.overwrite(start, end, ''); - return; - } - - // if (module && module.hot && module.hot.decline) { - if ( - testBlock.length === 11 && - testBlock[0].type === TokenType.name && - processor.identifierNameForToken(testBlock[0]) === 'module' && - testBlock[1].type === TokenType.logicalAND && - testBlock[2].type === TokenType.name && - processor.identifierNameForToken(testBlock[2]) === 'module' && - testBlock[3].type === TokenType.dot && - testBlock[4].type === TokenType.name && - processor.identifierNameForToken(testBlock[4]) === 'hot' && - testBlock[5].type === TokenType.logicalAND && - testBlock[6].type === TokenType.name && - processor.identifierNameForToken(testBlock[6]) === 'module' && - testBlock[7].type === TokenType.dot && - testBlock[8].type === TokenType.name && - processor.identifierNameForToken(testBlock[8]) === 'hot' && - testBlock[9].type === TokenType.dot && - testBlock[10].type === TokenType.name && - processor.identifierNameForToken(testBlock[10]) === 'decline' - ) { - helpers.overwrite(start, end, ''); - } + walk(ast, { + IfStatement(node) { + // if (module.hot) { + if ( + node.test.type === 'StaticMemberExpression' && + node.test.object.type === 'Identifier' && + node.test.object.name === 'module' && + node.test.property.type === 'Identifier' && + node.test.property.name === 'hot' + ) { + helpers.overwrite(node.start, node.end, ''); + return; + } + + // if (import.meta.webpackHot) { + if ( + node.test.type === 'StaticMemberExpression' && + node.test.object.type === 'MetaProperty' && + node.test.object.meta.type === 'Identifier' && + node.test.object.meta.name === 'import' && + node.test.object.property.type === 'Identifier' && + node.test.object.property.name === 'meta' && + node.test.property.type === 'Identifier' && + node.test.property.name === 'webpackHot' + ) { + helpers.overwrite(node.start, node.end, ''); + return; + } + + // if (module && module.hot) { + if ( + node.test.type === 'LogicalExpression' && + node.test.operator === '&&' && + node.test.left.type === 'Identifier' && + node.test.left.name === 'module' && + node.test.right.type === 'StaticMemberExpression' && + node.test.right.object.type === 'Identifier' && + node.test.right.object.name === 'module' && + node.test.right.property.type === 'Identifier' && + node.test.right.property.name === 'hot' + ) { + helpers.overwrite(node.start, node.end, ''); + return; + } + + // if (module && module.hot && module.hot.decline) { + if ( + node.test.type === 'LogicalExpression' && + node.test.operator === '&&' && + node.test.left.type === 'LogicalExpression' && + node.test.left.operator === '&&' && + node.test.left.left.type === 'Identifier' && + node.test.left.left.name === 'module' && + node.test.left.right.type === 'StaticMemberExpression' && + node.test.left.right.object.type === 'Identifier' && + node.test.left.right.object.name === 'module' && + node.test.left.right.property.type === 'Identifier' && + node.test.left.right.property.name === 'hot' && + node.test.right.type === 'StaticMemberExpression' && + node.test.right.object.type === 'StaticMemberExpression' && + node.test.right.object.object.type === 'Identifier' && + node.test.right.object.object.name === 'module' && + node.test.right.object.property.type === 'Identifier' && + node.test.right.object.property.name === 'hot' && + node.test.right.property.type === 'Identifier' && + node.test.right.property.name === 'decline' + ) { + helpers.overwrite(node.start, node.end, ''); + return; + } + }, }); if (!helpers.isDirty()) { diff --git a/packages/esbuild-plugin-worker/lib/index.js b/packages/esbuild-plugin-worker/lib/index.js index 8b059932..a81d647c 100644 --- a/packages/esbuild-plugin-worker/lib/index.js +++ b/packages/esbuild-plugin-worker/lib/index.js @@ -2,7 +2,7 @@ import { Buffer } from 'buffer'; import path from 'path'; import metaUrlPlugin, { getHashParam } from '@chialab/esbuild-plugin-meta-url'; import { useRna } from '@chialab/esbuild-rna'; -import { getBlock, getIdentifierValue, getLocation, parse, splitArgs, TokenType, walk } from '@chialab/estransform'; +import { getLocation, parse, walk } from '@chialab/estransform'; /** * @typedef {{ constructors?: string[], proxy?: boolean, emit?: boolean }} PluginOptions @@ -58,248 +58,225 @@ export default function ({ constructors = ['Worker', 'SharedWorker'], proxy = fa return; } + const { ast, helpers } = await parse(code, path.relative(workingDir, args.path)); + /** - * @type {Promise[]} + * @type {import('esbuild').Message[]} */ - const promises = []; + const warnings = []; /** - * @type {Set} + * @type {string[]} */ - const redefined = new Set(); - - const { helpers, processor } = await parse(code, path.relative(workingDir, args.path)); - await walk(processor, (token) => { - if (token.type === TokenType._class) { - processor.nextToken(); - if (processor.currentToken().type === TokenType.name) { - const name = processor.identifierNameForToken(processor.currentToken()); - if (constructors.includes(name)) { - redefined.add(name); - } - } - } - }); + const classDeclarations = []; /** - * @type {import('esbuild').Message[]} + * @type {{ [key: string]: string }} */ - const warnings = []; - - await walk(processor, (token) => { - if (token.type !== TokenType._new) { - return; - } - - processor.nextToken(); - let Ctr = processor.identifierNameForToken(processor.currentToken()); - if (Ctr === 'window' || Ctr === 'self' || Ctr === 'globalThis') { - processor.nextToken(); - processor.nextToken(); - Ctr = `${Ctr}.${processor.identifierNameForToken(processor.currentToken())}`; - } - - if (redefined.has(Ctr)) { - return; - } - - if (!variants.includes(Ctr)) { - return; - } - - const block = getBlock(processor, TokenType.parenL, TokenType.parenR); - const argsBlock = block.slice(2, -1); - const [firstArg, secondArg] = splitArgs(argsBlock); - if (!firstArg) { - return; - } - - const startToken = firstArg[0]; - const endToken = firstArg[firstArg.length - 1]; - - /** - * @type {import('@chialab/esbuild-rna').BuildOptions} - */ - const transformOptions = { - format: 'iife', - bundle: true, - platform: 'neutral', - }; - - if ( - (format !== 'iife' || !bundle) && - secondArg && - secondArg.length >= 4 && - secondArg[0].type === TokenType.braceL - ) { - if ( - ((secondArg[1].type === TokenType.string && - processor.stringValueForToken(secondArg[1]) === 'type') || - (secondArg[1].type === TokenType.name && - processor.identifierNameForToken(secondArg[1]) === 'type')) && - secondArg[2].type === TokenType.colon && - secondArg[3].type === TokenType.string && - processor.stringValueForToken(secondArg[3]) === 'module' - ) { - transformOptions.format = 'esm'; - delete transformOptions.external; - delete transformOptions.bundle; + const symbols = {}; + walk(ast, { + ClassDeclaration(node) { + if (!node.id || node.id.type !== 'Identifier') { + return; } - } - - if ( - startToken.type !== TokenType._new || - firstArg[1].type !== TokenType.name || - processor.identifierNameForToken(firstArg[1]) !== 'URL' - ) { - const isStringLiteral = startToken.type === TokenType.string; - const isIdentifier = startToken.type === TokenType.name; - if ((isStringLiteral || isIdentifier) && proxy) { - const arg = code.substring(firstArg[0].start, firstArg[firstArg.length - 1].end); - helpers.overwrite( - firstArg[0].start, - firstArg[firstArg.length - 1].end, - createBlobProxy(arg, transformOptions, true) - ); + classDeclarations.push(node.id.name); + }, + VariableDeclarator(node) { + if (node.id.type === 'Identifier' && node.init && node.init.type === 'StringLiteral') { + symbols[node.id.name] = node.init.value; } - return; - } - - const firstParen = firstArg.findIndex((token) => token.type === TokenType.parenL); - const lastParen = -firstArg - .slice(0) - .reverse() - .findIndex((token) => token.type === TokenType.parenR); - const [urlArgs, metaArgs] = splitArgs(firstArg.slice(firstParen + 1, lastParen - 1)); - const reference = urlArgs[0]; - - if ( - !metaArgs || - metaArgs.length !== 5 || - metaArgs[0].type !== TokenType.name || - processor.identifierNameForToken(metaArgs[0]) !== 'import' || - metaArgs[1].type !== TokenType.dot || - metaArgs[2].type !== TokenType.name || - processor.identifierNameForToken(metaArgs[2]) !== 'meta' || - metaArgs[3].type !== TokenType.dot || - metaArgs[4].type !== TokenType.name || - processor.identifierNameForToken(metaArgs[4]) !== 'url' || - !reference - ) { - return; - } - - const isStringLiteral = reference.type === TokenType.string; - const isIdentifier = reference.type === TokenType.name; - if (!isStringLiteral && !isIdentifier && !proxy) { - return; - } - - promises.push( - Promise.resolve().then(async () => { - const value = isStringLiteral - ? processor.stringValueForToken(reference) - : isIdentifier - ? getIdentifierValue(processor, reference) - : null; - - if (typeof value !== 'string') { - if (proxy) { - const arg = code.substring(firstArg[0].start, firstArg[firstArg.length - 1].end); - helpers.overwrite( - firstArg[0].start, - firstArg[firstArg.length - 1].end, - createBlobProxy(arg, transformOptions, true) - ); - } + }, + }); + + await walk(ast, { + async NewExpression(node) { + const callee = node.callee; + if (callee.type !== 'Identifier' || !constructors.includes(callee.name)) { + if (callee.type !== 'StaticMemberExpression') { return; } - - const id = getHashParam(value); - if (id && build.isEmittedPath(id)) { + if ( + callee.object.type !== 'Identifier' || + !['window', 'globalThis', 'self', 'global'].includes(callee.object.name) || + callee.property.type !== 'Identifier' || + !constructors.includes(callee.property.name) + ) { return; } + } else if (classDeclarations.includes(callee.name)) { + return; + } - const { path: resolvedPath, external } = await build.resolve(value, { - kind: 'dynamic-import', - importer: args.path, - namespace: 'file', - resolveDir: path.dirname(args.path), - pluginData: null, - }); + const argument = node.arguments[0]; + if (!argument) { + return; + } - if (external) { - return; + const options = node.arguments[1]; + + /** + * @type {import('@chialab/esbuild-rna').BuildOptions} + */ + const transformOptions = { + format: 'iife', + bundle: true, + platform: 'neutral', + }; + + if (options && options.type === 'ObjectExpression') { + for (const property of options.properties) { + if ( + property.type === 'ObjectProperty' && + property.key.type === 'Identifier' && + property.key.name === 'type' && + property.value.type === 'StringLiteral' + ) { + transformOptions.format = 'esm'; + delete transformOptions.external; + delete transformOptions.bundle; + break; + } } + } - if (!resolvedPath) { - const location = getLocation(code, startToken.start); - warnings.push({ - id: 'worker-reference-not-found', - pluginName: 'worker', - text: `Unable to resolve '${value}' file.`, - location: { - file: args.path, - namespace: args.namespace, - ...location, - length: endToken.end - startToken.start, - lineText: code.split('\n')[location.line - 1], - suggestion: '', - }, - notes: [], - detail: '', - }); - return; + if ( + argument.type !== 'NewExpression' || + argument.callee.type !== 'Identifier' || + argument.callee.name !== 'URL' + ) { + const isStringLiteral = argument.type === 'StringLiteral'; + const isIdentifier = argument.type === 'Identifier'; + if ((isStringLiteral || isIdentifier) && proxy) { + const arg = code.substring(argument.start, argument.end); + helpers.overwrite( + argument.start, + argument.end, + createBlobProxy(arg, transformOptions, true) + ); } + return; + } + + const reference = argument.arguments[0]; + const originArgument = argument.arguments[1]; + if ( + !originArgument || + originArgument.type !== 'StaticMemberExpression' || + originArgument.object.type !== 'MetaProperty' || + originArgument.object.meta.name !== 'import' || + originArgument.object.property.name !== 'meta' || + originArgument.property.type !== 'Identifier' || + originArgument.property.name !== 'url' + ) { + return; + } + + const isStringLiteral = reference.type === 'StringLiteral'; + const isIdentifier = reference.type === 'Identifier'; + if (!isStringLiteral && !isIdentifier && !proxy) { + return; + } - let emittedChunk; - let entryPoint = resolvedPath; - const searchParams = new URLSearchParams(); - if (emit) { - emittedChunk = await build.emitChunk( - { - ...transformOptions, - path: resolvedPath, - write: format !== 'iife' || !bundle, - }, - format !== 'iife' || !bundle + const value = isStringLiteral + ? reference.value + : isIdentifier + ? symbols[reference.name] || null + : null; + + if (typeof value !== 'string') { + if (proxy) { + const arg = code.substring(argument.start, argument.end); + helpers.overwrite( + argument.start, + argument.end, + createBlobProxy(arg, transformOptions, true) ); - searchParams.set('hash', emittedChunk.id); - entryPoint = emittedChunk.path; } + return; + } - if (emittedChunk && format === 'iife' && bundle) { - const { outputFiles } = emittedChunk; - if (outputFiles) { - const base64 = Buffer.from(outputFiles[0].contents).toString('base64'); - helpers.overwrite( - startToken.start, - endToken.end, - `new URL('data:text/javascript;base64,${base64}')` - ); - } + const id = getHashParam(value); + if (id && build.isEmittedPath(id)) { + return; + } + + const { path: resolvedPath, external } = await build.resolve(value, { + kind: 'dynamic-import', + importer: args.path, + namespace: 'file', + resolveDir: path.dirname(args.path), + pluginData: null, + }); + + if (external) { + return; + } + + if (!resolvedPath) { + const location = getLocation(code, argument.start); + warnings.push({ + id: 'worker-reference-not-found', + pluginName: 'worker', + text: `Unable to resolve '${value}' file.`, + location: { + file: args.path, + namespace: args.namespace, + ...location, + length: argument.end - argument.start, + lineText: code.split('\n')[location.line - 1], + suggestion: '', + }, + notes: [], + detail: '', + }); + return; + } + + let emittedChunk; + let entryPoint = resolvedPath; + const searchParams = new URLSearchParams(); + if (emit) { + emittedChunk = await build.emitChunk( + { + ...transformOptions, + path: resolvedPath, + write: format !== 'iife' || !bundle, + }, + format !== 'iife' || !bundle + ); + searchParams.set('hash', emittedChunk.id); + entryPoint = emittedChunk.path; + } + + if (emittedChunk && format === 'iife' && bundle) { + const { outputFiles } = emittedChunk; + if (outputFiles) { + const base64 = Buffer.from(outputFiles[0].contents).toString('base64'); + helpers.overwrite( + argument.start, + argument.end, + `new URL('data:text/javascript;base64,${base64}')` + ); + } + } else { + const outputPath = build.resolveRelativePath(entryPoint); + const searchParamsString = searchParams.toString(); + const arg = `new URL('${outputPath}${ + searchParamsString ? `?${searchParamsString}` : '' + }', import.meta.url).href`; + if (proxy) { + helpers.overwrite( + argument.start, + argument.end, + createBlobProxy(arg, transformOptions, false) + ); } else { - const outputPath = build.resolveRelativePath(entryPoint); - const searchParamsString = searchParams.toString(); - const arg = `new URL('${outputPath}${ - searchParamsString ? `?${searchParamsString}` : '' - }', import.meta.url).href`; - if (proxy) { - helpers.overwrite( - firstArg[0].start, - firstArg[firstArg.length - 1].end, - createBlobProxy(arg, transformOptions, false) - ); - } else { - helpers.overwrite(firstArg[0].start, firstArg[firstArg.length - 1].end, arg); - } + helpers.overwrite(argument.start, argument.end, arg); } - }) - ); + } + }, }); - await Promise.all(promises); - if (!helpers.isDirty()) { return { warnings, diff --git a/packages/estransform/build.js b/packages/estransform/build.js index 20ef4d67..6622c524 100644 --- a/packages/estransform/build.js +++ b/packages/estransform/build.js @@ -9,5 +9,5 @@ esbuild.build({ sourcemap: true, format: 'esm', platform: 'node', - external: ['@parcel/source-map'], + external: ['@parcel/source-map', 'oxc-parser'], }); diff --git a/packages/estransform/lib/helpers.js b/packages/estransform/lib/helpers.js index fb44b07f..ea5c6f52 100644 --- a/packages/estransform/lib/helpers.js +++ b/packages/estransform/lib/helpers.js @@ -1,5 +1,3 @@ -import { TokenType } from './types.js'; - /** * Create a empty sourcemap comment. */ @@ -14,61 +12,6 @@ export function createEmptyModule() { return `export default {};${createEmptySourcemapComment()}`; } -/** - * Detect first level identifier for esbuild file loader imports. - * File could be previously bundled using esbuild, so the first argument of a new URL(something, import.meta.url) - * is not a literal anymore but an identifier. - * Here, we are looking for its computed value. - * @param {import('./parser.js').TokenProcessor} processor The program processor. - * @param {import('./types.js').Token} id The name of the identifier. - * @returns {string|undefined} The init token. - */ -export function getIdentifierValue(processor, id) { - const { tokens } = processor; - const name = processor.identifierNameForToken(id); - let index = 0; - let count = 0; - let token = tokens[index++]; - while (index < tokens.length) { - if (token.type === TokenType.braceL) { - count++; - token = tokens[index++]; - continue; - } - - if (token.type === TokenType.braceR) { - count--; - token = tokens[index++]; - continue; - } - - if (count) { - token = tokens[index++]; - continue; - } - - if (token.type !== TokenType._var && token.type !== TokenType._const && token.type !== TokenType._let) { - token = tokens[index++]; - continue; - } - - token = tokens[index++]; - if (token.type !== TokenType.name || processor.identifierNameForToken(token) !== name) { - continue; - } - - // = - index++; - - token = tokens[index++]; - if (token.type !== TokenType.string) { - continue; - } - - return processor.stringValueForToken(token); - } -} - /** * Get token location. * @param {string} code Source code. @@ -97,227 +40,3 @@ export function getLocation(code, index) { return { line, column }; } - -/** - * Get a block of tokens. - * @param {import('./parser.js').TokenProcessor} processor - * @param {TokenType} [openingToken] - * @param {TokenType} [closingToken] - * @returns {import('./types.js').Token[]} - */ -export function getBlock(processor, openingToken = TokenType.braceL, closingToken = TokenType.braceR) { - /** - * @type {import('./types.js').Token | null} - */ - let token = processor.currentToken(); - let count = 0; - - const block = [token]; - while (token && (token.type !== closingToken || count > 0)) { - if (processor.isAtEnd() || token.type === TokenType.eof) { - break; - } - token = getNextToken(processor); - if (token) { - block.push(token); - if (token.type === openingToken) { - count++; - } else if (token.type === closingToken) { - count--; - } - } - } - - return block; -} - -/** - * @param {import('./parser.js').TokenProcessor} processor - */ -export function getStatement(processor) { - /** - * @type {import('./types.js').Token | null} - */ - let token = processor.currentToken(); - let count = 0; - - const block = [token]; - while (token && (token.type !== TokenType.semi || count > 0)) { - if (processor.isAtEnd() || token.type === TokenType.eof) { - break; - } - token = getNextToken(processor); - if (token) { - block.push(token); - if (token.type === TokenType.braceL || token.type === TokenType.parenL) { - count++; - } else if (token.type === TokenType.braceR || token.type === TokenType.parenR) { - count--; - } - } - } - - return block; -} - -/** - * Split tokens into function arguments. - * @param {import('./types.js').Token[]} tokens - * @returns {import('./types.js').Token[][]} - */ -export function splitArgs(tokens) { - /** - * @type {import('./types.js').Token[][]} - */ - const args = []; - - /** - * @type {import('./types.js').Token[]} - */ - let currentArg = []; - - let count = 0; - - let token = tokens.shift(); - while (token) { - if (token.type === TokenType.braceL || token.type === TokenType.parenL) { - count++; - } else if (token.type === TokenType.braceR || token.type === TokenType.parenR) { - count--; - } - - if (!count && token.type === TokenType.comma) { - args.push(currentArg); - currentArg = []; - token = tokens.shift(); - continue; - } - - currentArg.push(token); - token = tokens.shift(); - } - - if (currentArg.length) { - args.push(currentArg); - } - - return args; -} - -/** - * Extract argument tokens for a function declaration. - * @param {import('./parser.js').TokenProcessor} processor - */ -export function extractFunctionArguments(processor) { - const args = []; - - let openParens = 0; - let openBrackets = 0; - let openBraces = 0; - - /** - * @type {import('./types.js').Token | null} - */ - let token = processor.currentToken(); - let arg = []; - while ((token && token.type !== TokenType.parenR) || openParens || openBrackets || openBraces) { - arg.push({ - ...token, - index: processor.currentIndex(), - }); - - token = getNextToken(processor); - if (!token) { - break; - } - - if (token.type === TokenType.parenL) { - openParens++; - } - if (token.type === TokenType.parenR && openParens) { - openParens--; - } - if (token.type === TokenType.bracketL) { - openBrackets++; - } - if (token.type === TokenType.bracketR) { - openBrackets--; - } - if (token.type === TokenType.braceL) { - openBraces++; - } - if (token.type === TokenType.braceR) { - openBraces--; - } - if (token.type === TokenType.comma && !openParens && !openBrackets && !openBraces) { - args.push(arg); - arg = []; - - token = getNextToken(processor); - } - } - - args.push(arg); - - return args; -} - -/** - * Move forward in tokens list and return the current token. - * @param {import('./parser.js').TokenProcessor} processor - * @returns {import('./types.js').Token|null} - */ -export function getNextToken(processor) { - if (processor.isAtEnd()) { - return null; - } - processor.nextToken(); - return processor.currentToken(); -} - -/** - * Move forward until `)` closes the block. - * @param {import('./parser.js').TokenProcessor} processor - */ -export function nextBlock(processor) { - let openParens = 0; - /** - * @type {import('./types.js').Token | null} - */ - let token = processor.currentToken(); - while (token && (token.type !== TokenType.parenR || openParens)) { - if (token.type === TokenType.parenR) { - openParens--; - } - token = getNextToken(processor); - if (!token) { - break; - } - if (token && token.type === TokenType.parenL) { - openParens++; - } - } -} - -/** - * Extract comments for a code range delmited by node span. - * @param {string} code The original code. - * @param {number} start The start index. - * @param {number} end The end index. - */ -export function getNodeComments(code, start, end) { - const chunk = code.substring(start, end); - const matches = chunk.match(/\/\*[\s\S]*?\*\/|(?:[^\\:]|^)\/\/.*$/gm); - if (!matches) { - return []; - } - - return matches.map((comment) => - // remove comment delimiters - comment - .trim() - .replace(/^\/\*+\s*/, '') - .replace(/\s*\*+\/$/, '') - .replace(/^\/\/\s*/, '') - ); -} diff --git a/packages/estransform/lib/index.js b/packages/estransform/lib/index.js index 5092690c..ef20f3b8 100644 --- a/packages/estransform/lib/index.js +++ b/packages/estransform/lib/index.js @@ -1,4 +1,3 @@ -export * from './types.js'; export * from './parser.js'; export * from './modules.js'; export * from './sourcemaps.js'; diff --git a/packages/estransform/lib/parser.js b/packages/estransform/lib/parser.js index e5f819ee..af24e315 100644 --- a/packages/estransform/lib/parser.js +++ b/packages/estransform/lib/parser.js @@ -1,53 +1,49 @@ import MagicString from 'magic-string'; -import { HelperManager } from 'sucrase/dist/HelperManager.js'; -import NameManagerModule from 'sucrase/dist/NameManager.js'; -import { parse as sucraseParse } from 'sucrase/dist/parser/index.js'; -import TokenProcessorModule from 'sucrase/dist/TokenProcessor.js'; +import { parseAsync } from 'oxc-parser'; import { inlineSourcemap, loadSourcemap, mergeSourcemaps, removeInlineSourcemap } from './sourcemaps.js'; /** - * @param {*} mod + * @typedef {{ type: string; start: number; end: number; [key: string]: any }} Node */ -function interopImport(mod) { - return typeof mod.default !== 'undefined' ? mod.default : mod; -} - -export const NameManager = /** @type {typeof import('sucrase/dist/NameManager.js').default} */ ( - interopImport(NameManagerModule) -); -export const TokenProcessor = /** @type {typeof import('sucrase/dist/types/TokenProcessor').default} */ ( - interopImport(TokenProcessorModule) -); /** - * Walk through tokens and wait async visitors. - * - * @param {InstanceType} processor - * @param {(token: import('./types.js').Token, index: number, processor: InstanceType) => void|false|Promise} callback + * @param {*} obj + * @param {(string|number)[]} path + * @returns {Generator} */ -export async function walk(processor, callback) { - if (processor.isAtEnd()) { - processor.reset(); - } - - while (!processor.isAtEnd()) { - const token = processor.currentToken(); - const index = processor.currentIndex(); - - let result = callback(token, index, processor); - if (result instanceof Promise) { - result = await result; - } - - if (result === false) { - return; +function* jsonWalker(obj, path = []) { + if (typeof obj === 'object' && obj != null) { + if (Array.isArray(obj)) { + for (let i = 0; i < obj.length; i++) { + yield* jsonWalker(obj[i], [...path, i]); + } + } else { + if (Object.hasOwn(obj, 'type')) { + yield obj; + } + for (const key in obj) { + if (Object.hasOwn(obj, key)) { + yield* jsonWalker(obj[key], [...path, key]); + } + } } + } +} - if (processor.isAtEnd()) { - return; +/** + * Walk an ast node. + * @param {Node} root + * @param {Record void | Promise>} visitors + * @returns {Promise} + */ +export async function walk(root, visitors) { + for (const object of jsonWalker(root)) { + if (visitors[object.type]) { + const result = visitors[object.type](object); + if (result instanceof Promise) { + await result; + } } - - processor.nextToken(); } } @@ -55,21 +51,17 @@ export async function walk(processor, callback) { * @param {string} inputCode The code to parse. * @param {string} [filePath] The source file name. */ -export function parse(inputCode, filePath) { +export async function parse(inputCode, filePath) { const code = removeInlineSourcemap(inputCode); - const program = sucraseParse(code, true, true, false); - const nameManager = new NameManager(code, program.tokens); - const helperManager = new HelperManager(nameManager); - const processor = new TokenProcessor(code, program.tokens, false, true, helperManager); const magicCode = new MagicString(code); + const result = await parseAsync(code, { sourceType: 'module', sourceFilename: filePath }); + const ast = JSON.parse(result.program); let changed = false; return { - program, - nameManager, - helperManager, - processor, + ast, + comments: result.comments, helpers: { /** * @param {string} code diff --git a/packages/estransform/lib/types.js b/packages/estransform/lib/types.js deleted file mode 100644 index b19ee2c8..00000000 --- a/packages/estransform/lib/types.js +++ /dev/null @@ -1,6 +0,0 @@ -import { TokenType } from 'sucrase/dist/parser/tokenizer/types.js'; - -/** @typedef {import('sucrase/dist/types/parser/index').File} File */ -/** @typedef {import('sucrase/dist/types/parser/tokenizer/index').Token} Token */ - -export { TokenType }; diff --git a/packages/estransform/modules.d.ts b/packages/estransform/modules.d.ts deleted file mode 100644 index ae003964..00000000 --- a/packages/estransform/modules.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -declare module 'sucrase/dist/parser/index.js' { - export { File, parse } from 'sucrase'; -} - -declare module 'sucrase/dist/NameManager.js' { - export { NameManagerModule as default } from 'sucrase'; -} - -declare module 'sucrase/dist/HelperManager.js' { - export { HelperManager } from 'sucrase'; -} - -declare module 'sucrase/dist/TokenProcessor.js' { - export * from 'sucrase/dist/types/TokenProcessor'; -} - -declare module 'sucrase/dist/parser/tokenizer/types.js' { - export { TokenType } from 'sucrase'; -} - -declare module 'sucrase/dist/parser/tokenizer/index.js' { - export { Token } from 'sucrase'; -} diff --git a/packages/estransform/package.json b/packages/estransform/package.json index ad4c6214..4ca6f256 100644 --- a/packages/estransform/package.json +++ b/packages/estransform/package.json @@ -32,14 +32,14 @@ "node": ">=18" }, "dependencies": { - "@parcel/source-map": "^2.0.0" + "@parcel/source-map": "^2.0.0", + "oxc-parser": "^0.8.0" }, "devDependencies": { "cjs-module-lexer": "^1.2.2", "es-module-lexer": "^1.0.0", "magic-string": "^0.30.3", "rimraf": "^5.0.1", - "sucrase": "^3.0.0", "typescript": "^5.0.0" } } diff --git a/packages/estransform/tsconfig.json b/packages/estransform/tsconfig.json index ca6cf70d..7e463a46 100644 --- a/packages/estransform/tsconfig.json +++ b/packages/estransform/tsconfig.json @@ -6,6 +6,6 @@ "baseUrl": ".", "rootDir": "./lib" }, - "include": ["lib/**/*", "modules.d.ts"], + "include": ["lib/**/*"], "references": [] } diff --git a/packages/rna-dev-server/build.js b/packages/rna-dev-server/build.js index 4c8b07b3..188c6142 100644 --- a/packages/rna-dev-server/build.js +++ b/packages/rna-dev-server/build.js @@ -23,7 +23,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/rna-logger/build.js b/packages/rna-logger/build.js index 059b11bf..e9b522d2 100644 --- a/packages/rna-logger/build.js +++ b/packages/rna-logger/build.js @@ -12,7 +12,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/rna/build.js b/packages/rna/build.js index 1fff9880..a1979254 100644 --- a/packages/rna/build.js +++ b/packages/rna/build.js @@ -22,7 +22,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/wds-plugin-hmr/build.js b/packages/wds-plugin-hmr/build.js index d3dd8b99..90b44eeb 100644 --- a/packages/wds-plugin-hmr/build.js +++ b/packages/wds-plugin-hmr/build.js @@ -14,7 +14,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/packages/wtr-mocha-reporter/build.js b/packages/wtr-mocha-reporter/build.js index 8e243555..f2cbfbb9 100644 --- a/packages/wtr-mocha-reporter/build.js +++ b/packages/wtr-mocha-reporter/build.js @@ -13,7 +13,7 @@ esbuild.build({ banner: { js: `import { dirname as __pathDirname } from 'path'; import { createRequire as __moduleCreateRequire } from 'module'; -import { fileURLToPath as __fileURLToPath } from 'url'; +import { fileURLToPath as __fileURLToPath } from 'url'; const require = __moduleCreateRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); diff --git a/yarn.lock b/yarn.lock index d142f158..3114c000 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2045,8 +2045,8 @@ __metadata: cjs-module-lexer: ^1.2.2 es-module-lexer: ^1.0.0 magic-string: ^0.30.3 + oxc-parser: ^0.8.0 rimraf: ^5.0.1 - sucrase: ^3.0.0 typescript: ^5.0.0 languageName: unknown linkType: soft @@ -3420,6 +3420,62 @@ __metadata: languageName: node linkType: hard +"@oxc-parser/binding-darwin-arm64@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-darwin-arm64@npm:0.8.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-darwin-x64@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-darwin-x64@npm:0.8.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm64-gnu@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-linux-arm64-gnu@npm:0.8.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm64-musl@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-linux-arm64-musl@npm:0.8.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-x64-gnu@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-linux-x64-gnu@npm:0.8.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-x64-musl@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-linux-x64-musl@npm:0.8.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxc-parser/binding-win32-arm64-msvc@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-win32-arm64-msvc@npm:0.8.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-win32-x64-msvc@npm:0.8.0": + version: 0.8.0 + resolution: "@oxc-parser/binding-win32-x64-msvc@npm:0.8.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@parcel/source-map@npm:^2.0.0": version: 2.1.1 resolution: "@parcel/source-map@npm:2.1.1" @@ -5187,13 +5243,6 @@ __metadata: languageName: node linkType: hard -"any-promise@npm:^1.0.0": - version: 1.3.0 - resolution: "any-promise@npm:1.3.0" - checksum: 0ee8a9bdbe882c90464d75d1f55cf027f5458650c4bd1f0467e65aec38ccccda07ca5844969ee77ed46d04e7dded3eaceb027e8d32f385688523fe305fa7e1de - languageName: node - linkType: hard - "anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" @@ -6419,13 +6468,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^4.0.0": - version: 4.1.1 - resolution: "commander@npm:4.1.1" - checksum: d7b9913ff92cae20cb577a4ac6fcc121bd6223319e54a40f51a14740a681ad5c574fd29a57da478a5f234a6fa6c52cbf0b7c641353e03c648b1ae85ba670b977 - languageName: node - linkType: hard - "commander@npm:^7.2.0": version: 7.2.0 resolution: "commander@npm:7.2.0" @@ -11424,17 +11466,6 @@ __metadata: languageName: node linkType: hard -"mz@npm:^2.7.0": - version: 2.7.0 - resolution: "mz@npm:2.7.0" - dependencies: - any-promise: ^1.0.0 - object-assign: ^4.0.1 - thenify-all: ^1.0.0 - checksum: 8427de0ece99a07e9faed3c0c6778820d7543e3776f9a84d22cf0ec0a8eb65f6e9aee9c9d353ff9a105ff62d33a9463c6ca638974cc652ee8140cd1e35951c87 - languageName: node - linkType: hard - "n12@npm:1.8.24": version: 1.8.24 resolution: "n12@npm:1.8.24" @@ -11652,13 +11683,6 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - "object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" @@ -11885,6 +11909,39 @@ __metadata: languageName: node linkType: hard +"oxc-parser@npm:^0.8.0": + version: 0.8.0 + resolution: "oxc-parser@npm:0.8.0" + dependencies: + "@oxc-parser/binding-darwin-arm64": 0.8.0 + "@oxc-parser/binding-darwin-x64": 0.8.0 + "@oxc-parser/binding-linux-arm64-gnu": 0.8.0 + "@oxc-parser/binding-linux-arm64-musl": 0.8.0 + "@oxc-parser/binding-linux-x64-gnu": 0.8.0 + "@oxc-parser/binding-linux-x64-musl": 0.8.0 + "@oxc-parser/binding-win32-arm64-msvc": 0.8.0 + "@oxc-parser/binding-win32-x64-msvc": 0.8.0 + dependenciesMeta: + "@oxc-parser/binding-darwin-arm64": + optional: true + "@oxc-parser/binding-darwin-x64": + optional: true + "@oxc-parser/binding-linux-arm64-gnu": + optional: true + "@oxc-parser/binding-linux-arm64-musl": + optional: true + "@oxc-parser/binding-linux-x64-gnu": + optional: true + "@oxc-parser/binding-linux-x64-musl": + optional: true + "@oxc-parser/binding-win32-arm64-msvc": + optional: true + "@oxc-parser/binding-win32-x64-msvc": + optional: true + checksum: e60e5817e66b1e8020dcfdc45c7e730882e477798fc067e98aa7d473d887334e62876c85824769d61b6bf5f07068d34001081dd61c7f152db9a8eccf32e054fb + languageName: node + linkType: hard + "p-cancelable@npm:^2.0.0": version: 2.1.1 resolution: "p-cancelable@npm:2.1.1" @@ -12301,13 +12358,6 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1": - version: 4.0.6 - resolution: "pirates@npm:4.0.6" - checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 - languageName: node - linkType: hard - "pixelmatch@npm:^4.0.2": version: 4.0.2 resolution: "pixelmatch@npm:4.0.2" @@ -14765,24 +14815,6 @@ __metadata: languageName: node linkType: hard -"sucrase@npm:^3.0.0": - version: 3.35.0 - resolution: "sucrase@npm:3.35.0" - dependencies: - "@jridgewell/gen-mapping": ^0.3.2 - commander: ^4.0.0 - glob: ^10.3.10 - lines-and-columns: ^1.1.6 - mz: ^2.7.0 - pirates: ^4.0.1 - ts-interface-checker: ^0.1.9 - bin: - sucrase: bin/sucrase - sucrase-node: bin/sucrase-node - checksum: 9fc5792a9ab8a14dcf9c47dcb704431d35c1cdff1d17d55d382a31c2e8e3063870ad32ce120a80915498486246d612e30cda44f1624d9d9a10423e1a43487ad1 - languageName: node - linkType: hard - "supports-color@npm:8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" @@ -14964,24 +14996,6 @@ __metadata: languageName: node linkType: hard -"thenify-all@npm:^1.0.0": - version: 1.6.0 - resolution: "thenify-all@npm:1.6.0" - dependencies: - thenify: ">= 3.1.0 < 4" - checksum: dba7cc8a23a154cdcb6acb7f51d61511c37a6b077ec5ab5da6e8b874272015937788402fd271fdfc5f187f8cb0948e38d0a42dcc89d554d731652ab458f5343e - languageName: node - linkType: hard - -"thenify@npm:>= 3.1.0 < 4": - version: 3.3.1 - resolution: "thenify@npm:3.3.1" - dependencies: - any-promise: ^1.0.0 - checksum: 84e1b804bfec49f3531215f17b4a6e50fd4397b5f7c1bccc427b9c656e1ecfb13ea79d899930184f78bc2f57285c54d9a50a590c8868f4f0cef5c1d9f898b05e - languageName: node - linkType: hard - "through@npm:2, through@npm:^2.3.8, through@npm:~2.3, through@npm:~2.3.1": version: 2.3.8 resolution: "through@npm:2.3.8" @@ -15154,13 +15168,6 @@ __metadata: languageName: node linkType: hard -"ts-interface-checker@npm:^0.1.9": - version: 0.1.13 - resolution: "ts-interface-checker@npm:0.1.13" - checksum: 20c29189c2dd6067a8775e07823ddf8d59a33e2ffc47a1bd59a5cb28bb0121a2969a816d5e77eda2ed85b18171aa5d1c4005a6b88ae8499ec7cc49f78571cb5e - languageName: node - linkType: hard - "tsconfig-paths@npm:^3.15.0": version: 3.15.0 resolution: "tsconfig-paths@npm:3.15.0"