From 507f756c34171db842365398150460e1e29f531a Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 12 Dec 2022 08:50:41 +0000 Subject: [PATCH] fix(@angular-devkit/build-angular): downlevel class private methods when targeting Safari <=v15 This commits enables `@babel/plugin-proposal-private-methods` when targeting Safari <=v15 as this is needed to handle private class methods when using `@babel/plugin-proposal-class-properties`. Closes #24411 (cherry picked from commit 97373016cfe2635125015b2fec390f43d22ebf31) --- .../src/babel/presets/application.ts | 5 +- .../tests/misc/safari-15-class-properties.ts | 64 +++++++++++-------- 2 files changed, 43 insertions(+), 26 deletions(-) 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 13b184d6e37e..02011ab5a701 100644 --- a/packages/angular_devkit/build_angular/src/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/babel/presets/application.ts @@ -197,7 +197,10 @@ export default function (api: unknown, options: ApplicationPresetOptions) { // downlevel class properties by ensuring the class properties Babel plugin // is always included- regardless of the preset-env targets. if (options.supportedBrowsers.some((b) => safariClassFieldScopeBugBrowsers.has(b))) { - includePlugins.push('@babel/plugin-proposal-class-properties'); + includePlugins.push( + '@babel/plugin-proposal-class-properties', + '@babel/plugin-proposal-private-methods', + ); } presets.push([ diff --git a/tests/legacy-cli/e2e/tests/misc/safari-15-class-properties.ts b/tests/legacy-cli/e2e/tests/misc/safari-15-class-properties.ts index a0dce7186cff..ef9b42b85b11 100644 --- a/tests/legacy-cli/e2e/tests/misc/safari-15-class-properties.ts +++ b/tests/legacy-cli/e2e/tests/misc/safari-15-class-properties.ts @@ -1,6 +1,6 @@ -import { expectFileToExist, readFile, writeFile } from '../../utils/fs'; +import assert from 'node:assert'; +import { expectFileToExist, readFile, writeFile, replaceInFile } from '../../utils/fs'; import { ng } from '../../utils/process'; -import { updateJsonFile } from '../../utils/project'; const unexpectedStaticFieldErrorMessage = 'Found unexpected static field. This indicates that the Safari <=v15 ' + @@ -8,15 +8,19 @@ const unexpectedStaticFieldErrorMessage = 'See: https://github.com/angular/angular-cli/pull/24357'; export default async function () { - await updateJsonFile('angular.json', (workspace) => { - const build = workspace.projects['test-project'].architect.build; - build.defaultConfiguration = undefined; - build.options = { - ...build.options, - optimization: false, - outputHashing: 'none', - }; - }); + // Add a private method + await replaceInFile( + 'src/app/app.component.ts', + `title = 'test-project';`, + ` + #myPrivateMethod() { return 1 } + + constructor() { + console.log(this.#myPrivateMethod) + } + + title = 'test-project';`, + ); // Matches two types of static fields that indicate that the Safari bug // may still occur. With the workaround this should not appear in bundles. @@ -24,33 +28,43 @@ export default async function () { // - static #_ = this.ecmp = bla const staticIndicatorRegex = /static\s+(\{|#[_\d]+\s+=)/; - await ng('build'); + await ng('build', '--configuration=development'); await expectFileToExist('dist/test-project/main.js'); const mainContent = await readFile('dist/test-project/main.js'); - // TODO: This default cause can be removed in the future when Safari v15 // is longer included in the default browserlist configuration of CLI apps. - if (staticIndicatorRegex.test(mainContent)) { - throw new Error(unexpectedStaticFieldErrorMessage); - } + assert.doesNotMatch(mainContent, staticIndicatorRegex, unexpectedStaticFieldErrorMessage); await writeFile('.browserslistrc', 'last 1 chrome version'); - - await ng('build'); + await ng('build', '--configuration=development'); await expectFileToExist('dist/test-project/main.js'); const mainContentChromeLatest = await readFile('dist/test-project/main.js'); - if (!staticIndicatorRegex.test(mainContentChromeLatest)) { - throw new Error('Expected static fields to be used when Safari <=v15 is not targeted.'); - } + assert.match( + mainContentChromeLatest, + staticIndicatorRegex, + 'Expected static fields to be used when Safari <=v15 is not targeted.', + ); + assert.match( + mainContentChromeLatest, + /#myPrivateMethod/, + 'Expected private method to be used when Safari <=v15 is not targeted.', + ); await writeFile('.browserslistrc', 'Safari <=15'); - await ng('build'); + await ng('build', '--configuration=development'); await expectFileToExist('dist/test-project/main.js'); const mainContentSafari15Explicit = await readFile('dist/test-project/main.js'); + assert.doesNotMatch( + mainContentSafari15Explicit, + staticIndicatorRegex, + unexpectedStaticFieldErrorMessage, + ); - if (staticIndicatorRegex.test(mainContentSafari15Explicit)) { - throw new Error(unexpectedStaticFieldErrorMessage); - } + assert.match( + mainContentSafari15Explicit, + /var _myPrivateMethod/, + 'Expected private method to be downlevelled when Safari <=v15 is targeted', + ); }