Repository navigation
fix(@angular/build): fall back to Babel linker in WebContainer environments #34623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,7 +19,6 @@ import { | |||||||||||||||||||||||||||||||
| loadInputSourceMapFromUrl, | ||||||||||||||||||||||||||||||||
| removeSourceMappingURL, | ||||||||||||||||||||||||||||||||
| } from '../../utils/source-map'; | ||||||||||||||||||||||||||||||||
| import { transform as transformWithOxc } from '../oxc/oxc-transform.js'; | ||||||||||||||||||||||||||||||||
| import type { JavaScriptTransformerOptions } from './javascript-transformer'; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| interface JavaScriptTransformRequest { | ||||||||||||||||||||||||||||||||
|
|
@@ -54,6 +53,8 @@ let babelLinkerDeps: | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| let remapping: typeof import('@ampproject/remapping').default | undefined; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| let oxcTransform: typeof import('../oxc/oxc-transform.js').transform | undefined; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const textDecoder = new TextDecoder(); | ||||||||||||||||||||||||||||||||
| const textEncoder = new TextEncoder(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -181,7 +182,18 @@ async function transformJavaScriptImpl( | |||||||||||||||||||||||||||||||
| coverageMap = result.map; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (shouldLink && useBabelLinker) { | ||||||||||||||||||||||||||||||||
| let oxcLink = shouldLink && !useBabelLinker; | ||||||||||||||||||||||||||||||||
| const shouldRunOxc = oxcLink || (!process.versions.webcontainer && advancedOptimizations); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (shouldRunOxc) { | ||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
| oxcTransform ??= (await import('../oxc/oxc-transform.js')).transform; | ||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||
| oxcLink = false; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+188
to
+194
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolve the cached let transform: typeof import('../oxc/oxc-transform.js').transform | null = null;
if (shouldRunOxc) {
oxcTransformPromise ??= import('../oxc/oxc-transform.js')
.then((m) => m.transform)
.catch(() => null);
transform = await oxcTransformPromise;
if (!transform) {
oxcLink = false;
}
} |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (shouldLink && (useBabelLinker || !oxcLink)) { | ||||||||||||||||||||||||||||||||
| babelLinkerDeps ??= Promise.all([ | ||||||||||||||||||||||||||||||||
| import('@angular/compiler-cli/linker/babel'), | ||||||||||||||||||||||||||||||||
| import('@angular/compiler-cli'), | ||||||||||||||||||||||||||||||||
|
|
@@ -222,14 +234,13 @@ async function transformJavaScriptImpl( | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Run Oxc linking and/or advanced optimizations in a single unified AST traversal pass | ||||||||||||||||||||||||||||||||
| const oxcLink = shouldLink && !useBabelLinker; | ||||||||||||||||||||||||||||||||
| if (oxcLink || advancedOptimizations) { | ||||||||||||||||||||||||||||||||
| if (oxcTransform && (oxcLink || advancedOptimizations)) { | ||||||||||||||||||||||||||||||||
| const sideEffectFree = options.sideEffects === false; | ||||||||||||||||||||||||||||||||
| const safeAngularPackage = | ||||||||||||||||||||||||||||||||
| sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename); | ||||||||||||||||||||||||||||||||
| const topLevelSafeMode = !safeAngularPackage; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const result = transformWithOxc(filename, code, { | ||||||||||||||||||||||||||||||||
| const result = oxcTransform(filename, code, { | ||||||||||||||||||||||||||||||||
|
Comment on lines
+237
to
+243
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the check and invocation to use the locally resolved
Suggested change
|
||||||||||||||||||||||||||||||||
| link: oxcLink, | ||||||||||||||||||||||||||||||||
| jit, | ||||||||||||||||||||||||||||||||
| advancedOptimizations, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a module-level variable
oxcTransformthat is assigned directly inside thetry/catchblock can lead to repeated failing import attempts. If the import ofoxc-transform.jsfails (which is expected in WebContainer environments when the WASM/WASI bindings fail),oxcTransformremainsundefined. Consequently, every subsequent file transformation in the worker will re-attempt the import, throwing and catching errors repeatedly. This can severely degrade build performance, especially if the fallback script attempts synchronous process execution. We should instead use a Promise to cache the import attempt (including its failure state).