From 29fb05517ec804fc1b4b74954b76c49cf85f6143 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:37:34 -0400 Subject: [PATCH] feat(@angular/build): migrate i18n inliner to oxc-parser + magic-string This refactors the i18n translation and locale inlining in the ESBuild pipeline to use `oxc-parser` and `magic-string` instead of `@babel/core`. By using the lightweight AST and precise token spans provided by OXC, we are able to perform `$localize` inlining and locale name replacements via targeted `magic-string` overwrites in-place. This completely removes the dependency on `@babel/core` and the custom/upstream Babel plugins in the worker, yielding faster startup times and significant compile-time speedups for localized builds. --- packages/angular/build/BUILD.bazel | 2 + packages/angular/build/package.json | 2 + .../src/tools/esbuild/i18n-inliner-worker.ts | 159 ++++++----- pnpm-lock.yaml | 255 ++++++++++++++++++ 4 files changed, 336 insertions(+), 82 deletions(-) diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel index 52eb43f9472c..4f4b8f003de0 100644 --- a/packages/angular/build/BUILD.bazel +++ b/packages/angular/build/BUILD.bazel @@ -85,6 +85,7 @@ ts_project( ":node_modules/@babel/helper-annotate-as-pure", ":node_modules/@babel/helper-split-export-declaration", ":node_modules/@inquirer/confirm", + ":node_modules/@oxc-project/types", ":node_modules/@vitejs/plugin-basic-ssl", ":node_modules/beasties", ":node_modules/browserslist", @@ -97,6 +98,7 @@ ts_project( ":node_modules/magic-string", ":node_modules/mrmime", ":node_modules/ng-packagr", + ":node_modules/oxc-parser", ":node_modules/parse5-html-rewriting-stream", ":node_modules/picomatch", ":node_modules/piscina", diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json index 90d2e99c0dda..2bd38201d6ce 100644 --- a/packages/angular/build/package.json +++ b/packages/angular/build/package.json @@ -33,6 +33,7 @@ "listr2": "10.2.2", "magic-string": "0.30.21", "mrmime": "2.0.1", + "oxc-parser": "0.140.0", "parse5-html-rewriting-stream": "8.0.1", "picomatch": "4.0.5", "piscina": "5.2.0", @@ -50,6 +51,7 @@ "devDependencies": { "@angular-devkit/core": "workspace:*", "@angular/ssr": "workspace:*", + "@oxc-project/types": "0.140.0", "istanbul-lib-instrument": "6.0.3", "jsdom": "29.1.1", "less": "4.6.7", diff --git a/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts b/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts index 9bdf4a8b422a..23957fc1790e 100644 --- a/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts +++ b/packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts @@ -6,11 +6,11 @@ * found in the LICENSE file at https://angular.dev/license */ -import remapping, { SourceMapInput } from '@ampproject/remapping'; -import { NodePath, PluginItem, parseSync, transformFromAstAsync, types } from '@babel/core'; +import remapping, { type EncodedSourceMap, type SourceMapInput } from '@ampproject/remapping'; +import MagicString from 'magic-string'; import assert from 'node:assert'; import { workerData } from 'node:worker_threads'; -import { assertIsError } from '../../utils/error'; +import { Visitor, parseSync } from 'oxc-parser'; /** * The options passed to the inliner for each file request @@ -80,11 +80,7 @@ export default async function inlineFile(request: InlineFileRequest) { const code = await data.text(); const map = await files.get(request.filename + '.map')?.text(); - const result = await transformWithBabel( - code, - map && (JSON.parse(map) as SourceMapInput), - request, - ); + const result = await transformWithOxc(code, map && (JSON.parse(map) as SourceMapInput), request); return { file: request.filename, @@ -102,7 +98,7 @@ export default async function inlineFile(request: InlineFileRequest) { * @returns An object containing the inlined code. */ export async function inlineCode(request: InlineCodeRequest) { - const result = await transformWithBabel(request.code, undefined, request); + const result = await transformWithOxc(request.code, undefined, request); return { output: result.code, @@ -136,95 +132,94 @@ async function loadLocalizeTools(): Promise { } /** - * Creates the needed Babel plugins to inline a given locale and translation for a JavaScript file. - * @param locale A string containing the locale specifier to use. - * @param translation A object record containing locale specific messages to use. - * @returns An array of Babel plugins. - */ -async function createI18nPlugins(locale: string, translation: Record | undefined) { - const { Diagnostics, makeEs2015TranslatePlugin } = await loadLocalizeTools(); - - const plugins: PluginItem[] = []; - const diagnostics = new Diagnostics(); - - plugins.push( - makeEs2015TranslatePlugin(diagnostics, translation || {}, { - missingTranslation: translation === undefined ? 'ignore' : missingTranslation, - }) as unknown as PluginItem, - ); - - // Create a plugin to replace the locale specifier constant inject by the build system with the actual specifier - plugins.push(() => ({ - visitor: { - StringLiteral(path: NodePath) { - if (path.node.value === '___NG_LOCALE_INSERT___') { - path.replaceWith(types.stringLiteral(locale)); - } - }, - }, - })); - - return { diagnostics, plugins }; -} - -/** - * Transforms a JavaScript file using Babel to inline the request locale and translation. + * Transforms a JavaScript file using OXC and Magic-String to inline the request locale and translation. * @param code A string containing the JavaScript code to transform. * @param map A sourcemap object for the provided JavaScript code. * @param options The inline request options to use. * @returns An object containing the code, map, and diagnostics from the transformation. */ -async function transformWithBabel( +async function transformWithOxc( code: string, map: SourceMapInput | undefined, options: InlineFileRequest, ) { - let ast; - try { - ast = parseSync(code, { - babelrc: false, - configFile: false, - sourceType: 'unambiguous', - filename: options.filename, - }); - } catch (error) { - assertIsError(error); - - // Make the error more readable. - // Same errors will contain the full content of the file as the error message - // Which makes it hard to find the actual error message. - const index = error.message.indexOf(')\n'); - const msg = index !== -1 ? error.message.slice(0, index + 1) : error.message; - throw new Error(`${msg}\nAn error occurred inlining file "${options.filename}"`, { - cause: error, - }); - } + const { program } = parseSync(options.filename, code, { + sourceType: 'unambiguous', + }); - if (!ast) { - throw new Error(`Unknown error occurred inlining file "${options.filename}"`); + if (!program) { + throw new Error(`Unknown error occurred parsing file "${options.filename}" with OXC.`); } - const { diagnostics, plugins } = await createI18nPlugins(options.locale, options.translation); - const transformResult = await transformFromAstAsync(ast, code, { - filename: options.filename, - // false is a valid value but not included in the type definition - inputSourceMap: false as unknown as undefined, - sourceMaps: !!map, - compact: shouldOptimize, - configFile: false, - babelrc: false, - browserslistConfigFile: false, - plugins, + const magicString = new MagicString(code); + const { Diagnostics, translate } = await loadLocalizeTools(); + const diagnostics = new Diagnostics(); + + const visitor = new Visitor({ + Literal(node) { + if (typeof node.value === 'string' && node.value === '___NG_LOCALE_INSERT___') { + magicString.overwrite(node.start, node.end, JSON.stringify(options.locale)); + } + }, + 'TaggedTemplateExpression:exit'(node) { + if (node.tag.type === 'Identifier' && node.tag.name === '$localize') { + const cooked = node.quasi.quasis.map((q) => q.value.cooked); + const raw = node.quasi.quasis.map((q) => q.value.raw); + const messageParts = Object.assign(cooked, { raw }) as unknown as TemplateStringsArray; + + const [translatedParts, translatedSubstitutions] = translate( + diagnostics, + options.translation || {}, + messageParts, + node.quasi.expressions.map((_, index) => index), + options.translation === undefined ? 'ignore' : missingTranslation, + ); + + // Reconstruct the new template/string literal replacement + let replacement: string; + if (translatedSubstitutions.length === 0) { + replacement = JSON.stringify(translatedParts[0]); + } else { + replacement = '`'; + for (let i = 0; i < translatedParts.length; i++) { + const escapedPart = JSON.stringify(translatedParts[i]) + .slice(1, -1) + .replace(/\\"/g, '"') + .replace(/`/g, '\\`') + .replace(/\$\{/g, '\\${'); + replacement += escapedPart; + + if (i < translatedSubstitutions.length) { + const originalIndex = translatedSubstitutions[i]; + const exprNode = node.quasi.expressions[originalIndex]; + const exprCode = magicString.slice(exprNode.start, exprNode.end); + replacement += '${' + exprCode + '}'; + } + } + replacement += '`'; + } + + magicString.overwrite(node.start, node.end, replacement); + } + }, }); - if (!transformResult || !transformResult.code) { - throw new Error(`Unknown error occurred processing bundle for "${options.filename}".`); - } + visitor.visit(program); + const outputCode = magicString.toString(); let outputMap; - if (map && transformResult.map) { - outputMap = remapping([transformResult.map as SourceMapInput, map], () => null); + if (map && magicString.hasChanged()) { + const rawMap = magicString.generateMap({ + source: options.filename, + includeContent: true, + hires: 'boundary', + }); + outputMap = remapping([rawMap as EncodedSourceMap, map], () => null); } - return { code: transformResult.code, map: outputMap && JSON.stringify(outputMap), diagnostics }; + return { + code: outputCode, + map: outputMap && JSON.stringify(outputMap), + diagnostics, + }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f4f12f4da90..f918fd8d627f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -373,6 +373,9 @@ importers: mrmime: specifier: 2.0.1 version: 2.0.1 + oxc-parser: + specifier: 0.140.0 + version: 0.140.0 parse5-html-rewriting-stream: specifier: 8.0.1 version: 8.0.1 @@ -410,6 +413,9 @@ importers: '@angular/ssr': specifier: workspace:* version: link:../ssr + '@oxc-project/types': + specifier: 0.140.0 + version: 0.140.0 istanbul-lib-instrument: specifier: 6.0.3 version: 6.0.3 @@ -1691,9 +1697,15 @@ packages: '@emnapi/core@1.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} @@ -2830,9 +2842,139 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + resolution: {integrity: sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.140.0': + resolution: {integrity: sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.140.0': + resolution: {integrity: sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.140.0': + resolution: {integrity: sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.140.0': + resolution: {integrity: sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + resolution: {integrity: sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + resolution: {integrity: sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + resolution: {integrity: sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + resolution: {integrity: sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + resolution: {integrity: sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + resolution: {integrity: sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + resolution: {integrity: sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + resolution: {integrity: sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + resolution: {integrity: sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + resolution: {integrity: sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + resolution: {integrity: sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + resolution: {integrity: sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + resolution: {integrity: sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + resolution: {integrity: sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + resolution: {integrity: sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + '@parcel/watcher-android-arm64@2.5.6': resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} engines: {node: '>= 10.0.0'} @@ -6612,6 +6754,10 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxc-parser@0.140.0: + resolution: {integrity: sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -9275,11 +9421,22 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.2': dependencies: tslib: 2.8.1 @@ -10306,6 +10463,13 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@noble/hashes@1.4.0': {} '@nodelib/fs.scandir@2.1.5': @@ -10453,8 +10617,74 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.140.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + optional: true + '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.140.0': {} + '@parcel/watcher-android-arm64@2.5.6': optional: true @@ -14723,6 +14953,31 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxc-parser@0.140.0: + dependencies: + '@oxc-project/types': 0.140.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.140.0 + '@oxc-parser/binding-android-arm64': 0.140.0 + '@oxc-parser/binding-darwin-arm64': 0.140.0 + '@oxc-parser/binding-darwin-x64': 0.140.0 + '@oxc-parser/binding-freebsd-x64': 0.140.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.140.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.140.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.140.0 + '@oxc-parser/binding-linux-arm64-musl': 0.140.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.140.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-musl': 0.140.0 + '@oxc-parser/binding-openharmony-arm64': 0.140.0 + '@oxc-parser/binding-wasm32-wasi': 0.140.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.140.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.140.0 + '@oxc-parser/binding-win32-x64-msvc': 0.140.0 + p-cancelable@2.1.1: {} p-finally@1.0.0: {}