From e688270cf8665a9de02ba2e9aebab9d703509f85 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 22 Mar 2023 14:27:15 -0700 Subject: [PATCH 1/5] Revert "build: force benchpress to be compiled with ES2020 (#49332)" This reverts commit 132c00c2f88faf97591de0477f80397e5e3c31d4. --- packages/benchpress/BUILD.bazel | 3 --- packages/benchpress/test/BUILD.bazel | 3 --- tools/defaults.bzl | 7 +++---- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/benchpress/BUILD.bazel b/packages/benchpress/BUILD.bazel index 9378ac34eed2..dd207fbce4eb 100644 --- a/packages/benchpress/BUILD.bazel +++ b/packages/benchpress/BUILD.bazel @@ -10,9 +10,6 @@ ts_library( "src/**/*.ts", ], ), - # TODO(alanagius) fix benchpress to compile with es2022 - devmode_target = "es2020", - prodmode_target = "es2020", deps = [ "//packages:types", "//packages/core", diff --git a/packages/benchpress/test/BUILD.bazel b/packages/benchpress/test/BUILD.bazel index 0642530a1a71..7449f4f9d6bf 100644 --- a/packages/benchpress/test/BUILD.bazel +++ b/packages/benchpress/test/BUILD.bazel @@ -4,9 +4,6 @@ ts_library( name = "test_lib", testonly = True, srcs = glob(["**/*.ts"]), - # TODO(alanagius) fix benchpress to compile with es2022 - devmode_target = "es2020", - prodmode_target = "es2020", deps = [ "//packages:types", "//packages/benchpress", diff --git a/tools/defaults.bzl b/tools/defaults.bzl index 60e3d460aa32..ddf67325634e 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -103,8 +103,6 @@ def ts_library( deps = [], module_name = None, package_name = None, - devmode_target = "es2022", - prodmode_target = "es2022", **kwargs): """Default values for ts_library""" deps = deps + ["@npm//tslib"] @@ -124,6 +122,7 @@ def ts_library( if not package_name: package_name = _default_module_name(testonly) + default_target = "es2022" default_module = "esnext" _ts_library( @@ -131,13 +130,13 @@ def ts_library( tsconfig = tsconfig, testonly = testonly, deps = deps, - devmode_target = devmode_target, + devmode_target = default_target, devmode_module = default_module, # For prodmode, the target is set to `ES2022`. `@bazel/typecript` sets `ES2015` by # default. Note that this should be in sync with the `ng_module` tsconfig generation. # https://github.com/bazelbuild/rules_nodejs/blob/901df3868e3ceda177d3ed181205e8456a5592ea/third_party/github.com/bazelbuild/rules_typescript/internal/common/tsconfig.bzl#L195 # https://github.com/bazelbuild/rules_nodejs/blob/9b36274dba34204625579463e3da054a9f42cb47/packages/typescript/internal/build_defs.bzl#L85. - prodmode_target = prodmode_target, + prodmode_target = default_target, prodmode_module = default_module, # `module_name` is used for AMD module names within emitted JavaScript files. module_name = module_name, From 081b8b5848b38942861f902d34e2878457d84586 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 22 Mar 2023 14:27:18 -0700 Subject: [PATCH 2/5] Revert "build: update `ts_library` to produce `ES2022` (#49332)" This reverts commit 262c989c81a40292f05b8a083ac7b9944b6dbf40. --- packages/tsconfig-build.json | 4 +--- tools/defaults.bzl | 4 ++-- tools/postinstall-patches.js | 4 ---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/tsconfig-build.json b/packages/tsconfig-build.json index 54a51e755905..1b9f4595e3e9 100644 --- a/packages/tsconfig-build.json +++ b/packages/tsconfig-build.json @@ -16,9 +16,7 @@ "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "module": "esnext", - "target": "es2022", - // Keep the below in sync with ng_module.bzl - "useDefineForClassFields": false, + "target": "es2020", "lib": ["es2020", "dom"], "skipLibCheck": true, // don't auto-discover @types/node, it results in a /// f.startsWith('babel__')).forEach(pkg => { sed('-i', 'private rootDirsRelative;', 'rootDirsRelative(fileName: string): string;', 'node_modules/@bazel/concatjs/internal/tsc_wrapped/compiler_host.d.ts'); -// Add support for ES2022 in ts_library -sed('-i', '"es2020", "esnext"', '"es2020", "es2022", "esnext"', - 'node_modules/@bazel/concatjs/internal/build_defs.bzl'); - log('\n# patch: delete d.ts files referring to rxjs-compat'); // more info in https://github.com/angular/angular/pull/33786 rm('-rf', [ From bf87783e3e1e85756c92f5a5c734daf2a094d05a Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 22 Mar 2023 14:27:21 -0700 Subject: [PATCH 3/5] Revert "ci: disable system js tests (#49332)" This reverts commit 9c3f8d52d89918fcb78301e981aff6b4ffb092fb. --- aio/content/examples/upgrade-module/BUILD.bazel | 6 +----- aio/content/examples/upgrade-phonecat-2-hybrid/BUILD.bazel | 6 +----- aio/content/examples/upgrade-phonecat-3-final/BUILD.bazel | 1 - aio/package.json | 6 +++--- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/aio/content/examples/upgrade-module/BUILD.bazel b/aio/content/examples/upgrade-module/BUILD.bazel index 0c13cff305bf..19bd04f2a90a 100644 --- a/aio/content/examples/upgrade-module/BUILD.bazel +++ b/aio/content/examples/upgrade-module/BUILD.bazel @@ -8,9 +8,5 @@ docs_example( flaky = True, # TODO: figure out why this is flaky or times out # This example downloads and inlines resources test_exec_properties = ENABLE_NETWORK, - test_tags = [ - "requires-network", - # This is currently broken due to usage of ESM2022 which does not work out-of-the-box with system.js. - "broken", - ], + test_tags = ["requires-network"], ) diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/BUILD.bazel b/aio/content/examples/upgrade-phonecat-2-hybrid/BUILD.bazel index 7685052b87b8..18ff1e776fe1 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/BUILD.bazel +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/BUILD.bazel @@ -8,9 +8,5 @@ docs_example( flaky = True, # TODO: figure out why this is flaky or times out # This example downloads and inlines resources test_exec_properties = ENABLE_NETWORK, - test_tags = [ - "requires-network", - # This is currently broken due to usage of ESM2022 which does not work out-of-the-box with system.js. - "broken", - ], + test_tags = ["requires-network"], ) diff --git a/aio/content/examples/upgrade-phonecat-3-final/BUILD.bazel b/aio/content/examples/upgrade-phonecat-3-final/BUILD.bazel index a6d2ecfe030b..ffefa1698cd3 100644 --- a/aio/content/examples/upgrade-phonecat-3-final/BUILD.bazel +++ b/aio/content/examples/upgrade-phonecat-3-final/BUILD.bazel @@ -5,5 +5,4 @@ package(default_visibility = ["//visibility:public"]) docs_example( name = "upgrade-phonecat-3-final", flaky = True, # TODO: figure out why this is flaky or times out - test_tags = ["broken"], # This is currently broken due to usage of ESM2022 which does not work out-of-the-box with system.js. ) diff --git a/aio/package.json b/aio/package.json index e120ea2083d9..1fe49936aca9 100644 --- a/aio/package.json +++ b/aio/package.json @@ -12,10 +12,10 @@ "build-prod": "yarn build --config=release", "build-local": "yarn build --config=aio_local_deps", "lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint && yarn security-lint", - "test": "bazel test //aio:test --test_output=streamed --test_tag_filters=-broken", - "test-and-watch": "ibazel test //aio:test-and-watch --test_output=streamed --test_tag_filters=-broken", + "test": "bazel test //aio:test --test_output=streamed", + "test-and-watch": "ibazel test //aio:test-and-watch --test_output=streamed", "test-local": "yarn test --config=aio_local_deps", - "test:ci": "bazel test //aio/... --test_tag_filters=-broken", + "test:ci": "bazel test //aio/...", "test-local:ci": "yarn test:ci --config=aio_local_deps", "e2e": "bazel test //aio:e2e", "e2e-local": "yarn e2e --config=aio_local_deps", From 8c31edf65235f590e9cfb6e96133010fbf8bb758 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 22 Mar 2023 14:27:23 -0700 Subject: [PATCH 4/5] Revert "test: remove google-closure-compiler from tests (#49332)" This reverts commit 4d8969628510ca17a3815ee9554e8a69c255530c. --- integration/hello_world__closure/BUILD.bazel | 11 ++++++ integration/hello_world__closure/closure.conf | 20 ++++++++++ .../hello_world__closure/e2e/app.e2e-spec.ts | 11 ++++++ .../e2e/browser.config.json | 15 +++++++ .../e2e/protractor.config.js | 21 ++++++++++ .../hello_world__closure/e2e/tsconfig.json | 6 +++ integration/hello_world__closure/package.json | 38 ++++++++++++++++++ .../hello_world__closure/rollup.config.mjs | 27 +++++++++++++ integration/hello_world__closure/src/app.ts | 11 ++++++ .../src/hello-world.component.ts | 12 ++++++ .../hello_world__closure/src/index.html | 18 +++++++++ integration/hello_world__closure/src/main.ts | 4 ++ .../hello_world__closure/tsconfig.json | 25 ++++++++++++ integration/i18n/BUILD.bazel | 6 +++ integration/i18n/closure.conf | 20 ++++++++++ integration/i18n/e2e/app.e2e-spec.ts | 10 +++++ integration/i18n/e2e/browser.config.json | 15 +++++++ integration/i18n/e2e/protractor.config.js | 21 ++++++++++ integration/i18n/e2e/tsconfig.json | 6 +++ integration/i18n/package.json | 39 +++++++++++++++++++ integration/i18n/rollup.config.mjs | 27 +++++++++++++ integration/i18n/src/app.ts | 11 ++++++ integration/i18n/src/hello-world.component.ts | 9 +++++ integration/i18n/src/index.html | 18 +++++++++ integration/i18n/src/main.ts | 6 +++ integration/i18n/test-locale-folder.js | 14 +++++++ integration/i18n/tsconfig.json | 26 +++++++++++++ integration/ng_elements/closure.conf | 20 ++++++++++ integration/ng_elements/package.json | 4 +- integration/npm_package_archives.bzl | 1 + package.json | 1 + 31 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 integration/hello_world__closure/BUILD.bazel create mode 100644 integration/hello_world__closure/closure.conf create mode 100644 integration/hello_world__closure/e2e/app.e2e-spec.ts create mode 100644 integration/hello_world__closure/e2e/browser.config.json create mode 100644 integration/hello_world__closure/e2e/protractor.config.js create mode 100644 integration/hello_world__closure/e2e/tsconfig.json create mode 100644 integration/hello_world__closure/package.json create mode 100644 integration/hello_world__closure/rollup.config.mjs create mode 100644 integration/hello_world__closure/src/app.ts create mode 100644 integration/hello_world__closure/src/hello-world.component.ts create mode 100644 integration/hello_world__closure/src/index.html create mode 100644 integration/hello_world__closure/src/main.ts create mode 100644 integration/hello_world__closure/tsconfig.json create mode 100644 integration/i18n/BUILD.bazel create mode 100644 integration/i18n/closure.conf create mode 100644 integration/i18n/e2e/app.e2e-spec.ts create mode 100644 integration/i18n/e2e/browser.config.json create mode 100644 integration/i18n/e2e/protractor.config.js create mode 100644 integration/i18n/e2e/tsconfig.json create mode 100644 integration/i18n/package.json create mode 100644 integration/i18n/rollup.config.mjs create mode 100644 integration/i18n/src/app.ts create mode 100644 integration/i18n/src/hello-world.component.ts create mode 100644 integration/i18n/src/index.html create mode 100644 integration/i18n/src/main.ts create mode 100644 integration/i18n/test-locale-folder.js create mode 100644 integration/i18n/tsconfig.json create mode 100644 integration/ng_elements/closure.conf diff --git a/integration/hello_world__closure/BUILD.bazel b/integration/hello_world__closure/BUILD.bazel new file mode 100644 index 000000000000..905707ba692e --- /dev/null +++ b/integration/hello_world__closure/BUILD.bazel @@ -0,0 +1,11 @@ +load("//integration:index.bzl", "ng_integration_test") + +ng_integration_test( + name = "test", + # TODO: Re-enable size-tracking: + # We should define ngDevMode to false in Closure, but --define only works in the global scope. + # With ngDevMode not being set to false, this size tracking test provides little value but a lot of + # headache to continue updating the size. + # track_payload_size = "hello_world_closure", + setup_chromium = True, +) diff --git a/integration/hello_world__closure/closure.conf b/integration/hello_world__closure/closure.conf new file mode 100644 index 000000000000..3d2fcdb95c0f --- /dev/null +++ b/integration/hello_world__closure/closure.conf @@ -0,0 +1,20 @@ +--compilation_level=SIMPLE +--language_in=ECMASCRIPT_2020 +--language_out=ECMASCRIPT_2020 +--js_output_file=dist/bundle.js +--output_manifest=dist/manifest.MF +--variable_renaming_report=dist/variable_renaming_report +--property_renaming_report=dist/property_renaming_report +--create_source_map=%outname%.map + +--warning_level=QUIET +--dependency_mode=PRUNE +--rewrite_polyfills=false + +--module_resolution=node +--package_json_entry_names es2020,module + +node_modules/zone.js/zone_externs.js + +--js built/bundle.js +--entry_point=built/bundle.js diff --git a/integration/hello_world__closure/e2e/app.e2e-spec.ts b/integration/hello_world__closure/e2e/app.e2e-spec.ts new file mode 100644 index 000000000000..04fadb25251a --- /dev/null +++ b/integration/hello_world__closure/e2e/app.e2e-spec.ts @@ -0,0 +1,11 @@ +import { browser, element, by } from 'protractor'; + +describe('Hello world E2E Tests', function () { + it('should display: Hello world!', function () { + browser.get(''); + const div = element(by.css('div')); + expect(div.getText()).toEqual('Hello world!'); + element(by.css('input')).sendKeys('!'); + expect(div.getText()).toEqual('Hello world!!'); + }); +}); diff --git a/integration/hello_world__closure/e2e/browser.config.json b/integration/hello_world__closure/e2e/browser.config.json new file mode 100644 index 000000000000..d62ba608f475 --- /dev/null +++ b/integration/hello_world__closure/e2e/browser.config.json @@ -0,0 +1,15 @@ +{ + "open": false, + "logLevel": "silent", + "port": 4202, + "server": { + "baseDir": "src", + "routes": { + "/dist": "dist", + "/node_modules": "node_modules" + }, + "middleware": { + "0": null + } + } +} \ No newline at end of file diff --git a/integration/hello_world__closure/e2e/protractor.config.js b/integration/hello_world__closure/e2e/protractor.config.js new file mode 100644 index 000000000000..f8ff4a85e6bb --- /dev/null +++ b/integration/hello_world__closure/e2e/protractor.config.js @@ -0,0 +1,21 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts +exports.config = { + specs: [ + '../built/e2e/*.e2e-spec.js' + ], + chromeDriver: process.env.CHROMEDRIVER_BIN, + capabilities: { + browserName: 'chrome', + chromeOptions: { + binary: process.env.CHROME_BIN, + // See /integration/README.md#browser-tests for more info on these args + args: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio'] + } + }, + directConnect: true, + // Port comes from lite-server config `/e2e/browser.config.json` `"port": 4202` + baseUrl: 'http://localhost:4202/', + framework: 'jasmine', + useAllAngular2AppRoots: true +}; diff --git a/integration/hello_world__closure/e2e/tsconfig.json b/integration/hello_world__closure/e2e/tsconfig.json new file mode 100644 index 000000000000..b60faa75fdf2 --- /dev/null +++ b/integration/hello_world__closure/e2e/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "../built/e2e", + "types": ["jasmine", "jasminewd2"], + } +} diff --git a/integration/hello_world__closure/package.json b/integration/hello_world__closure/package.json new file mode 100644 index 000000000000..ebc5b49b9b21 --- /dev/null +++ b/integration/hello_world__closure/package.json @@ -0,0 +1,38 @@ +{ + "name": "angular-integration", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@angular/common": "file:../../dist/packages-dist/common", + "@angular/compiler": "file:../../dist/packages-dist/compiler", + "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", + "@angular/core": "file:../../dist/packages-dist/core", + "@angular/elements": "file:../../dist/packages-dist/elements", + "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", + "rxjs": "file:../../node_modules/rxjs", + "typescript": "file:../../node_modules/typescript", + "tslib": "file:../../node_modules/tslib", + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" + }, + "devDependencies": { + "@babel/core": "file:../../node_modules/@babel/core", + "@rollup/plugin-babel": "file:../../node_modules/@rollup/plugin-babel", + "@rollup/plugin-node-resolve": "file:../../node_modules/@rollup/plugin-node-resolve", + "@types/jasmine": "file:../../node_modules/@types/jasmine", + "@types/jasminewd2": "file:../../node_modules/@types/jasminewd2", + "concurrently": "3.4.0", + "google-closure-compiler": "file:../../node_modules/google-closure-compiler", + "lite-server": "2.2.2", + "protractor": "file:../../node_modules/protractor", + "rollup": "file:../../node_modules/rollup", + "tsickle": "file:../../node_modules/tsickle" + }, + "scripts": { + "closure": "google-closure-compiler --flagfile closure.conf", + "build": "yarn ngc && yarn rollup -c rollup.config.mjs && yarn closure", + "test": "yarn build && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first", + "serve": "lite-server -c e2e/browser.config.json", + "preprotractor": "tsc -p e2e", + "protractor": "protractor e2e/protractor.config.js" + } +} diff --git a/integration/hello_world__closure/rollup.config.mjs b/integration/hello_world__closure/rollup.config.mjs new file mode 100644 index 000000000000..2ddcb493475d --- /dev/null +++ b/integration/hello_world__closure/rollup.config.mjs @@ -0,0 +1,27 @@ +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import {babel} from '@rollup/plugin-babel'; +import {ConsoleLogger, NodeJSFileSystem, LogLevel} from '@angular/compiler-cli'; +import {createEs2015LinkerPlugin} from '@angular/compiler-cli/linker/babel'; + +/** File system used by the Angular linker plugin. */ +const fileSystem = new NodeJSFileSystem(); +/** Logger used by the Angular linker plugin. */ +const logger = new ConsoleLogger(LogLevel.info); +/** Linker babel plugin. */ +const linkerPlugin = createEs2015LinkerPlugin({ + fileSystem, + logger, + linkerJitMode: false, +}); + +export default { + input: './built/src/main.js', + output: { + file: './built/bundle.js', + format: 'iife' + }, + plugins: [ + nodeResolve(), + babel({plugins: [linkerPlugin]}), + ] +} \ No newline at end of file diff --git a/integration/hello_world__closure/src/app.ts b/integration/hello_world__closure/src/app.ts new file mode 100644 index 000000000000..31ecac712b0d --- /dev/null +++ b/integration/hello_world__closure/src/app.ts @@ -0,0 +1,11 @@ +import {HelloWorldComponent} from './hello-world.component'; + +import {NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +@NgModule({ + declarations: [HelloWorldComponent], + bootstrap: [HelloWorldComponent], + imports: [BrowserModule], +}) +export class AppModule {} diff --git a/integration/hello_world__closure/src/hello-world.component.ts b/integration/hello_world__closure/src/hello-world.component.ts new file mode 100644 index 000000000000..87b9ca39de84 --- /dev/null +++ b/integration/hello_world__closure/src/hello-world.component.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'hello-world-app', + template: ` +
Hello {{ name }}!
+ + `, +}) +export class HelloWorldComponent { + name: string = 'world'; +} diff --git a/integration/hello_world__closure/src/index.html b/integration/hello_world__closure/src/index.html new file mode 100644 index 000000000000..5a1c1afc2df3 --- /dev/null +++ b/integration/hello_world__closure/src/index.html @@ -0,0 +1,18 @@ + + + + + + Hello World + + + + + Loading... + + + + + + + diff --git a/integration/hello_world__closure/src/main.ts b/integration/hello_world__closure/src/main.ts new file mode 100644 index 000000000000..1870d726a819 --- /dev/null +++ b/integration/hello_world__closure/src/main.ts @@ -0,0 +1,4 @@ +import {platformBrowser} from '@angular/platform-browser'; +import {AppModule} from './app'; + +platformBrowser().bootstrapModule(AppModule); diff --git a/integration/hello_world__closure/tsconfig.json b/integration/hello_world__closure/tsconfig.json new file mode 100644 index 000000000000..f9590ec2c35d --- /dev/null +++ b/integration/hello_world__closure/tsconfig.json @@ -0,0 +1,25 @@ +{ + "angularCompilerOptions": { + "annotationsAs": "static fields", + "annotateForClosureCompiler": true, + }, + "compilerOptions": { + "module": "es2015", + "moduleResolution": "node", + "target": "es6", + "noImplicitAny": false, + "sourceMap": false, + "experimentalDecorators": true, + "outDir": "built", + "rootDir": ".", + "declaration": true, + "types": [] + }, + "exclude": [ + "vendor", + "node_modules", + "built", + "dist", + "e2e" + ] +} diff --git a/integration/i18n/BUILD.bazel b/integration/i18n/BUILD.bazel new file mode 100644 index 000000000000..45298ffe0143 --- /dev/null +++ b/integration/i18n/BUILD.bazel @@ -0,0 +1,6 @@ +load("//integration:index.bzl", "ng_integration_test") + +ng_integration_test( + name = "test", + setup_chromium = True, +) diff --git a/integration/i18n/closure.conf b/integration/i18n/closure.conf new file mode 100644 index 000000000000..3d2fcdb95c0f --- /dev/null +++ b/integration/i18n/closure.conf @@ -0,0 +1,20 @@ +--compilation_level=SIMPLE +--language_in=ECMASCRIPT_2020 +--language_out=ECMASCRIPT_2020 +--js_output_file=dist/bundle.js +--output_manifest=dist/manifest.MF +--variable_renaming_report=dist/variable_renaming_report +--property_renaming_report=dist/property_renaming_report +--create_source_map=%outname%.map + +--warning_level=QUIET +--dependency_mode=PRUNE +--rewrite_polyfills=false + +--module_resolution=node +--package_json_entry_names es2020,module + +node_modules/zone.js/zone_externs.js + +--js built/bundle.js +--entry_point=built/bundle.js diff --git a/integration/i18n/e2e/app.e2e-spec.ts b/integration/i18n/e2e/app.e2e-spec.ts new file mode 100644 index 000000000000..afcc36025a61 --- /dev/null +++ b/integration/i18n/e2e/app.e2e-spec.ts @@ -0,0 +1,10 @@ +import { browser, element, by } from 'protractor'; + +describe('i18n E2E Tests', function () { + it('remove i18n attributes', function () { + browser.get(''); + const div = element(by.css('div')); + expect(div.getAttribute('title')).not.toBe(null); + expect(div.getAttribute('i18n')).toBe(null); + }); +}); diff --git a/integration/i18n/e2e/browser.config.json b/integration/i18n/e2e/browser.config.json new file mode 100644 index 000000000000..1c4310b25277 --- /dev/null +++ b/integration/i18n/e2e/browser.config.json @@ -0,0 +1,15 @@ +{ + "open": false, + "logLevel": "silent", + "port": 4204, + "server": { + "baseDir": "src", + "routes": { + "/dist": "dist", + "/node_modules": "node_modules" + }, + "middleware": { + "0": null + } + } +} \ No newline at end of file diff --git a/integration/i18n/e2e/protractor.config.js b/integration/i18n/e2e/protractor.config.js new file mode 100644 index 000000000000..cd2fb657131a --- /dev/null +++ b/integration/i18n/e2e/protractor.config.js @@ -0,0 +1,21 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts +exports.config = { + specs: [ + '../built/e2e/*.e2e-spec.js' + ], + chromeDriver: process.env.CHROMEDRIVER_BIN, + capabilities: { + browserName: 'chrome', + chromeOptions: { + binary: process.env.CHROME_BIN, + // See /integration/README.md#browser-tests for more info on these args + args: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio'] + } + }, + directConnect: true, + // Port comes from lite-server config `/e2e/browser.config.json` `"port": 4204` + baseUrl: 'http://localhost:4204/', + framework: 'jasmine', + useAllAngular2AppRoots: true +}; diff --git a/integration/i18n/e2e/tsconfig.json b/integration/i18n/e2e/tsconfig.json new file mode 100644 index 000000000000..b60faa75fdf2 --- /dev/null +++ b/integration/i18n/e2e/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "../built/e2e", + "types": ["jasmine", "jasminewd2"], + } +} diff --git a/integration/i18n/package.json b/integration/i18n/package.json new file mode 100644 index 000000000000..d48d30f4e0ec --- /dev/null +++ b/integration/i18n/package.json @@ -0,0 +1,39 @@ +{ + "name": "angular-integration", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@angular/common": "file:../../dist/packages-dist/common", + "@angular/compiler": "file:../../dist/packages-dist/compiler", + "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", + "@angular/core": "file:../../dist/packages-dist/core", + "@angular/localize": "file:../../dist/packages-dist/localize", + "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", + "rxjs": "file:../../node_modules/rxjs", + "tslib": "file:../../node_modules/tslib", + "typescript": "file:../../node_modules/typescript", + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" + }, + "devDependencies": { + "@babel/core": "file:../../node_modules/@babel/core", + "@rollup/plugin-babel": "file:../../node_modules/@rollup/plugin-babel", + "@rollup/plugin-node-resolve": "file:../../node_modules/@rollup/plugin-node-resolve", + "@types/jasmine": "file:../../node_modules/@types/jasmine", + "@types/jasminewd2": "file:../../node_modules/@types/jasminewd2", + "concurrently": "3.4.0", + "google-closure-compiler": "file:../../node_modules/google-closure-compiler", + "lite-server": "2.2.2", + "protractor": "file:../../node_modules/protractor", + "rollup": "file:../../node_modules/rollup", + "tsickle": "file:../../node_modules/tsickle" + }, + "scripts": { + "build": "yarn ngc && yarn rollup -c rollup.config.mjs && yarn closure", + "closure": "google-closure-compiler --flagfile closure.conf", + "test": "yarn build && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first && yarn test-locale-folder", + "test-locale-folder": "node test-locale-folder.js", + "serve": "lite-server -c e2e/browser.config.json", + "preprotractor": "tsc -p e2e", + "protractor": "protractor e2e/protractor.config.js" + } +} diff --git a/integration/i18n/rollup.config.mjs b/integration/i18n/rollup.config.mjs new file mode 100644 index 000000000000..2ddcb493475d --- /dev/null +++ b/integration/i18n/rollup.config.mjs @@ -0,0 +1,27 @@ +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import {babel} from '@rollup/plugin-babel'; +import {ConsoleLogger, NodeJSFileSystem, LogLevel} from '@angular/compiler-cli'; +import {createEs2015LinkerPlugin} from '@angular/compiler-cli/linker/babel'; + +/** File system used by the Angular linker plugin. */ +const fileSystem = new NodeJSFileSystem(); +/** Logger used by the Angular linker plugin. */ +const logger = new ConsoleLogger(LogLevel.info); +/** Linker babel plugin. */ +const linkerPlugin = createEs2015LinkerPlugin({ + fileSystem, + logger, + linkerJitMode: false, +}); + +export default { + input: './built/src/main.js', + output: { + file: './built/bundle.js', + format: 'iife' + }, + plugins: [ + nodeResolve(), + babel({plugins: [linkerPlugin]}), + ] +} \ No newline at end of file diff --git a/integration/i18n/src/app.ts b/integration/i18n/src/app.ts new file mode 100644 index 000000000000..31ecac712b0d --- /dev/null +++ b/integration/i18n/src/app.ts @@ -0,0 +1,11 @@ +import {HelloWorldComponent} from './hello-world.component'; + +import {NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +@NgModule({ + declarations: [HelloWorldComponent], + bootstrap: [HelloWorldComponent], + imports: [BrowserModule], +}) +export class AppModule {} diff --git a/integration/i18n/src/hello-world.component.ts b/integration/i18n/src/hello-world.component.ts new file mode 100644 index 000000000000..5aabbddd9309 --- /dev/null +++ b/integration/i18n/src/hello-world.component.ts @@ -0,0 +1,9 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'hello-world-app', + template: `
Hello {{ name }}!
`, +}) +export class HelloWorldComponent { + name: string = 'world'; +} diff --git a/integration/i18n/src/index.html b/integration/i18n/src/index.html new file mode 100644 index 000000000000..5a1c1afc2df3 --- /dev/null +++ b/integration/i18n/src/index.html @@ -0,0 +1,18 @@ + + + + + + Hello World + + + + + Loading... + + + + + + + diff --git a/integration/i18n/src/main.ts b/integration/i18n/src/main.ts new file mode 100644 index 000000000000..e7bf284bc875 --- /dev/null +++ b/integration/i18n/src/main.ts @@ -0,0 +1,6 @@ +import '@angular/localize/init' + +import {platformBrowser} from '@angular/platform-browser'; +import {AppModule} from './app'; + +platformBrowser().bootstrapModule(AppModule); diff --git a/integration/i18n/test-locale-folder.js b/integration/i18n/test-locale-folder.js new file mode 100644 index 000000000000..13eef35f121e --- /dev/null +++ b/integration/i18n/test-locale-folder.js @@ -0,0 +1,14 @@ +const fs = require('fs'); +const path = require('path'); + +const packageJson = require('@angular/common/package.json'); +const localesFolder = packageJson['locales']; +if (!localesFolder) { + throw new Error(`@angular/common/package.json does not contain 'locales' entry.`) +} +const enLocalePath = `@angular/common/${localesFolder}/en`; +try { + require.resolve(enLocalePath); +} catch (err) { + throw new Error(`@angular/common does not contain 'en' locale in ${enLocalePath}.`) +} diff --git a/integration/i18n/tsconfig.json b/integration/i18n/tsconfig.json new file mode 100644 index 000000000000..150751592dcb --- /dev/null +++ b/integration/i18n/tsconfig.json @@ -0,0 +1,26 @@ +{ + "angularCompilerOptions": { + "annotationsAs": "static fields", + "annotateForClosureCompiler": true, + }, + "compilerOptions": { + "module": "es2020", + "moduleResolution": "node", + "target": "es2020", + "noImplicitAny": false, + "sourceMap": false, + "experimentalDecorators": true, + "outDir": "built", + "rootDir": ".", + "declaration": true, + "types": [] + }, + + "exclude": [ + "vendor", + "node_modules", + "built", + "dist", + "e2e" + ] +} diff --git a/integration/ng_elements/closure.conf b/integration/ng_elements/closure.conf new file mode 100644 index 000000000000..3d2fcdb95c0f --- /dev/null +++ b/integration/ng_elements/closure.conf @@ -0,0 +1,20 @@ +--compilation_level=SIMPLE +--language_in=ECMASCRIPT_2020 +--language_out=ECMASCRIPT_2020 +--js_output_file=dist/bundle.js +--output_manifest=dist/manifest.MF +--variable_renaming_report=dist/variable_renaming_report +--property_renaming_report=dist/property_renaming_report +--create_source_map=%outname%.map + +--warning_level=QUIET +--dependency_mode=PRUNE +--rewrite_polyfills=false + +--module_resolution=node +--package_json_entry_names es2020,module + +node_modules/zone.js/zone_externs.js + +--js built/bundle.js +--entry_point=built/bundle.js diff --git a/integration/ng_elements/package.json b/integration/ng_elements/package.json index 09d1e834f86d..f39c27427fd3 100644 --- a/integration/ng_elements/package.json +++ b/integration/ng_elements/package.json @@ -21,13 +21,15 @@ "@types/jasmine": "file:../../node_modules/@types/jasmine", "@types/jasminewd2": "file:../../node_modules/@types/jasminewd2", "concurrently": "3.4.0", + "google-closure-compiler": "file:../../node_modules/google-closure-compiler", "lite-server": "2.2.2", "protractor": "file:../../node_modules/protractor", "rollup": "file:../../node_modules/rollup", "tsickle": "file:../../node_modules/tsickle" }, "scripts": { - "build": "yarn ngc && yarn rollup -c rollup.config.mjs", + "closure": "google-closure-compiler --flagfile closure.conf", + "build": "yarn ngc && yarn rollup -c rollup.config.mjs && yarn closure", "test": "yarn build && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first", "serve": "lite-server -c e2e/browser.config.json", "preprotractor": "tsc -p e2e", diff --git a/integration/npm_package_archives.bzl b/integration/npm_package_archives.bzl index 90723bd2a08d..a0783370257b 100644 --- a/integration/npm_package_archives.bzl +++ b/integration/npm_package_archives.bzl @@ -6,6 +6,7 @@ NPM_PACKAGE_ARCHIVES = [ "@rollup/plugin-node-resolve", "@rollup/plugin-commonjs", "check-side-effects", + "google-closure-compiler", "jasmine", "typescript", "rxjs", diff --git a/package.json b/package.json index 6ffaa19f49c6..15f7293010ca 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "diff": "^5.0.0", "document-register-element": "^1.7.2", "domino": "https://github.com/angular/domino.git#4280d0380df839d97b81e7680877ad5b55500e77", + "google-closure-compiler": "20230206.0.0", "graceful-fs": "4.2.10", "hammerjs": "~2.0.8", "http-server": "^14.0.0", From 96bf952e73ed0c49bbb633f8153042c99710174b Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 22 Mar 2023 14:27:25 -0700 Subject: [PATCH 5/5] Revert "refactor: update code to be ES2022 compliant (#49332)" This reverts commit 349ff01c4b4a5129e6fc933d40f57516aa61d6d0. --- .../annotations/component/src/handler.ts | 15 +-- .../src/ngtsc/core/src/compiler.ts | 8 +- .../compiler-cli/src/ngtsc/core/src/host.ts | 107 +++++++----------- .../src/ngtsc/imports/src/emitter.ts | 6 +- .../src/ngtsc/perf/src/recorder.ts | 3 +- .../src/ts_create_program_driver.ts | 98 ++++++---------- .../src/ngtsc/resource/src/loader.ts | 12 +- packages/compiler/src/i18n/i18n_ast.ts | 7 +- .../compiler/src/render3/view/i18n/meta.ts | 8 +- packages/core/schematics/tsconfig.json | 4 +- .../core/schematics/utils/change_tracker.ts | 20 ++-- .../src/component-factory-strategy.ts | 16 +-- packages/forms/src/directives/ng_model.ts | 3 +- .../forms/src/directives/ng_model_group.ts | 3 +- .../reactive_directives/form_control_name.ts | 3 +- .../reactive_directives/form_group_name.ts | 6 +- packages/router/src/router_state.ts | 4 +- .../service-worker/worker/src/app-version.ts | 3 +- .../service-worker/worker/src/db-cache.ts | 6 +- packages/service-worker/worker/src/driver.ts | 9 +- 20 files changed, 130 insertions(+), 211 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts index 4796d26e109e..f7aecf4f1da1 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts @@ -60,13 +60,7 @@ export class ComponentDecoratorHandler implements private injectableRegistry: InjectableClassRegistry, private semanticDepGraphUpdater: SemanticDepGraphUpdater|null, private annotateForClosureCompiler: boolean, private perf: PerfRecorder, - private hostDirectivesResolver: HostDirectivesResolver) { - this.extractTemplateOptions = { - enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, - i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs, - usePoisonedData: this.usePoisonedData, - }; - } + private hostDirectivesResolver: HostDirectivesResolver) {} private literalCache = new Map(); private elementSchemaRegistry = new DomElementSchemaRegistry(); @@ -79,9 +73,10 @@ export class ComponentDecoratorHandler implements private preanalyzeTemplateCache = new Map(); private preanalyzeStylesCache = new Map(); - private extractTemplateOptions: { - enableI18nLegacyMessageIdFormat: boolean; i18nNormalizeLineEndingsInICUs: boolean; - usePoisonedData: boolean; + private extractTemplateOptions = { + enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, + i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs, + usePoisonedData: this.usePoisonedData, }; readonly precedence = HandlerPrecedence.PRIMARY; diff --git a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts index b0c4c34dff0a..59294edcee5f 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/compiler.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/compiler.ts @@ -1265,12 +1265,8 @@ class ReferenceGraphAdapter implements ReferencesRegistry { } class NotifyingProgramDriverWrapper implements ProgramDriver { - getSourceFileVersion: ProgramDriver['getSourceFileVersion']; - constructor( - private delegate: ProgramDriver, private notifyNewProgram: (program: ts.Program) => void) { - this.getSourceFileVersion = this.delegate.getSourceFileVersion?.bind(this); - } + private delegate: ProgramDriver, private notifyNewProgram: (program: ts.Program) => void) {} get supportsInlineOperations() { return this.delegate.supportsInlineOperations; @@ -1284,6 +1280,8 @@ class NotifyingProgramDriverWrapper implements ProgramDriver { this.delegate.updateFiles(contents, updateMode); this.notifyNewProgram(this.delegate.getProgram()); } + + getSourceFileVersion = this.delegate.getSourceFileVersion?.bind(this); } function versionMapFromProgram( diff --git a/packages/compiler-cli/src/ngtsc/core/src/host.ts b/packages/compiler-cli/src/ngtsc/core/src/host.ts index a9df5743fb6e..2856686ebae7 100644 --- a/packages/compiler-cli/src/ngtsc/core/src/host.ts +++ b/packages/compiler-cli/src/ngtsc/core/src/host.ts @@ -32,81 +32,50 @@ import {ExtendedTsCompilerHost, NgCompilerAdapter, NgCompilerOptions, UnifiedMod */ export class DelegatingCompilerHost implements Omit, 'getSourceFile'|'fileExists'> { - createHash; - directoryExists; - fileNameToModuleName; - getCancellationToken; - getCanonicalFileName; - getCurrentDirectory; - getDefaultLibFileName; - getDefaultLibLocation; - getDirectories; - getEnvironmentVariable; - getModifiedResourceFiles; - getNewLine; - getParsedCommandLine; - getSourceFileByPath; - readDirectory; - readFile; - readResource; - transformResource; - realpath; - resolveModuleNames; - resolveTypeReferenceDirectives; - resourceNameToFileName; - trace; - useCaseSensitiveFileNames; - writeFile; - getModuleResolutionCache; - hasInvalidatedResolutions; - resolveModuleNameLiterals; - resolveTypeReferenceDirectiveReferences; - - constructor(protected delegate: ExtendedTsCompilerHost) { - // Excluded are 'getSourceFile' and 'fileExists', which are actually implemented by - // NgCompilerHost - // below. - this.createHash = this.delegateMethod('createHash'); - this.directoryExists = this.delegateMethod('directoryExists'); - this.fileNameToModuleName = this.delegateMethod('fileNameToModuleName'); - this.getCancellationToken = this.delegateMethod('getCancellationToken'); - this.getCanonicalFileName = this.delegateMethod('getCanonicalFileName'); - this.getCurrentDirectory = this.delegateMethod('getCurrentDirectory'); - this.getDefaultLibFileName = this.delegateMethod('getDefaultLibFileName'); - this.getDefaultLibLocation = this.delegateMethod('getDefaultLibLocation'); - this.getDirectories = this.delegateMethod('getDirectories'); - this.getEnvironmentVariable = this.delegateMethod('getEnvironmentVariable'); - this.getModifiedResourceFiles = this.delegateMethod('getModifiedResourceFiles'); - this.getNewLine = this.delegateMethod('getNewLine'); - this.getParsedCommandLine = this.delegateMethod('getParsedCommandLine'); - this.getSourceFileByPath = this.delegateMethod('getSourceFileByPath'); - this.readDirectory = this.delegateMethod('readDirectory'); - this.readFile = this.delegateMethod('readFile'); - this.readResource = this.delegateMethod('readResource'); - this.transformResource = this.delegateMethod('transformResource'); - this.realpath = this.delegateMethod('realpath'); - this.resolveModuleNames = this.delegateMethod('resolveModuleNames'); - this.resolveTypeReferenceDirectives = this.delegateMethod('resolveTypeReferenceDirectives'); - this.resourceNameToFileName = this.delegateMethod('resourceNameToFileName'); - this.trace = this.delegateMethod('trace'); - this.useCaseSensitiveFileNames = this.delegateMethod('useCaseSensitiveFileNames'); - this.writeFile = this.delegateMethod('writeFile'); - this.getModuleResolutionCache = this.delegateMethod('getModuleResolutionCache'); - this.hasInvalidatedResolutions = this.delegateMethod('hasInvalidatedResolutions'); - // The following methods are required in TS 5.0+, but they don't exist in earlier versions. - // TODO(crisbeto): remove the `ts-ignore` when dropping support for TypeScript 4.9. - // @ts-ignore - this.resolveModuleNameLiterals = this.delegateMethod('resolveModuleNameLiterals'); - this.resolveTypeReferenceDirectiveReferences = - // @ts-ignore - this.delegateMethod('resolveTypeReferenceDirectiveReferences'); - } + constructor(protected delegate: ExtendedTsCompilerHost) {} private delegateMethod(name: M): ExtendedTsCompilerHost[M] { return this.delegate[name] !== undefined ? (this.delegate[name] as any).bind(this.delegate) : undefined; } + + // Excluded are 'getSourceFile' and 'fileExists', which are actually implemented by NgCompilerHost + // below. + createHash = this.delegateMethod('createHash'); + directoryExists = this.delegateMethod('directoryExists'); + fileNameToModuleName = this.delegateMethod('fileNameToModuleName'); + getCancellationToken = this.delegateMethod('getCancellationToken'); + getCanonicalFileName = this.delegateMethod('getCanonicalFileName'); + getCurrentDirectory = this.delegateMethod('getCurrentDirectory'); + getDefaultLibFileName = this.delegateMethod('getDefaultLibFileName'); + getDefaultLibLocation = this.delegateMethod('getDefaultLibLocation'); + getDirectories = this.delegateMethod('getDirectories'); + getEnvironmentVariable = this.delegateMethod('getEnvironmentVariable'); + getModifiedResourceFiles = this.delegateMethod('getModifiedResourceFiles'); + getNewLine = this.delegateMethod('getNewLine'); + getParsedCommandLine = this.delegateMethod('getParsedCommandLine'); + getSourceFileByPath = this.delegateMethod('getSourceFileByPath'); + readDirectory = this.delegateMethod('readDirectory'); + readFile = this.delegateMethod('readFile'); + readResource = this.delegateMethod('readResource'); + transformResource = this.delegateMethod('transformResource'); + realpath = this.delegateMethod('realpath'); + resolveModuleNames = this.delegateMethod('resolveModuleNames'); + resolveTypeReferenceDirectives = this.delegateMethod('resolveTypeReferenceDirectives'); + resourceNameToFileName = this.delegateMethod('resourceNameToFileName'); + trace = this.delegateMethod('trace'); + useCaseSensitiveFileNames = this.delegateMethod('useCaseSensitiveFileNames'); + writeFile = this.delegateMethod('writeFile'); + getModuleResolutionCache = this.delegateMethod('getModuleResolutionCache'); + hasInvalidatedResolutions = this.delegateMethod('hasInvalidatedResolutions'); + // The following methods are required in TS 5.0+, but they don't exist in earlier versions. + // TODO(crisbeto): remove the `ts-ignore` when dropping support for TypeScript 4.9. + // @ts-ignore + resolveModuleNameLiterals = this.delegateMethod('resolveModuleNameLiterals'); + resolveTypeReferenceDirectiveReferences = + // @ts-ignore + this.delegateMethod('resolveTypeReferenceDirectiveReferences'); } /** diff --git a/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts b/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts index 85e080b0c322..e65dc762e294 100644 --- a/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts +++ b/packages/compiler-cli/src/ngtsc/imports/src/emitter.ts @@ -367,11 +367,9 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy { * Instead, `LogicalProjectPath`s are used. */ export class LogicalProjectStrategy implements ReferenceEmitStrategy { - private relativePathStrategy: RelativePathStrategy; + private relativePathStrategy = new RelativePathStrategy(this.reflector); - constructor(private reflector: ReflectionHost, private logicalFs: LogicalFileSystem) { - this.relativePathStrategy = new RelativePathStrategy(this.reflector); - } + constructor(private reflector: ReflectionHost, private logicalFs: LogicalFileSystem) {} emit(ref: Reference, context: ts.SourceFile, importFlags: ImportFlags): ReferenceEmitResult|null { const destSf = getSourceFile(ref.node); diff --git a/packages/compiler-cli/src/ngtsc/perf/src/recorder.ts b/packages/compiler-cli/src/ngtsc/perf/src/recorder.ts index a8dd832a2381..223a46ef5c70 100644 --- a/packages/compiler-cli/src/ngtsc/perf/src/recorder.ts +++ b/packages/compiler-cli/src/ngtsc/perf/src/recorder.ts @@ -28,7 +28,7 @@ export class ActivePerfRecorder implements PerfRecorder { private bytes: number[]; private currentPhase = PerfPhase.Unaccounted; - private currentPhaseEntered: HrTime; + private currentPhaseEntered = this.zeroTime; /** * Creates an `ActivePerfRecorder` with its zero point set to the current time. @@ -38,7 +38,6 @@ export class ActivePerfRecorder implements PerfRecorder { } private constructor(private zeroTime: HrTime) { - this.currentPhaseEntered = this.zeroTime; this.counters = Array(PerfEvent.LAST).fill(0); this.phaseTime = Array(PerfPhase.LAST).fill(0); this.bytes = Array(PerfCheckpoint.LAST).fill(0); diff --git a/packages/compiler-cli/src/ngtsc/program_driver/src/ts_create_program_driver.ts b/packages/compiler-cli/src/ngtsc/program_driver/src/ts_create_program_driver.ts index a054199b2591..90010fc96476 100644 --- a/packages/compiler-cli/src/ngtsc/program_driver/src/ts_create_program_driver.ts +++ b/packages/compiler-cli/src/ngtsc/program_driver/src/ts_create_program_driver.ts @@ -23,68 +23,43 @@ import {FileUpdate, MaybeSourceFileWithOriginalFile, NgOriginalFile, ProgramDriv */ export class DelegatingCompilerHost implements Omit, 'getSourceFile'|'fileExists'|'writeFile'> { - createHash; - directoryExists; - getCancellationToken; - getCanonicalFileName; - getCurrentDirectory; - getDefaultLibFileName; - getDefaultLibLocation; - getDirectories; - getEnvironmentVariable; - getNewLine; - getParsedCommandLine; - getSourceFileByPath; - readDirectory; - readFile; - realpath; - resolveModuleNames; - resolveTypeReferenceDirectives; - trace; - useCaseSensitiveFileNames; - getModuleResolutionCache; - hasInvalidatedResolutions; - resolveModuleNameLiterals; - resolveTypeReferenceDirectiveReferences; - - constructor(protected delegate: ts.CompilerHost) { - // Excluded are 'getSourceFile', 'fileExists' and 'writeFile', which are actually implemented by - // `TypeCheckProgramHost` below. - - this.createHash = this.delegateMethod('createHash'); - this.directoryExists = this.delegateMethod('directoryExists'); - this.getCancellationToken = this.delegateMethod('getCancellationToken'); - this.getCanonicalFileName = this.delegateMethod('getCanonicalFileName'); - this.getCurrentDirectory = this.delegateMethod('getCurrentDirectory'); - this.getDefaultLibFileName = this.delegateMethod('getDefaultLibFileName'); - this.getDefaultLibLocation = this.delegateMethod('getDefaultLibLocation'); - this.getDirectories = this.delegateMethod('getDirectories'); - this.getEnvironmentVariable = this.delegateMethod('getEnvironmentVariable'); - this.getNewLine = this.delegateMethod('getNewLine'); - this.getParsedCommandLine = this.delegateMethod('getParsedCommandLine'); - this.getSourceFileByPath = this.delegateMethod('getSourceFileByPath'); - this.readDirectory = this.delegateMethod('readDirectory'); - this.readFile = this.delegateMethod('readFile'); - this.realpath = this.delegateMethod('realpath'); - this.resolveModuleNames = this.delegateMethod('resolveModuleNames'); - this.resolveTypeReferenceDirectives = this.delegateMethod('resolveTypeReferenceDirectives'); - this.trace = this.delegateMethod('trace'); - this.useCaseSensitiveFileNames = this.delegateMethod('useCaseSensitiveFileNames'); - this.getModuleResolutionCache = this.delegateMethod('getModuleResolutionCache'); - this.hasInvalidatedResolutions = this.delegateMethod('hasInvalidatedResolutions'); - // The following methods are required in TS 5.0+, but they don't exist in earlier versions. - // TODO(crisbeto): remove the `ts-ignore` when dropping support for TypeScript 4.9. - // @ts-ignore - this.resolveModuleNameLiterals = this.delegateMethod('resolveModuleNameLiterals'); - this.resolveTypeReferenceDirectiveReferences = - // @ts-ignore - this.delegateMethod('resolveTypeReferenceDirectiveReferences'); - } + constructor(protected delegate: ts.CompilerHost) {} private delegateMethod(name: M): ts.CompilerHost[M] { return this.delegate[name] !== undefined ? (this.delegate[name] as any).bind(this.delegate) : undefined; } + + // Excluded are 'getSourceFile', 'fileExists' and 'writeFile', which are actually implemented by + // `TypeCheckProgramHost` below. + createHash = this.delegateMethod('createHash'); + directoryExists = this.delegateMethod('directoryExists'); + getCancellationToken = this.delegateMethod('getCancellationToken'); + getCanonicalFileName = this.delegateMethod('getCanonicalFileName'); + getCurrentDirectory = this.delegateMethod('getCurrentDirectory'); + getDefaultLibFileName = this.delegateMethod('getDefaultLibFileName'); + getDefaultLibLocation = this.delegateMethod('getDefaultLibLocation'); + getDirectories = this.delegateMethod('getDirectories'); + getEnvironmentVariable = this.delegateMethod('getEnvironmentVariable'); + getNewLine = this.delegateMethod('getNewLine'); + getParsedCommandLine = this.delegateMethod('getParsedCommandLine'); + getSourceFileByPath = this.delegateMethod('getSourceFileByPath'); + readDirectory = this.delegateMethod('readDirectory'); + readFile = this.delegateMethod('readFile'); + realpath = this.delegateMethod('realpath'); + resolveModuleNames = this.delegateMethod('resolveModuleNames'); + resolveTypeReferenceDirectives = this.delegateMethod('resolveTypeReferenceDirectives'); + trace = this.delegateMethod('trace'); + useCaseSensitiveFileNames = this.delegateMethod('useCaseSensitiveFileNames'); + getModuleResolutionCache = this.delegateMethod('getModuleResolutionCache'); + hasInvalidatedResolutions = this.delegateMethod('hasInvalidatedResolutions'); + // The following methods are required in TS 5.0+, but they don't exist in earlier versions. + // TODO(crisbeto): remove the `ts-ignore` when dropping support for TypeScript 4.9. + // @ts-ignore + resolveModuleNameLiterals = this.delegateMethod('resolveModuleNameLiterals'); + resolveTypeReferenceDirectiveReferences = + // @ts-ignore + this.delegateMethod('resolveTypeReferenceDirectiveReferences'); } /** @@ -106,13 +81,12 @@ class UpdatedProgramHost extends DelegatingCompilerHost { * order for those shims to be loaded, and then cleaned up afterwards. Thus the * `UpdatedProgramHost` has its own `ShimReferenceTagger` to perform this function. */ - private shimTagger: ShimReferenceTagger; + private shimTagger = new ShimReferenceTagger(this.shimExtensionPrefixes); constructor( sfMap: Map, private originalProgram: ts.Program, delegate: ts.CompilerHost, private shimExtensionPrefixes: string[]) { super(delegate); - this.shimTagger = new ShimReferenceTagger(this.shimExtensionPrefixes); this.sfMap = sfMap; } @@ -176,13 +150,11 @@ export class TsCreateProgramDriver implements ProgramDriver { */ private sfMap = new Map(); - private program: ts.Program; + private program: ts.Program = this.originalProgram; constructor( private originalProgram: ts.Program, private originalHost: ts.CompilerHost, - private options: ts.CompilerOptions, private shimExtensionPrefixes: string[]) { - this.program = this.originalProgram; - } + private options: ts.CompilerOptions, private shimExtensionPrefixes: string[]) {} readonly supportsInlineOperations = true; diff --git a/packages/compiler-cli/src/ngtsc/resource/src/loader.ts b/packages/compiler-cli/src/ngtsc/resource/src/loader.ts index 3aeeee240ca1..c3013c325b8b 100644 --- a/packages/compiler-cli/src/ngtsc/resource/src/loader.ts +++ b/packages/compiler-cli/src/ngtsc/resource/src/loader.ts @@ -24,16 +24,12 @@ const RESOURCE_MARKER_TS = RESOURCE_MARKER + '.ts'; export class AdapterResourceLoader implements ResourceLoader { private cache = new Map(); private fetching = new Map>(); - private lookupResolutionHost: RequiredDelegations; + private lookupResolutionHost = createLookupResolutionHost(this.adapter); - canPreload: boolean; - canPreprocess: boolean; + canPreload = !!this.adapter.readResource; + canPreprocess = !!this.adapter.transformResource; - constructor(private adapter: NgCompilerAdapter, private options: ts.CompilerOptions) { - this.lookupResolutionHost = createLookupResolutionHost(this.adapter); - this.canPreload = !!this.adapter.readResource; - this.canPreprocess = !!this.adapter.transformResource; - } + constructor(private adapter: NgCompilerAdapter, private options: ts.CompilerOptions) {} /** * Resolve the url of a resource relative to the file that contains the reference to it. diff --git a/packages/compiler/src/i18n/i18n_ast.ts b/packages/compiler/src/i18n/i18n_ast.ts index a09229f1c1bd..4443c3d0a4f9 100644 --- a/packages/compiler/src/i18n/i18n_ast.ts +++ b/packages/compiler/src/i18n/i18n_ast.ts @@ -22,11 +22,11 @@ export interface MessagePlaceholder { export class Message { sources: MessageSpan[]; - id: string; + id: string = this.customId; /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */ legacyIds: string[] = []; - messageString: string; + messageString = serializeMessage(this.nodes); /** * @param nodes message AST @@ -40,9 +40,6 @@ export class Message { public nodes: Node[], public placeholders: {[phName: string]: MessagePlaceholder}, public placeholderToMessage: {[phName: string]: Message}, public meaning: string, public description: string, public customId: string) { - this.id = this.customId; - this.messageString = serializeMessage(this.nodes); - if (nodes.length) { this.sources = [{ filePath: nodes[0].sourceSpan.start.file.url, diff --git a/packages/compiler/src/render3/view/i18n/meta.ts b/packages/compiler/src/render3/view/i18n/meta.ts index 250c7a96a097..3958f29079f5 100644 --- a/packages/compiler/src/render3/view/i18n/meta.ts +++ b/packages/compiler/src/render3/view/i18n/meta.ts @@ -8,7 +8,7 @@ import {computeDecimalDigest, computeDigest, decimalDigest} from '../../../i18n/digest'; import * as i18n from '../../../i18n/i18n_ast'; -import {createI18nMessageFactory, I18nMessageFactory, VisitNodeFn} from '../../../i18n/i18n_parser'; +import {createI18nMessageFactory, VisitNodeFn} from '../../../i18n/i18n_parser'; import {I18nError} from '../../../i18n/parse_util'; import * as html from '../../../ml_parser/ast'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../ml_parser/interpolation_config'; @@ -51,6 +51,9 @@ export class I18nMetaVisitor implements html.Visitor { public hasI18nMeta: boolean = false; private _errors: I18nError[] = []; + // i18n message generation factory + private _createI18nMessage = createI18nMessageFactory(this.interpolationConfig); + constructor( private interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG, private keepI18nAttrs = false, private enableI18nLegacyMessageIdFormat = false) {} @@ -59,8 +62,7 @@ export class I18nMetaVisitor implements html.Visitor { nodes: html.Node[], meta: string|i18n.I18nMeta = '', visitNodeFn?: VisitNodeFn): i18n.Message { const {meaning, description, customId} = this._parseMetadata(meta); - const createI18nMessage = createI18nMessageFactory(this.interpolationConfig); - const message = createI18nMessage(nodes, meaning, description, customId, visitNodeFn); + const message = this._createI18nMessage(nodes, meaning, description, customId, visitNodeFn); this._setMessageId(message, meta); this._setLegacyIds(message, meta); return message; diff --git a/packages/core/schematics/tsconfig.json b/packages/core/schematics/tsconfig.json index 450689783aaa..dbeb0be6f638 100644 --- a/packages/core/schematics/tsconfig.json +++ b/packages/core/schematics/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "strict": true, "moduleResolution": "node", - "target": "es2022", + "target": "es2019", "lib": [ "es2019" ], @@ -32,4 +32,4 @@ "bazelOptions": { "suppressTsconfigOverrideWarnings": true } -} +} \ No newline at end of file diff --git a/packages/core/schematics/utils/change_tracker.ts b/packages/core/schematics/utils/change_tracker.ts index 30c9c04ef4b9..a3364c310a1d 100644 --- a/packages/core/schematics/utils/change_tracker.ts +++ b/packages/core/schematics/utils/change_tracker.ts @@ -32,17 +32,15 @@ export interface PendingChange { /** Tracks changes that have to be made for specific files. */ export class ChangeTracker { private readonly _changes = new Map(); - private readonly _importManager: ImportManager; - - constructor(private _printer: ts.Printer, private _importRemapper?: ImportRemapper) { - this._importManager = new ImportManager( - currentFile => ({ - addNewImport: (start, text) => this.insertText(currentFile, start, text), - updateExistingImport: (namedBindings, text) => this.replaceText( - currentFile, namedBindings.getStart(), namedBindings.getWidth(), text), - }), - this._printer); - } + private readonly _importManager = new ImportManager( + currentFile => ({ + addNewImport: (start, text) => this.insertText(currentFile, start, text), + updateExistingImport: (namedBindings, text) => + this.replaceText(currentFile, namedBindings.getStart(), namedBindings.getWidth(), text), + }), + this._printer); + + constructor(private _printer: ts.Printer, private _importRemapper?: ImportRemapper) {} /** * Tracks the insertion of some text. diff --git a/packages/elements/src/component-factory-strategy.ts b/packages/elements/src/component-factory-strategy.ts index da7d734fd04c..0d013c26b5c0 100644 --- a/packages/elements/src/component-factory-strategy.ts +++ b/packages/elements/src/component-factory-strategy.ts @@ -81,21 +81,17 @@ export class ComponentNgElementStrategy implements NgElementStrategy { * fired. * (This helps detect the first change of an input, even if it is explicitly set to `undefined`.) */ - private readonly unchangedInputs: Set; + private readonly unchangedInputs = + new Set(this.componentFactory.inputs.map(({propName}) => propName)); /** Service for setting zone context. */ - private readonly ngZone: NgZone; + private readonly ngZone = this.injector.get(NgZone); /** The zone the element was created in or `null` if Zone.js is not loaded. */ - private readonly elementZone: Zone|null; + private readonly elementZone = + (typeof Zone === 'undefined') ? null : this.ngZone.run(() => Zone.current); - - constructor(private componentFactory: ComponentFactory, private injector: Injector) { - this.unchangedInputs = - new Set(this.componentFactory.inputs.map(({propName}) => propName)); - this.ngZone = this.injector.get(NgZone); - this.elementZone = (typeof Zone === 'undefined') ? null : this.ngZone.run(() => Zone.current); - } + constructor(private componentFactory: ComponentFactory, private injector: Injector) {} /** * Initializes a new component if one has not yet been created and cancels any scheduled diff --git a/packages/forms/src/directives/ng_model.ts b/packages/forms/src/directives/ng_model.ts index c9bdc5c26e14..710d4786f65c 100644 --- a/packages/forms/src/directives/ng_model.ts +++ b/packages/forms/src/directives/ng_model.ts @@ -162,7 +162,8 @@ export class NgModel extends NgControl implements OnChanges, OnDestroy { * Tracks the name bound to the directive. If a parent form exists, it * uses this name as a key to retrieve this control's value. */ - @Input() override name: string = ''; + // TODO(issue/24571): remove '!'. + @Input() override name!: string; /** * @description diff --git a/packages/forms/src/directives/ng_model_group.ts b/packages/forms/src/directives/ng_model_group.ts index f50400595156..bd2cdccca181 100644 --- a/packages/forms/src/directives/ng_model_group.ts +++ b/packages/forms/src/directives/ng_model_group.ts @@ -54,7 +54,8 @@ export class NgModelGroup extends AbstractFormGroupDirective implements OnInit, * Tracks the name of the `NgModelGroup` bound to the directive. The name corresponds * to a key in the parent `NgForm`. */ - @Input('ngModelGroup') override name: string = ''; + // TODO(issue/24571): remove '!'. + @Input('ngModelGroup') override name!: string; constructor( @Host() @SkipSelf() parent: ControlContainer, diff --git a/packages/forms/src/directives/reactive_directives/form_control_name.ts b/packages/forms/src/directives/reactive_directives/form_control_name.ts index 02b3754d10df..8d4dc9650540 100644 --- a/packages/forms/src/directives/reactive_directives/form_control_name.ts +++ b/packages/forms/src/directives/reactive_directives/form_control_name.ts @@ -86,7 +86,8 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy { * while the numerical form allows for form controls to be bound * to indices when iterating over controls in a `FormArray`. */ - @Input('formControlName') override name: string|number|null = null; + // TODO(issue/24571): remove '!'. + @Input('formControlName') override name!: string|number|null; /** * @description diff --git a/packages/forms/src/directives/reactive_directives/form_group_name.ts b/packages/forms/src/directives/reactive_directives/form_group_name.ts index 3d52c9353800..46caaebd0e5f 100644 --- a/packages/forms/src/directives/reactive_directives/form_group_name.ts +++ b/packages/forms/src/directives/reactive_directives/form_group_name.ts @@ -81,7 +81,8 @@ export class FormGroupName extends AbstractFormGroupDirective implements OnInit, * while the numerical form allows for form groups to be bound * to indices when iterating over groups in a `FormArray`. */ - @Input('formGroupName') override name: string|number|null = null; + // TODO(issue/24571): remove '!'. + @Input('formGroupName') override name!: string|number|null; constructor( @Optional() @Host() @SkipSelf() parent: ControlContainer, @@ -145,7 +146,8 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy * while the numerical form allows for form arrays to be bound * to indices when iterating over arrays in a `FormArray`. */ - @Input('formArrayName') override name: string|number|null = null; + // TODO(issue/24571): remove '!'. + @Input('formArrayName') override name!: string|number|null; constructor( @Optional() @Host() @SkipSelf() parent: ControlContainer, diff --git a/packages/router/src/router_state.ts b/packages/router/src/router_state.ts index 2d884a2b5a55..4667a8dfd174 100644 --- a/packages/router/src/router_state.ts +++ b/packages/router/src/router_state.ts @@ -120,7 +120,8 @@ export class ActivatedRoute { _queryParamMap?: Observable; /** An Observable of the resolved route title */ - readonly title: Observable; + readonly title: Observable = + this.data?.pipe(map((d: Data) => d[RouteTitleKey])) ?? of(undefined); /** @internal */ constructor( @@ -139,7 +140,6 @@ export class ActivatedRoute { /** The component of the route, a constant. */ public component: Type|null, futureSnapshot: ActivatedRouteSnapshot) { this._futureSnapshot = futureSnapshot; - this.title = this.data?.pipe(map((d: Data) => d[RouteTitleKey])) ?? of(undefined); } /** The configuration used to match this route. */ diff --git a/packages/service-worker/worker/src/app-version.ts b/packages/service-worker/worker/src/app-version.ts index 99ce1d8d78fa..1a6349d44bd2 100644 --- a/packages/service-worker/worker/src/app-version.ts +++ b/packages/service-worker/worker/src/app-version.ts @@ -55,7 +55,7 @@ export class AppVersion implements UpdateSource { * The normalized URL to the file that serves as the index page to satisfy navigation requests. * Usually this is `/index.html`. */ - private indexUrl: NormalizedUrl; + private indexUrl = this.adapter.normalizeUrl(this.manifest.index); /** * Tracks whether the manifest has encountered any inconsistencies. @@ -70,7 +70,6 @@ export class AppVersion implements UpdateSource { private scope: ServiceWorkerGlobalScope, private adapter: Adapter, private database: Database, idle: IdleScheduler, private debugHandler: DebugHandler, readonly manifest: Manifest, readonly manifestHash: string) { - this.indexUrl = this.adapter.normalizeUrl(this.manifest.index); // The hashTable within the manifest is an Object - convert it to a Map for easier lookups. Object.keys(manifest.hashTable).forEach(url => { this.hashTable.set(adapter.normalizeUrl(url), manifest.hashTable[url]); diff --git a/packages/service-worker/worker/src/db-cache.ts b/packages/service-worker/worker/src/db-cache.ts index 59c0c7fc2aed..120b4117185a 100644 --- a/packages/service-worker/worker/src/db-cache.ts +++ b/packages/service-worker/worker/src/db-cache.ts @@ -52,13 +52,11 @@ export class CacheDatabase implements Database { * A `Table` backed by a `Cache`. */ export class CacheTable implements Table { - cacheName: string; + cacheName = this.cache.name; constructor( readonly name: string, private cache: NamedCache, private adapter: Adapter, - private cacheQueryOptions?: CacheQueryOptions) { - this.cacheName = this.cache.name; - } + private cacheQueryOptions?: CacheQueryOptions) {} private request(key: string): Request { return this.adapter.newRequest('/' + key); diff --git a/packages/service-worker/worker/src/driver.ts b/packages/service-worker/worker/src/driver.ts index 53a87abd62b2..1862b0fe129b 100644 --- a/packages/service-worker/worker/src/driver.ts +++ b/packages/service-worker/worker/src/driver.ts @@ -9,7 +9,7 @@ import {Adapter} from './adapter'; import {CacheState, Debuggable, DebugIdleState, DebugState, DebugVersion, NormalizedUrl, UpdateCacheStatus, UpdateSource} from './api'; import {AppVersion} from './app-version'; -import {Database, Table} from './database'; +import {Database} from './database'; import {CacheTable} from './db-cache'; import {DebugHandler} from './debug'; import {errorToString} from './error'; @@ -101,7 +101,7 @@ export class Driver implements Debuggable, UpdateSource { */ private loggedInvalidOnlyIfCachedRequest: boolean = false; - private ngswStatePath: string; + private ngswStatePath = this.adapter.parseUrl('ngsw/state', this.scope.registration.scope).path; /** * A scheduler which manages a queue of tasks that need to be executed when the SW is @@ -112,13 +112,10 @@ export class Driver implements Debuggable, UpdateSource { debugger: DebugHandler; // A promise resolving to the control DB table. - private controlTable: Promise; + private controlTable = this.db.open('control'); constructor( private scope: ServiceWorkerGlobalScope, private adapter: Adapter, private db: Database) { - this.controlTable = this.db.open('control'); - this.ngswStatePath = this.adapter.parseUrl('ngsw/state', this.scope.registration.scope).path; - // Set up all the event handlers that the SW needs. // The install event is triggered when the service worker is first installed.