Skip to content

Commit 9c02306

Browse files
clydinalan-agius4
authored andcommitted
refactor(@angular-devkit/build-angular): use built-in async generator downleveling in esbuild
As of esbuild v0.18.8, async generators can be downleveled when not supported. This improvement allows for the removal of the babel plugins to perform the async generator downleveling that were previously used. This can provide a performance benefit for cases of async generator usage in application and third-party library code.
1 parent 0580230 commit 9c02306

File tree

3 files changed

+10
-27
lines changed

3 files changed

+10
-27
lines changed

packages/angular_devkit/build_angular/src/tools/esbuild/javascript-transformer-worker.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ interface JavaScriptTransformRequest {
1818
sourcemap: boolean;
1919
thirdPartySourcemaps: boolean;
2020
advancedOptimizations: boolean;
21-
forceAsyncTransformation?: boolean;
2221
skipLinker: boolean;
2322
jit: boolean;
2423
}
@@ -41,16 +40,13 @@ async function transformWithBabel({
4140
data,
4241
...options
4342
}: JavaScriptTransformRequest): Promise<string> {
44-
const forceAsyncTransformation =
45-
options.forceAsyncTransformation ??
46-
(!/[\\/][_f]?esm2015[\\/]/.test(filename) && /async(?:\s+function)?\s*\*/.test(data));
4743
const shouldLink = !options.skipLinker && (await requiresLinking(filename, data));
4844
const useInputSourcemap =
4945
options.sourcemap &&
5046
(!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
5147

5248
// If no additional transformations are needed, return the data directly
53-
if (!forceAsyncTransformation && !options.advancedOptimizations && !shouldLink) {
49+
if (!options.advancedOptimizations && !shouldLink) {
5450
// Strip sourcemaps if they should not be used
5551
return useInputSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
5652
}
@@ -87,7 +83,6 @@ async function transformWithBabel({
8783
jitMode: options.jit,
8884
linkerPluginCreator,
8985
},
90-
forceAsyncTransformation,
9186
optimize: options.advancedOptimizations && {
9287
pureTopLevel: safeAngularPackage,
9388
},

packages/angular_devkit/build_angular/src/tools/esbuild/javascript-transformer.ts

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class JavaScriptTransformer {
5858
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
5959
*/
6060
transformFile(filename: string, skipLinker?: boolean): Promise<Uint8Array> {
61-
// Always send the request to a worker. Files are almost always from node modules which measn
61+
// Always send the request to a worker. Files are almost always from node modules which means
6262
// they may need linking. The data is also not yet available to perform most transformation checks.
6363
return this.#workerPool.run({
6464
filename,
@@ -78,29 +78,20 @@ export class JavaScriptTransformer {
7878
async transformData(filename: string, data: string, skipLinker: boolean): Promise<Uint8Array> {
7979
// Perform a quick test to determine if the data needs any transformations.
8080
// This allows directly returning the data without the worker communication overhead.
81-
let forceAsyncTransformation;
8281
if (skipLinker && !this.#commonOptions.advancedOptimizations) {
83-
// If the linker is being skipped and no optimizations are needed, only async transformation is left.
84-
// This checks for async generator functions and class methods. All other async transformation is handled by esbuild.
85-
forceAsyncTransformation = data.includes('async') && /async(?:\s+function)?\s*\*/.test(data);
82+
const keepSourcemap =
83+
this.#commonOptions.sourcemap &&
84+
(!!this.#commonOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
8685

87-
if (!forceAsyncTransformation) {
88-
const keepSourcemap =
89-
this.#commonOptions.sourcemap &&
90-
(!!this.#commonOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
91-
92-
return Buffer.from(
93-
keepSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
94-
'utf-8',
95-
);
96-
}
86+
return Buffer.from(
87+
keepSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
88+
'utf-8',
89+
);
9790
}
9891

9992
return this.#workerPool.run({
10093
filename,
10194
data,
102-
// Send the async check result if present to avoid rechecking in the worker
103-
forceAsyncTransformation,
10495
skipLinker,
10596
...this.#commonOptions,
10697
});

packages/angular_devkit/build_angular/src/tools/esbuild/utils.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,7 @@ export async function logMessages(
123123
export function getFeatureSupport(target: string[]): BuildOptions['supported'] {
124124
const supported: Record<string, boolean> = {
125125
// Native async/await is not supported with Zone.js. Disabling support here will cause
126-
// esbuild to downlevel async/await and for await...of to a Zone.js supported form. However, esbuild
127-
// does not currently support downleveling async generators. Instead babel is used within the JS/TS
128-
// loader to perform the downlevel transformation.
129-
// NOTE: If esbuild adds support in the future, the babel support for async generators can be disabled.
126+
// esbuild to downlevel async/await, async generators, and for await...of to a Zone.js supported form.
130127
'async-await': false,
131128
// V8 currently has a performance defect involving object spread operations that can cause signficant
132129
// degradation in runtime performance. By not supporting the language feature here, a downlevel form

0 commit comments

Comments
 (0)