diff --git a/packages/angular_devkit/build_angular/src/babel/presets/application.ts b/packages/angular_devkit/build_angular/src/babel/presets/application.ts index 366f07e48a10..2b180ed13fc8 100644 --- a/packages/angular_devkit/build_angular/src/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/babel/presets/application.ts @@ -16,6 +16,16 @@ import type { import { strict as assert } from 'assert'; import * as fs from 'fs'; import * as path from 'path'; +import browserslist from 'browserslist'; + +/** + * List of browsers which are affected by a WebKit bug where class field + * initializers might have incorrect variable scopes. + * + * See: https://github.com/angular/angular-cli/issues/24355#issuecomment-1333477033 + * See: https://github.com/WebKit/WebKit/commit/e8788a34b3d5f5b4edd7ff6450b80936bff396f2 + */ +const safariClassFieldScopeBugBrowsers = browserslist(['Safari <15', 'iOS <15']); export type DiagnosticReporter = (type: 'error' | 'warning' | 'info', message: string) => void; @@ -172,12 +182,23 @@ export default function (api: unknown, options: ApplicationPresetOptions) { } if (options.forcePresetEnv) { + const selectedBrowsers = browserslist(options.supportedBrowsers); + const includePlugins: string[] = []; + + // If a Safari browser affected by the class field scope bug is selected, we + // downlevel class properties by ensuring the class properties Babel plugin + // is always included- regardless of the preset-env targets. + if (safariClassFieldScopeBugBrowsers.some((b) => selectedBrowsers.includes(b))) { + includePlugins.push('@babel/plugin-proposal-class-properties'); + } + presets.push([ require('@babel/preset-env').default, { bugfixes: true, modules: false, targets: options.supportedBrowsers, + include: includePlugins, exclude: ['transform-typeof-symbol'], }, ]); diff --git a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts index 78af1b28d480..f0e9d483f3b3 100644 --- a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts +++ b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts @@ -108,7 +108,7 @@ export default custom(() => { // Analyze for ES target processing if (customOptions.supportedBrowsers?.length) { // Applications code ES version can be controlled using TypeScript's `target` option. - // However, this doesn't effect libraries and hence we use preset-env to downlevel ES fetaures + // However, this doesn't effect libraries and hence we use preset-env to downlevel ES features // based on the supported browsers in browserlist. customOptions.forcePresetEnv = true; }