Compare commits
34 Commits
8.2.7
...
9.0.0-next
Author | SHA1 | Date | |
---|---|---|---|
76503e65c8 | |||
eac993dfce | |||
975917bafd | |||
185b3dd08e | |||
78659ec0b0 | |||
a9ec3db91a | |||
561ec6a5be | |||
c0317d40c9 | |||
a4bc0db474 | |||
430124a051 | |||
e08391b333 | |||
a77d0e22bf | |||
4f42eb4e77 | |||
f216724c2c | |||
5c9a8961da | |||
3479fddf68 | |||
5bebac42f9 | |||
cbcbe23fd1 | |||
fc6f48185c | |||
80f290e301 | |||
5e5be43acd | |||
0386c964b5 | |||
f5c605b608 | |||
14dba72aee | |||
5f0d5e9ccf | |||
5296c04f61 | |||
40a0666651 | |||
4da805243a | |||
14ae50b4c3 | |||
397d0ba9a3 | |||
859ebdd836 | |||
30673090ec | |||
6033446d2d | |||
174770e6f3 |
84
CHANGELOG.md
84
CHANGELOG.md
@ -1,13 +1,59 @@
|
||||
<a name="8.2.0-next.2"></a>
|
||||
# [8.2.0-next.2](https://github.com/angular/angular/compare/8.2.0-next.1...8.2.0-next.2) (2019-07-17)
|
||||
<a name="9.0.0-next.0"></a>
|
||||
# [9.0.0-next.0](https://github.com/angular/angular/compare/8.2.0-next.2...9.0.0-next.0) (2019-07-31)
|
||||
|
||||
* Ivy related improvements and fixes
|
||||
|
||||
|
||||
<a name="8.2.0"></a>
|
||||
# [8.2.0](https://github.com/angular/angular/compare/8.2.0-rc.0...8.2.0) (2019-07-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** TypeScript 3.5 support ([#31615](https://github.com/angular/angular/issues/31615)) ([6ece7db]
|
||||
* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597))
|
||||
* **bazel:** compile targets used for indexing by Kythe with Ivy ([#31786](https://github.com/angular/angular/issues/31786)) ([82055b2](https://github.com/angular/angular/commit/82055b2))
|
||||
* **upgrade:** support $element in upgraded component template/templateUrl functions ([#31637](https://github.com/angular/angular/issues/31637)) ([29e1c53](https://github.com/angular/angular/commit/29e1c53))
|
||||
* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96))
|
||||
* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([24ca582](https://github.com/angular/angular/commit/24ca582)), closes [#31627](https://github.com/angular/angular/issues/31627)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** DebugElement.listeners not cleared on destroy ([#31820](https://github.com/angular/angular/issues/31820)) ([46b160e](https://github.com/angular/angular/commit/46b160e))
|
||||
* **bazel:** increase memory limit of ngc under bazel from 2 to 4 GB ([#31784](https://github.com/angular/angular/issues/31784)) ([5a8eb92](https://github.com/angular/angular/commit/5a8eb92))
|
||||
* **core:** allow Z variations of CSS transforms in sanitizer ([#29264](https://github.com/angular/angular/issues/29264)) ([78e7fdd](https://github.com/angular/angular/commit/78e7fdd))
|
||||
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([7151eae](https://github.com/angular/angular/commit/7151eae)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
|
||||
* **platform-browser:** debug element query predicates not compatible with strictFunctionTypes ([#30993](https://github.com/angular/angular/issues/30993)) ([10a1e19](https://github.com/angular/angular/commit/10a1e19))
|
||||
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([9204de9](https://github.com/angular/angular/commit/9204de9))
|
||||
* **bazel:** pass custom bazel compiler host rather than rewriting one ([#31496](https://github.com/angular/angular/issues/31496)) ([0c61a35](https://github.com/angular/angular/commit/0c61a35))
|
||||
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([3166cff](https://github.com/angular/angular/commit/3166cff)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
||||
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
|
||||
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
|
||||
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
|
||||
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
|
||||
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
|
||||
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
|
||||
|
||||
|
||||
|
||||
<a name="8.1.3"></a>
|
||||
## [8.1.3](https://github.com/angular/angular/compare/8.1.2...8.1.3) (2019-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **elements:** handle falsy initial value ([#31604](https://github.com/angular/angular/issues/31604)) ([434b796](https://github.com/angular/angular/commit/434b796)), closes [angular/angular#30834](https://github.com/angular/angular/issues/30834)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler:** avoid copying from prototype while cloning an object ([#31638](https://github.com/angular/angular/issues/31638)) ([1f3daa0](https://github.com/angular/angular/commit/1f3daa0)), closes [#31627](https://github.com/angular/angular/issues/31627)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -22,23 +68,6 @@
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
|
||||
|
||||
|
||||
<a name="8.2.0-next.1"></a>
|
||||
# [8.2.0-next.1](https://github.com/angular/angular/compare/8.2.0-next.0...8.2.0-next.1) (2019-07-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
|
||||
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** add automatic migration from Renderer to Renderer2 ([#30936](https://github.com/angular/angular/issues/30936)) ([c095597](https://github.com/angular/angular/commit/c095597))
|
||||
|
||||
|
||||
|
||||
<a name="8.1.1"></a>
|
||||
## [8.1.1](https://github.com/angular/angular/compare/8.1.0...8.1.1) (2019-07-10)
|
||||
|
||||
@ -48,23 +77,6 @@
|
||||
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com//github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com//github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||
|
||||
|
||||
<a name="8.2.0-next.0"></a>
|
||||
# [8.2.0-next.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.2.0-next.0) (2019-07-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
|
||||
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
|
||||
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** allow passing a custom bazel compiler host to ngc compile ([#31341](https://github.com/angular/angular/issues/31341)) ([a29dc96](https://github.com/angular/angular/commit/a29dc96))
|
||||
* **bazel:** allow passing and rewriting an old bazel host ([#31381](https://github.com/angular/angular/issues/31381)) ([11a208f](https://github.com/angular/angular/commit/11a208f)), closes [#31341](https://github.com/angular/angular/issues/31341)
|
||||
|
||||
|
||||
|
||||
<a name="8.1.0"></a>
|
||||
# [8.1.0](https://github.com/angular/angular/compare/8.1.0-rc.0...8.1.0) (2019-07-02)
|
||||
|
12
WORKSPACE
12
WORKSPACE
@ -21,8 +21,8 @@ http_archive(
|
||||
patch_args = ["-p1"],
|
||||
# Patch https://github.com/bazelbuild/rules_nodejs/pull/903
|
||||
patches = ["//tools:rollup_bundle_commonjs_ignoreGlobal.patch"],
|
||||
sha256 = "6d4edbf28ff6720aedf5f97f9b9a7679401bf7fca9d14a0fff80f644a99992b4",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.32.2/rules_nodejs-0.32.2.tar.gz"],
|
||||
sha256 = "7c4a690268be97c96f04d505224ec4cb1ae53c2c2b68be495c9bd2634296a5cd",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.34.0/rules_nodejs-0.34.0.tar.gz"],
|
||||
)
|
||||
|
||||
# Check the bazel version and download npm dependencies
|
||||
@ -53,7 +53,8 @@ Try running `yarn bazel` instead.
|
||||
# - 0.32.0 yarn_install and npm_install no longer puts build files under symlinked node_modules
|
||||
# - 0.32.1 remove override of @bazel/tsetse & exclude typescript lib declarations in node_module_library transitive_declarations
|
||||
# - 0.32.2 resolves bug in @bazel/hide-bazel-files postinstall step
|
||||
check_rules_nodejs_version(minimum_version_string = "0.32.2")
|
||||
# - 0.34.0 introduces protractor rule
|
||||
check_rules_nodejs_version(minimum_version_string = "0.34.0")
|
||||
|
||||
# Setup the Node.js toolchain
|
||||
node_repositories(
|
||||
@ -91,6 +92,11 @@ load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||
|
||||
rules_angular_dev_dependencies()
|
||||
|
||||
# Load protractor dependencies
|
||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||
|
||||
npm_bazel_protractor_dependencies()
|
||||
|
||||
# Load karma dependencies
|
||||
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||
|
||||
|
@ -128,7 +128,7 @@ The third argument, `easing`, controls how the animation [accelerates and decele
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Note:** See the Angular Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
|
||||
**Note:** See the Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
|
||||
</div>
|
||||
|
||||
This example provides a state transition from `open` to `closed` with a one second transition between states.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
You learned the basics of Angular animations in the [introduction](guide/animations) page.
|
||||
|
||||
In this guide, we go into greater depth on special transition states such as `*` (wildcard) and `void`, and show how these special states are used for elements entering and leaving a view. The chapter also explores on multiple animation triggers, animation callbacks and sequence-based animation using keyframes.
|
||||
In this guide, we go into greater depth on special transition states such as `*` (wildcard) and `void`, and show how these special states are used for elements entering and leaving a view. The chapter also explores multiple animation triggers, animation callbacks and sequence-based animation using keyframes.
|
||||
|
||||
## Predefined states and wildcard matching
|
||||
|
||||
|
@ -317,7 +317,7 @@ Each hero in the heroes list should have a delete button.
|
||||
Add the following button element to the `HeroesComponent` template, after the hero
|
||||
name in the repeated `<li>` element.
|
||||
|
||||
<code-example path="toh-pt6/src/app/heroes/heroes.component.html" header="src/app/hero.service.ts" region="delete"></code-example>
|
||||
<code-example path="toh-pt6/src/app/heroes/heroes.component.html" header="src/app/heroes/heroes.component.html" region="delete"></code-example>
|
||||
|
||||
The HTML for the list of heroes should look like this:
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
"build-local": "yarn ~~build",
|
||||
"prebuild-with-ivy": "yarn setup-local && node scripts/switch-to-ivy",
|
||||
"build-with-ivy": "yarn ~~build",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js a8fe15cb6",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 1e83a8ecb",
|
||||
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
||||
"test": "yarn check-env && ng test",
|
||||
"pree2e": "yarn check-env && yarn update-webdriver",
|
||||
|
@ -28,11 +28,11 @@
|
||||
"uncompressed": {
|
||||
"runtime-es5": 2932,
|
||||
"runtime-es2015": 2938,
|
||||
"main-es5": 555102,
|
||||
"main-es5": 560811,
|
||||
"main-es2015": 572938,
|
||||
"polyfills-es5": 129161,
|
||||
"polyfills-es2015": 53295
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -471,7 +471,7 @@
|
||||
|
||||
"@types/node@~8.9.4":
|
||||
version "8.9.5"
|
||||
resolved "http://registry.npmjs.org/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976"
|
||||
|
||||
"@types/q@^0.0.32":
|
||||
version "0.0.32"
|
||||
@ -2820,7 +2820,7 @@ express@2.5.x:
|
||||
|
||||
express@^4.14.1:
|
||||
version "4.16.3"
|
||||
resolved "http://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
|
||||
resolved "https://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
|
||||
dependencies:
|
||||
accepts "~1.3.5"
|
||||
array-flatten "1.1.1"
|
||||
@ -3039,7 +3039,7 @@ finalhandler@1.0.6:
|
||||
|
||||
finalhandler@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
|
||||
resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
@ -5592,7 +5592,7 @@ p-finally@^1.0.0:
|
||||
|
||||
p-is-promise@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
|
||||
resolved "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
|
||||
|
||||
p-limit@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -53,6 +53,7 @@ gulp.task('tools:build', loadTask('tools-build'));
|
||||
gulp.task('check-cycle', loadTask('check-cycle'));
|
||||
gulp.task('serve', loadTask('serve', 'default'));
|
||||
gulp.task('changelog', loadTask('changelog'));
|
||||
gulp.task('changelog:zonejs', loadTask('changelog-zonejs'));
|
||||
gulp.task('check-env', () => {/* this is a noop because the env test ran already above */});
|
||||
gulp.task('cldr:extract', loadTask('cldr', 'extract'));
|
||||
gulp.task('cldr:download', loadTask('cldr', 'download'));
|
||||
|
@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "6d4edbf28ff6720aedf5f97f9b9a7679401bf7fca9d14a0fff80f644a99992b4",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.32.2/rules_nodejs-0.32.2.tar.gz"],
|
||||
sha256 = "7c4a690268be97c96f04d505224ec4cb1ae53c2c2b68be495c9bd2634296a5cd",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.34.0/rules_nodejs-0.34.0.tar.gz"],
|
||||
)
|
||||
|
||||
# Fetch sass rules for compiling sass files
|
||||
@ -62,6 +62,11 @@ load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||
|
||||
install_bazel_dependencies()
|
||||
|
||||
# Load protractor dependencies
|
||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||
|
||||
npm_bazel_protractor_dependencies()
|
||||
|
||||
# Load karma dependencies
|
||||
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||
|
||||
|
@ -23,11 +23,10 @@
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@bazel/bazel": "file:../../node_modules/@bazel/bazel",
|
||||
"@bazel/hide-bazel-files": "0.32.2",
|
||||
"@bazel/karma": "0.32.2",
|
||||
"@bazel/typescript": "0.32.2",
|
||||
"@bazel/karma": "0.34.0",
|
||||
"@bazel/protractor": "0.34.0",
|
||||
"@bazel/typescript": "0.34.0",
|
||||
"@types/jasmine": "2.8.8",
|
||||
"protractor": "5.1.2",
|
||||
"typescript": "3.4.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -1,5 +1,5 @@
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
||||
load("@npm_angular_bazel//:index.bzl", "protractor_web_test_suite")
|
||||
|
||||
ts_library(
|
||||
name = "e2e",
|
||||
@ -7,7 +7,7 @@ ts_library(
|
||||
srcs = ["app.spec.ts"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = [
|
||||
"@npm//@types",
|
||||
"@npm//@types/jasmine",
|
||||
"@npm//protractor",
|
||||
],
|
||||
)
|
||||
@ -18,8 +18,8 @@ ts_library(
|
||||
srcs = ["on-prepare.ts"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = [
|
||||
"@npm//@angular/bazel",
|
||||
"@npm//@types",
|
||||
"@npm//@bazel/protractor",
|
||||
"@npm//@types/node",
|
||||
"@npm//protractor",
|
||||
],
|
||||
)
|
||||
@ -27,10 +27,6 @@ ts_library(
|
||||
protractor_web_test_suite(
|
||||
name = "devserver_test",
|
||||
configuration = "//:protractor.conf.js",
|
||||
data = [
|
||||
"@npm//@angular/bazel",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":ts_on_prepare",
|
||||
server = "//src:devserver",
|
||||
deps = [":e2e"],
|
||||
@ -39,10 +35,6 @@ protractor_web_test_suite(
|
||||
protractor_web_test_suite(
|
||||
name = "prodserver_test",
|
||||
configuration = "//:protractor.conf.js",
|
||||
data = [
|
||||
"@npm//@angular/bazel",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":ts_on_prepare",
|
||||
server = "//src:prodserver",
|
||||
deps = [":e2e"],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { browser } from 'protractor';
|
||||
import {OnPrepareConfig, runServer} from '@angular/bazel/protractor-utils';
|
||||
import {OnPrepareConfig, runServer} from '@bazel/protractor/protractor-utils';
|
||||
|
||||
export = function(config: OnPrepareConfig) {
|
||||
const portFlag = /prodserver(\.exe)?$/.test(config.server) ? '-p' : '-port';
|
||||
|
@ -30,12 +30,12 @@
|
||||
rxjs "6.4.0"
|
||||
|
||||
"@angular/animations@file:../../dist/packages-dist/animations":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/bazel@file:../../dist/packages-dist/bazel":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "^0.800.0-beta.15"
|
||||
"@angular-devkit/core" "^8.0.0-beta.15"
|
||||
@ -57,12 +57,12 @@
|
||||
parse5 "^5.0.0"
|
||||
|
||||
"@angular/common@file:../../dist/packages-dist/common":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/compiler-cli@file:../../dist/packages-dist/compiler-cli":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
canonical-path "1.0.0"
|
||||
chokidar "^2.1.1"
|
||||
@ -76,17 +76,17 @@
|
||||
yargs "13.1.0"
|
||||
|
||||
"@angular/compiler@file:../../dist/packages-dist/compiler":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/core@file:../../dist/packages-dist/core":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/forms@file:../../dist/packages-dist/forms":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
@ -98,51 +98,53 @@
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/platform-browser-dynamic@file:../../dist/packages-dist/platform-browser-dynamic":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/platform-browser@file:../../dist/packages-dist/platform-browser":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/router@file:../../dist/packages-dist/router":
|
||||
version "8.1.0-next.3"
|
||||
version "8.2.0-next.2"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@bazel/bazel-darwin_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.27.0.tgz#83a03c92d52ae60e48e86a1ee697e69e12ddbdf6"
|
||||
integrity sha512-CyavIbRKRa/55aMyfEM9hjbt4TVISfv7HLeymHTGTLWzS8uQokQ8W9tR/pgc7YJn8F0x64dd7nQKxhbYHM1Qfg==
|
||||
"@bazel/bazel-darwin_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.28.1.tgz#415658785e1dbd6f7ab5c8f2b98c1c99c614e1d5"
|
||||
integrity sha512-VDKWmplAfa4uCAbkIQ5nRn04MFQqtsPNuc2HkluJ8OIum773yC2dPR+OlLBKxrlBuKJYB27TtbOwOa6w/uK7aw==
|
||||
|
||||
"@bazel/bazel-linux_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.27.0.tgz#2358292aa4901f526ba9b90874256f63d6d6608c"
|
||||
integrity sha512-hO04v7C6M3Jf+qNlLE+IticZZKkkS7Nv6+pXDnENgFWrqLV2H93un6kNQnk83B0hP2cEqRQ8rw5yrIcqXNNuSQ==
|
||||
"@bazel/bazel-linux_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.28.1.tgz#f78006089e17660261088272a0e04fc886572e34"
|
||||
integrity sha512-n4XfNxagYhejQD32V4XSxT/qzuH1l/2jxslbKSak66/uQ+wad8Ew9rjNb4JUin3xtrfFtzmxx2jpQkybZsRVGA==
|
||||
|
||||
"@bazel/bazel-win32_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.27.0.tgz#0e5e498de5ccccc9a6cf481cd46904ee938ab6c2"
|
||||
integrity sha512-7hIGNhdgaxRt9ceSOCs3eSTtCNi4GXz3nu6OjfgSp+QiqLbW/iAVWa8M8vD5aemZ1BSHek4/LISdWUTncLJk+w==
|
||||
"@bazel/bazel-win32_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.28.1.tgz#60a2819618cf7582cc35ac16c01763a5e807b414"
|
||||
integrity sha512-T4xksGfKikaHS4zxnGT6r5R436mz9j2lz//L1vc5sJnaEF/1e2Gv6MLl86vfZW2Xxo6iIEi6ntSzgYxP2Blohw==
|
||||
|
||||
"@bazel/bazel@file:../../node_modules/@bazel/bazel":
|
||||
version "0.27.0"
|
||||
version "0.28.1"
|
||||
dependencies:
|
||||
"@bazel/hide-bazel-files" latest
|
||||
optionalDependencies:
|
||||
"@bazel/bazel-darwin_x64" "0.27.0"
|
||||
"@bazel/bazel-linux_x64" "0.27.0"
|
||||
"@bazel/bazel-win32_x64" "0.27.0"
|
||||
"@bazel/bazel-darwin_x64" "0.28.1"
|
||||
"@bazel/bazel-linux_x64" "0.28.1"
|
||||
"@bazel/bazel-win32_x64" "0.28.1"
|
||||
|
||||
"@bazel/hide-bazel-files@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/hide-bazel-files/-/hide-bazel-files-0.32.2.tgz#a482855eafbccb56b1fce0d92ff922c2c6e0a90c"
|
||||
integrity sha512-585XY53mhMZaCjEQJ+aDqkmydWZbuXsKrZsSpoW9YeAVEH0poQY3YhdyCPmMVBo7/l1mkrqpFuOK5BpECfwdtA==
|
||||
"@bazel/hide-bazel-files@latest":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/hide-bazel-files/-/hide-bazel-files-0.34.0.tgz#368ea84db2756ff80ead23bb9eb179e9ed24b462"
|
||||
integrity sha512-suyO6cZf8iV6W2LkM1X1spWBt7CsRRXH7gU1wYNuAuHYkkfI0A6qj84yPiIXiOt/2G44kbioGyC1bUsI3fKv7A==
|
||||
|
||||
"@bazel/karma@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-0.32.2.tgz#0f6adf0cf1970c50cfdcf9cb2b10a8d3e21731fe"
|
||||
integrity sha512-iWb8aqE+llpZhlreDweM7llwnSAQ9QTYdz4VvIcZBGVD0KtHxHaKiqK4Zo4Qrmr9H0kcOhT7nvRBg3QOUJVrUw==
|
||||
"@bazel/karma@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-0.34.0.tgz#ee468501a408244a2c1844b48ca5a938874d9444"
|
||||
integrity sha512-9EziieE3Zkf7D5tBuX4rO+hhpI4ypNAWReiO/fykjj5oYpLYhhhGGUyFQ8PCIfduPcGZooCTMsctmwZJUb3rRA==
|
||||
dependencies:
|
||||
jasmine-core "2.8.0"
|
||||
karma "^4.0.0"
|
||||
@ -156,10 +158,17 @@
|
||||
semver "5.6.0"
|
||||
tmp "0.0.33"
|
||||
|
||||
"@bazel/typescript@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.32.2.tgz#c296bb44cb6362a0e3a08ca88752852bc9591ecf"
|
||||
integrity sha512-32zDyvHdYjIa63vtImhl6wy5ErOFVWPkjMT2T035D0UPSKI1tvENW/bRZ3QFlFHqfmJZRBpaI3GiUpO3vUvzmw==
|
||||
"@bazel/protractor@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-0.34.0.tgz#af166306518bf1319e8ca255f798712c8714b5e9"
|
||||
integrity sha512-U6O8hRlerkQ/WfnEVct1yipVQr5epdYaLiOW1eLpmiRMM4RuMhIpIyKkpum5xqFlYP5kwqwje8BS8NHvBfvZnQ==
|
||||
dependencies:
|
||||
protractor "^5.4.2"
|
||||
|
||||
"@bazel/typescript@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.34.0.tgz#ca0fdf15343a930fc1418dbbf7d6cae49e6bc89b"
|
||||
integrity sha512-GXVSADXdbPyWLskIYAzQsBB1LhZgWF5+M6WCQGOvRWjZfXgRP5QDG5pKJavRGzVd6ofigLPA1xT6Vc7dUEDNtg==
|
||||
dependencies:
|
||||
protobufjs "6.8.8"
|
||||
semver "5.6.0"
|
||||
@ -327,20 +336,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.9.tgz#2e8d678039d27943ce53a1913386133227fd9066"
|
||||
integrity sha512-NelG/dSahlXYtSoVPErrp06tYFrvzj8XLWmKA+X8x0W//4MqbUyZu++giUG/v0bjAT6/Qxa8IjodrfdACyb0Fg==
|
||||
|
||||
"@types/node@^6.0.46":
|
||||
version "6.14.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.14.6.tgz#31df045b4c7618ff74d84f542fc3d29445dd566b"
|
||||
integrity sha512-rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w==
|
||||
|
||||
"@types/q@^0.0.32":
|
||||
version "0.0.32"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
|
||||
integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU=
|
||||
|
||||
"@types/selenium-webdriver@^2.53.35", "@types/selenium-webdriver@~2.53.39":
|
||||
version "2.53.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz#2de3d718819bc20165754c4a59afb7e9833f6707"
|
||||
integrity sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==
|
||||
"@types/selenium-webdriver@^3.0.0":
|
||||
version "3.0.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz#50a4755f8e33edacd9c406729e9b930d2451902a"
|
||||
integrity sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==
|
||||
|
||||
"@types/z-schema@3.16.31":
|
||||
version "3.16.31"
|
||||
@ -360,12 +364,7 @@ accepts@~1.3.4:
|
||||
mime-types "~2.1.24"
|
||||
negotiator "0.6.2"
|
||||
|
||||
adm-zip@0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736"
|
||||
integrity sha1-ph7VrmkFw66lizplfSUDMJEFJzY=
|
||||
|
||||
adm-zip@^0.4.7, adm-zip@^0.4.9, adm-zip@~0.4.3:
|
||||
adm-zip@^0.4.9, adm-zip@~0.4.3:
|
||||
version "0.4.13"
|
||||
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a"
|
||||
integrity sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==
|
||||
@ -375,14 +374,6 @@ after@0.8.2:
|
||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
|
||||
|
||||
agent-base@2:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7"
|
||||
integrity sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=
|
||||
dependencies:
|
||||
extend "~3.0.0"
|
||||
semver "~5.0.1"
|
||||
|
||||
agent-base@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||
@ -601,10 +592,10 @@ blob@0.0.5:
|
||||
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
|
||||
integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
|
||||
|
||||
blocking-proxy@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-0.0.5.tgz#462905e0dcfbea970f41aa37223dda9c07b1912b"
|
||||
integrity sha1-RikF4Nz76pcPQao3Ij3anAexkSs=
|
||||
blocking-proxy@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2"
|
||||
integrity sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
@ -653,6 +644,13 @@ braces@^2.3.1, braces@^2.3.2:
|
||||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
browserstack@^1.5.1:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.2.tgz#17d8bb76127a1cc0ea416424df80d218f803673f"
|
||||
integrity sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==
|
||||
dependencies:
|
||||
https-proxy-agent "^2.2.1"
|
||||
|
||||
buffer-alloc-unsafe@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||
@ -905,7 +903,7 @@ date-format@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.0.0.tgz#7cf7b172f1ec564f0003b39ea302c5498fb98c8f"
|
||||
integrity sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==
|
||||
|
||||
debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
@ -1171,7 +1169,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
|
||||
assign-symbols "^1.0.0"
|
||||
is-extendable "^1.0.1"
|
||||
|
||||
extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.2:
|
||||
extend@^3.0.0, extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
@ -1486,15 +1484,6 @@ http-signature@~1.2.0:
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
https-proxy-agent@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6"
|
||||
integrity sha1-NffabEjOTdv6JkiRrFk+5f+GceY=
|
||||
dependencies:
|
||||
agent-base "2"
|
||||
debug "2"
|
||||
extend "3"
|
||||
|
||||
https-proxy-agent@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
|
||||
@ -1748,7 +1737,7 @@ isstream@~0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
jasmine-core@2.8.0:
|
||||
jasmine-core@2.8.0, jasmine-core@~2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
|
||||
integrity sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=
|
||||
@ -1758,19 +1747,14 @@ jasmine-core@^3.3:
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.4.0.tgz#2a74618e966026530c3518f03e9f845d26473ce3"
|
||||
integrity sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==
|
||||
|
||||
jasmine-core@~2.99.0:
|
||||
version "2.99.1"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.99.1.tgz#e6400df1e6b56e130b61c4bcd093daa7f6e8ca15"
|
||||
integrity sha1-5kAN8ea1bhMLYcS80JPap/boyhU=
|
||||
|
||||
jasmine@^2.5.3:
|
||||
version "2.99.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.99.0.tgz#8ca72d102e639b867c6489856e0e18a9c7aa42b7"
|
||||
integrity sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=
|
||||
jasmine@2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e"
|
||||
integrity sha1-awicChFXax8W3xG4AUbZHU6Lij4=
|
||||
dependencies:
|
||||
exit "^0.1.2"
|
||||
glob "^7.0.6"
|
||||
jasmine-core "~2.99.0"
|
||||
jasmine-core "~2.8.0"
|
||||
|
||||
jasminewd2@^2.1.0:
|
||||
version "2.2.0"
|
||||
@ -1819,6 +1803,16 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jszip@^3.1.3:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.2.tgz#b143816df7e106a9597a94c77493385adca5bd1d"
|
||||
integrity sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==
|
||||
dependencies:
|
||||
lie "~3.3.0"
|
||||
pako "~1.0.2"
|
||||
readable-stream "~2.3.6"
|
||||
set-immediate-shim "~1.0.1"
|
||||
|
||||
jszip@^3.1.5:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.1.tgz#c5d32df7274042282b157efb16e522b43435e01a"
|
||||
@ -2308,11 +2302,6 @@ optimist@^0.6.1, optimist@~0.6.0:
|
||||
minimist "~0.0.1"
|
||||
wordwrap "~0.0.2"
|
||||
|
||||
options@>=0.0.5:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
|
||||
integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=
|
||||
|
||||
os-homedir@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||
@ -2489,25 +2478,25 @@ protobufjs@6.8.8:
|
||||
"@types/node" "^10.1.0"
|
||||
long "^4.0.0"
|
||||
|
||||
protractor@5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.2.tgz#9b221741709a4c62d5cd53c6aadd54a71137e95f"
|
||||
integrity sha1-myIXQXCaTGLVzVPGqt1UpxE36V8=
|
||||
protractor@^5.4.2:
|
||||
version "5.4.2"
|
||||
resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.4.2.tgz#329efe37f48b2141ab9467799be2d4d12eb48c13"
|
||||
integrity sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==
|
||||
dependencies:
|
||||
"@types/node" "^6.0.46"
|
||||
"@types/q" "^0.0.32"
|
||||
"@types/selenium-webdriver" "~2.53.39"
|
||||
blocking-proxy "0.0.5"
|
||||
"@types/selenium-webdriver" "^3.0.0"
|
||||
blocking-proxy "^1.0.0"
|
||||
browserstack "^1.5.1"
|
||||
chalk "^1.1.3"
|
||||
glob "^7.0.3"
|
||||
jasmine "^2.5.3"
|
||||
jasmine "2.8.0"
|
||||
jasminewd2 "^2.1.0"
|
||||
optimist "~0.6.0"
|
||||
q "1.4.1"
|
||||
saucelabs "~1.3.0"
|
||||
selenium-webdriver "3.0.1"
|
||||
saucelabs "^1.5.0"
|
||||
selenium-webdriver "3.6.0"
|
||||
source-map-support "~0.4.0"
|
||||
webdriver-js-extender "^1.0.0"
|
||||
webdriver-js-extender "2.1.0"
|
||||
webdriver-manager "^12.0.6"
|
||||
|
||||
pseudomap@^1.0.2:
|
||||
@ -2774,44 +2763,21 @@ saucelabs@^1.5.0:
|
||||
dependencies:
|
||||
https-proxy-agent "^2.2.1"
|
||||
|
||||
saucelabs@~1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.3.0.tgz#d240e8009df7fa87306ec4578a69ba3b5c424fee"
|
||||
integrity sha1-0kDoAJ33+ocwbsRXimm6O1xCT+4=
|
||||
dependencies:
|
||||
https-proxy-agent "^1.0.0"
|
||||
|
||||
sax@0.6.x:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9"
|
||||
integrity sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=
|
||||
|
||||
sax@>=0.6.0, sax@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
selenium-webdriver@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz#a2dea5da4a97f6672e89e7ca7276cefa365147a7"
|
||||
integrity sha1-ot6l2kqX9mcuiefKcnbO+jZRR6c=
|
||||
selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc"
|
||||
integrity sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==
|
||||
dependencies:
|
||||
adm-zip "^0.4.7"
|
||||
jszip "^3.1.3"
|
||||
rimraf "^2.5.4"
|
||||
tmp "0.0.30"
|
||||
xml2js "^0.4.17"
|
||||
|
||||
selenium-webdriver@^2.53.2:
|
||||
version "2.53.3"
|
||||
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085"
|
||||
integrity sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=
|
||||
dependencies:
|
||||
adm-zip "0.4.4"
|
||||
rimraf "^2.2.8"
|
||||
tmp "0.0.24"
|
||||
ws "^1.0.1"
|
||||
xml2js "0.4.4"
|
||||
|
||||
selenium-webdriver@^4.0.0-alpha.1:
|
||||
version "4.0.0-alpha.3"
|
||||
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.3.tgz#fb974f29696a6801ecaf203e38a65c3dbe7e363a"
|
||||
@ -2832,11 +2798,6 @@ semver@^5.3.0, semver@^5.5.0, semver@^5.6.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
||||
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
|
||||
|
||||
semver@~5.0.1:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a"
|
||||
integrity sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
@ -3158,11 +3119,6 @@ tar@^4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tmp@0.0.24:
|
||||
version "0.0.24"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12"
|
||||
integrity sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=
|
||||
|
||||
tmp@0.0.30:
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed"
|
||||
@ -3276,11 +3232,6 @@ typescript@~3.4.3:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
|
||||
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
|
||||
|
||||
ultron@1.0.x:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
|
||||
integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=
|
||||
|
||||
ultron@~1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
|
||||
@ -3378,13 +3329,13 @@ void-elements@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
||||
|
||||
webdriver-js-extender@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz#81c533a9e33d5bfb597b4e63e2cdb25b54777515"
|
||||
integrity sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=
|
||||
webdriver-js-extender@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7"
|
||||
integrity sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==
|
||||
dependencies:
|
||||
"@types/selenium-webdriver" "^2.53.35"
|
||||
selenium-webdriver "^2.53.2"
|
||||
"@types/selenium-webdriver" "^3.0.0"
|
||||
selenium-webdriver "^3.0.1"
|
||||
|
||||
webdriver-manager@^12.0.6:
|
||||
version "12.1.5"
|
||||
@ -3440,14 +3391,6 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
ws@^1.0.1:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51"
|
||||
integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==
|
||||
dependencies:
|
||||
options ">=0.0.5"
|
||||
ultron "1.0.x"
|
||||
|
||||
ws@~3.3.1:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
|
||||
@ -3457,14 +3400,6 @@ ws@~3.3.1:
|
||||
safe-buffer "~5.1.0"
|
||||
ultron "~1.1.0"
|
||||
|
||||
xml2js@0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.4.tgz#3111010003008ae19240eba17497b57c729c555d"
|
||||
integrity sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=
|
||||
dependencies:
|
||||
sax "0.6.x"
|
||||
xmlbuilder ">=1.0.0"
|
||||
|
||||
xml2js@^0.4.17, xml2js@^0.4.19:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
|
||||
@ -3473,11 +3408,6 @@ xml2js@^0.4.17, xml2js@^0.4.19:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~9.0.1"
|
||||
|
||||
xmlbuilder@>=1.0.0:
|
||||
version "13.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7"
|
||||
integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==
|
||||
|
||||
xmlbuilder@~9.0.1:
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
|
||||
|
@ -8084,7 +8084,7 @@ through2@^2.0.0:
|
||||
|
||||
"through@>=2.2.7 <3", through@X.X.X, through@^2.3.6:
|
||||
version "2.3.8"
|
||||
resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
||||
thunkify@~2.1.1:
|
||||
|
@ -67,8 +67,15 @@ if [[ $? != 0 ]]; then exit 1; fi
|
||||
grep "_MatMenuBase.ngBaseDef = ɵngcc0.ɵɵdefineBase({ inputs: {" node_modules/@angular/material/esm5/menu.es5.js
|
||||
if [[ $? != 0 ]]; then exit 1; fi
|
||||
|
||||
# Did it handle namespace imported decorators in UMD?
|
||||
# Did it handle namespace imported decorators in UMD using `__decorate` syntax?
|
||||
grep "type: core.Injectable" node_modules/@angular/common/bundles/common.umd.js
|
||||
# (and ensure the @angular/common package is indeed using `__decorate` syntax)
|
||||
grep "JsonPipe = __decorate(" node_modules/@angular/common/bundles/common.umd.js.__ivy_ngcc_bak
|
||||
|
||||
# Did it handle namespace imported decorators in UMD using static properties?
|
||||
grep "type: core.Injectable," node_modules/@angular/cdk/bundles/cdk-a11y.umd.js
|
||||
# (and ensure the @angular/cdk/a11y package is indeed using static properties)
|
||||
grep "FocusMonitor.decorators =" node_modules/@angular/cdk/bundles/cdk-a11y.umd.js.__ivy_ngcc_bak
|
||||
|
||||
# Can it be safely run again (as a noop)?
|
||||
# And check that it logged skipping compilation as expected
|
||||
|
@ -1,4 +1,4 @@
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
|
||||
"""
|
||||
Macro that can be used to define a benchmark test. This differentiates from
|
||||
@ -18,7 +18,6 @@ def benchmark_test(name, server, deps, tags = []):
|
||||
server = server,
|
||||
tags = tags,
|
||||
deps = [
|
||||
"@npm//protractor",
|
||||
"@npm//yargs",
|
||||
] + deps,
|
||||
)
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
def example_test(name, srcs, server, data = [], **kwargs):
|
||||
@ -18,12 +18,11 @@ def example_test(name, srcs, server, data = [], **kwargs):
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "protractor_tests",
|
||||
data = ["//packages/bazel/src/protractor/utils"] + data,
|
||||
data = data,
|
||||
on_prepare = "//modules/playground/e2e_test:start-server.js",
|
||||
server = server,
|
||||
deps = [
|
||||
":%s_lib" % name,
|
||||
"@npm//protractor",
|
||||
"@npm//selenium-webdriver",
|
||||
"@npm//yargs",
|
||||
"@npm//source-map",
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "8.2.0-next.2",
|
||||
"version": "9.0.0-next.0",
|
||||
"private": true,
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
"homepage": "https://github.com/angular/angular",
|
||||
@ -35,10 +35,10 @@
|
||||
"@angular-devkit/core": "^8.0.0-beta.15",
|
||||
"@angular-devkit/schematics": "^8.0.0-beta.15",
|
||||
"@angular/bazel": "file:./tools/npm/@angular_bazel",
|
||||
"@bazel/jasmine": "0.32.2",
|
||||
"@bazel/hide-bazel-files": "0.32.2",
|
||||
"@bazel/karma": "0.32.2",
|
||||
"@bazel/typescript": "0.32.2",
|
||||
"@bazel/jasmine": "0.34.0",
|
||||
"@bazel/karma": "0.34.0",
|
||||
"@bazel/protractor": "0.34.0",
|
||||
"@bazel/typescript": "0.34.0",
|
||||
"@microsoft/api-extractor": "^7.0.21",
|
||||
"@schematics/angular": "^8.0.0-beta.15",
|
||||
"@types/angular": "^1.6.47",
|
||||
@ -120,7 +120,7 @@
|
||||
"// 3": "when updating @bazel/bazel version you also need to update the RBE settings in .bazelrc (see https://github.com/angular/angular/pull/27935)",
|
||||
"devDependencies": {
|
||||
"@angular/cli": "^8.0.0-beta.15",
|
||||
"@bazel/bazel": "0.27.0",
|
||||
"@bazel/bazel": "0.28.1",
|
||||
"@bazel/buildifier": "^0.26.0",
|
||||
"@bazel/ibazel": "~0.9.0",
|
||||
"@types/minimist": "^1.2.0",
|
||||
@ -166,4 +166,4 @@
|
||||
"resolutions": {
|
||||
"natives": "1.1.6"
|
||||
}
|
||||
}
|
||||
}
|
@ -25,12 +25,13 @@ def rules_angular_dev_dependencies():
|
||||
"""
|
||||
|
||||
# Needed for Remote Execution
|
||||
# https://github.com/bazelbuild/bazel-toolchains/releases
|
||||
_maybe(
|
||||
http_archive,
|
||||
name = "bazel_toolchains",
|
||||
sha256 = "4598bf5a8b4f5ced82c782899438a7ba695165d47b3bf783ce774e89a8c6e617",
|
||||
strip_prefix = "bazel-toolchains-0.27.0",
|
||||
url = "https://github.com/bazelbuild/bazel-toolchains/archive/0.27.0.tar.gz",
|
||||
sha256 = "dcb58e7e5f0b4da54c6c5f8ebc65e63fcfb37414466010cf82ceff912162296e",
|
||||
strip_prefix = "bazel-toolchains-0.28.2",
|
||||
url = "https://github.com/bazelbuild/bazel-toolchains/archive/0.28.2.tar.gz",
|
||||
)
|
||||
|
||||
#############################################
|
||||
|
@ -15,8 +15,8 @@ workspace(
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
RULES_NODEJS_VERSION = "0.32.2"
|
||||
RULES_NODEJS_SHA256 = "6d4edbf28ff6720aedf5f97f9b9a7679401bf7fca9d14a0fff80f644a99992b4"
|
||||
RULES_NODEJS_VERSION = "0.34.0"
|
||||
RULES_NODEJS_SHA256 = "7c4a690268be97c96f04d505224ec4cb1ae53c2c2b68be495c9bd2634296a5cd"
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = RULES_NODEJS_SHA256,
|
||||
@ -63,8 +63,6 @@ node_repositories(
|
||||
|
||||
yarn_install(
|
||||
name = "npm",
|
||||
# TODO(gregmagolan): fix rules_nodejs so that if @bazel/hide-bazel-files is detected then this is forced true
|
||||
always_hide_bazel_files = True,
|
||||
package_json = "//:package.json",
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
@ -72,6 +70,9 @@ yarn_install(
|
||||
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||
install_bazel_dependencies()
|
||||
|
||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||
npm_bazel_protractor_dependencies()
|
||||
|
||||
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||
rules_karma_dependencies()
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
||||
load("@npm_angular_bazel//:index.bzl", "protractor_web_test_suite")
|
||||
|
||||
ts_library(
|
||||
name = "e2e_lib",
|
||||
@ -21,10 +21,6 @@ ts_library(
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "prodserver_test",
|
||||
data = [
|
||||
"@npm//@angular/bazel",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
server = "//src:prodserver",
|
||||
deps = [":e2e_lib"],
|
||||
@ -32,10 +28,6 @@ protractor_web_test_suite(
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "devserver_test",
|
||||
data = [
|
||||
"@npm//@angular/bazel",
|
||||
"@npm//protractor",
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
server = "//src:devserver",
|
||||
deps = [":e2e_lib"],
|
||||
|
@ -5,11 +5,11 @@
|
||||
// If the function returns a promise, as it does here, protractor will wait
|
||||
// for the promise to resolve before running tests.
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = function(config) {
|
||||
// In this example, `@angular/bazel/protractor-utils` is used to run
|
||||
// In this example, `@bazel/protractor/protractor-utils` is used to run
|
||||
// the server. protractorUtils.runServer() runs the server on a randomly
|
||||
// selected port (given a port flag to pass to the server as an argument).
|
||||
// The port used is returned in serverSpec and the protractor serverUrl
|
||||
|
@ -48,11 +48,11 @@ function addDevDependenciesToPackageJson(options: Schema) {
|
||||
|
||||
const devDependencies: {[k: string]: string} = {
|
||||
'@angular/bazel': angularCoreVersion,
|
||||
'@bazel/bazel': '^0.27.0',
|
||||
'@bazel/hide-bazel-files': '0.32.2',
|
||||
'@bazel/bazel': '^0.28.1',
|
||||
'@bazel/ibazel': '^0.10.2',
|
||||
'@bazel/karma': '0.32.2',
|
||||
'@bazel/typescript': '0.32.2',
|
||||
'@bazel/karma': '0.34.0',
|
||||
'@bazel/protractor': '0.34.0',
|
||||
'@bazel/typescript': '0.34.0',
|
||||
};
|
||||
|
||||
const recorder = host.beginUpdate(packageJson);
|
||||
|
@ -113,9 +113,10 @@ describe('ng-add schematic', () => {
|
||||
const json = JSON.parse(content);
|
||||
const devDeps = Object.keys(json.devDependencies);
|
||||
expect(devDeps).toContain('@bazel/bazel');
|
||||
expect(devDeps).toContain('@bazel/hide-bazel-files');
|
||||
expect(devDeps).toContain('@bazel/ibazel');
|
||||
expect(devDeps).toContain('@bazel/karma');
|
||||
expect(devDeps).toContain('@bazel/protractor');
|
||||
expect(devDeps).toContain('@bazel/typescript');
|
||||
});
|
||||
|
||||
it('should replace an existing dev dependency', async() => {
|
||||
|
@ -15,6 +15,7 @@ import localeHu from '@angular/common/locales/hu';
|
||||
import localeSr from '@angular/common/locales/sr';
|
||||
import localeTh from '@angular/common/locales/th';
|
||||
import {isDate, toDate, formatDate} from '@angular/common/src/i18n/format_date';
|
||||
import {ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID} from '@angular/core';
|
||||
|
||||
describe('Format date', () => {
|
||||
describe('toDate', () => {
|
||||
@ -46,13 +47,12 @@ describe('Format date', () => {
|
||||
|
||||
describe('formatDate', () => {
|
||||
const isoStringWithoutTime = '2015-01-01';
|
||||
const defaultLocale = 'en-US';
|
||||
const defaultFormat = 'mediumDate';
|
||||
let date: Date;
|
||||
|
||||
// Check the transformation of a date into a pattern
|
||||
function expectDateFormatAs(date: Date | string, pattern: any, output: string): void {
|
||||
expect(formatDate(date, pattern, defaultLocale)).toEqual(output, `pattern: "${pattern}"`);
|
||||
expect(formatDate(date, pattern, DEFAULT_LOCALE_ID)).toEqual(output, `pattern: "${pattern}"`);
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
@ -209,7 +209,8 @@ describe('Format date', () => {
|
||||
};
|
||||
|
||||
Object.keys(dateFixtures).forEach((pattern: string) => {
|
||||
expect(formatDate(date, pattern, defaultLocale, '+0430')).toMatch(dateFixtures[pattern]);
|
||||
expect(formatDate(date, pattern, DEFAULT_LOCALE_ID, '+0430'))
|
||||
.toMatch(dateFixtures[pattern]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -253,22 +254,22 @@ describe('Format date', () => {
|
||||
};
|
||||
|
||||
Object.keys(dateFixtures).forEach((pattern: string) => {
|
||||
expect(formatDate(date, pattern, defaultLocale)).toMatch(dateFixtures[pattern]);
|
||||
expect(formatDate(date, pattern, DEFAULT_LOCALE_ID)).toMatch(dateFixtures[pattern]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should format invalid in IE ISO date',
|
||||
() => expect(formatDate('2017-01-11T12:00:00.014-0500', defaultFormat, defaultLocale))
|
||||
() => expect(formatDate('2017-01-11T12:00:00.014-0500', defaultFormat, DEFAULT_LOCALE_ID))
|
||||
.toEqual('Jan 11, 2017'));
|
||||
|
||||
it('should format invalid in Safari ISO date',
|
||||
() => expect(formatDate('2017-01-20T12:00:00+0000', defaultFormat, defaultLocale))
|
||||
() => expect(formatDate('2017-01-20T12:00:00+0000', defaultFormat, DEFAULT_LOCALE_ID))
|
||||
.toEqual('Jan 20, 2017'));
|
||||
|
||||
// https://github.com/angular/angular/issues/9524
|
||||
// https://github.com/angular/angular/issues/9524
|
||||
it('should format correctly with iso strings that contain time',
|
||||
() => expect(formatDate('2017-05-07T22:14:39', 'dd-MM-yyyy HH:mm', defaultLocale))
|
||||
() => expect(formatDate('2017-05-07T22:14:39', 'dd-MM-yyyy HH:mm', DEFAULT_LOCALE_ID))
|
||||
.toMatch(/07-05-2017 \d{2}:\d{2}/));
|
||||
|
||||
// https://github.com/angular/angular/issues/21491
|
||||
@ -276,22 +277,22 @@ describe('Format date', () => {
|
||||
// this test only works if the timezone is not in UTC
|
||||
// which is the case for BrowserStack when we test Safari
|
||||
if (new Date().getTimezoneOffset() !== 0) {
|
||||
expect(formatDate('2018-01-11T13:00:00', 'HH', defaultLocale))
|
||||
.not.toEqual(formatDate('2018-01-11T13:00:00Z', 'HH', defaultLocale));
|
||||
expect(formatDate('2018-01-11T13:00:00', 'HH', DEFAULT_LOCALE_ID))
|
||||
.not.toEqual(formatDate('2018-01-11T13:00:00Z', 'HH', DEFAULT_LOCALE_ID));
|
||||
}
|
||||
});
|
||||
|
||||
// https://github.com/angular/angular/issues/16624
|
||||
// https://github.com/angular/angular/issues/17478
|
||||
it('should show the correct time when the timezone is fixed', () => {
|
||||
expect(formatDate('2017-06-13T10:14:39+0000', 'shortTime', defaultLocale, '+0000'))
|
||||
expect(formatDate('2017-06-13T10:14:39+0000', 'shortTime', DEFAULT_LOCALE_ID, '+0000'))
|
||||
.toEqual('10:14 AM');
|
||||
expect(formatDate('2017-06-13T10:14:39+0000', 'h:mm a', defaultLocale, '+0000'))
|
||||
expect(formatDate('2017-06-13T10:14:39+0000', 'h:mm a', DEFAULT_LOCALE_ID, '+0000'))
|
||||
.toEqual('10:14 AM');
|
||||
});
|
||||
|
||||
it('should remove bidi control characters',
|
||||
() => expect(formatDate(date, 'MM/dd/yyyy', defaultLocale) !.length).toEqual(10));
|
||||
() => expect(formatDate(date, 'MM/dd/yyyy', DEFAULT_LOCALE_ID) !.length).toEqual(10));
|
||||
|
||||
it(`should format the date correctly in various locales`, () => {
|
||||
expect(formatDate(date, 'short', 'de')).toEqual('15.06.15, 09:03');
|
||||
|
@ -12,10 +12,9 @@ import localeFr from '@angular/common/locales/fr';
|
||||
import localeAr from '@angular/common/locales/ar';
|
||||
import {formatCurrency, formatNumber, formatPercent, registerLocaleData} from '@angular/common';
|
||||
import {describe, expect, it} from '@angular/core/testing/src/testing_internal';
|
||||
import {ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID} from '@angular/core';
|
||||
|
||||
describe('Format number', () => {
|
||||
const defaultLocale = 'en-US';
|
||||
|
||||
beforeAll(() => {
|
||||
registerLocaleData(localeEn);
|
||||
registerLocaleData(localeEsUS);
|
||||
@ -26,18 +25,18 @@ describe('Format number', () => {
|
||||
describe('Number', () => {
|
||||
describe('transform', () => {
|
||||
it('should return correct value for numbers', () => {
|
||||
expect(formatNumber(12345, defaultLocale)).toEqual('12,345');
|
||||
expect(formatNumber(123, defaultLocale, '.2')).toEqual('123.00');
|
||||
expect(formatNumber(1, defaultLocale, '3.')).toEqual('001');
|
||||
expect(formatNumber(1.1, defaultLocale, '3.4-5')).toEqual('001.1000');
|
||||
expect(formatNumber(1.123456, defaultLocale, '3.4-5')).toEqual('001.12346');
|
||||
expect(formatNumber(1.1234, defaultLocale)).toEqual('1.123');
|
||||
expect(formatNumber(1.123456, defaultLocale, '.2')).toEqual('1.123');
|
||||
expect(formatNumber(1.123456, defaultLocale, '.4')).toEqual('1.1235');
|
||||
expect(formatNumber(12345, DEFAULT_LOCALE_ID)).toEqual('12,345');
|
||||
expect(formatNumber(123, DEFAULT_LOCALE_ID, '.2')).toEqual('123.00');
|
||||
expect(formatNumber(1, DEFAULT_LOCALE_ID, '3.')).toEqual('001');
|
||||
expect(formatNumber(1.1, DEFAULT_LOCALE_ID, '3.4-5')).toEqual('001.1000');
|
||||
expect(formatNumber(1.123456, DEFAULT_LOCALE_ID, '3.4-5')).toEqual('001.12346');
|
||||
expect(formatNumber(1.1234, DEFAULT_LOCALE_ID)).toEqual('1.123');
|
||||
expect(formatNumber(1.123456, DEFAULT_LOCALE_ID, '.2')).toEqual('1.123');
|
||||
expect(formatNumber(1.123456, DEFAULT_LOCALE_ID, '.4')).toEqual('1.1235');
|
||||
});
|
||||
|
||||
it('should throw if minFractionDigits is explicitly higher than maxFractionDigits', () => {
|
||||
expect(() => formatNumber(1.1, defaultLocale, '3.4-2'))
|
||||
expect(() => formatNumber(1.1, DEFAULT_LOCALE_ID, '3.4-2'))
|
||||
.toThrowError(/is higher than the maximum/);
|
||||
});
|
||||
});
|
||||
@ -51,27 +50,27 @@ describe('Format number', () => {
|
||||
describe('Percent', () => {
|
||||
describe('transform', () => {
|
||||
it('should return correct value for numbers', () => {
|
||||
expect(formatPercent(1.23, defaultLocale)).toEqual('123%');
|
||||
expect(formatPercent(1.2, defaultLocale, '.2')).toEqual('120.00%');
|
||||
expect(formatPercent(1.2, defaultLocale, '4.2')).toEqual('0,120.00%');
|
||||
expect(formatPercent(1.23, DEFAULT_LOCALE_ID)).toEqual('123%');
|
||||
expect(formatPercent(1.2, DEFAULT_LOCALE_ID, '.2')).toEqual('120.00%');
|
||||
expect(formatPercent(1.2, DEFAULT_LOCALE_ID, '4.2')).toEqual('0,120.00%');
|
||||
expect(formatPercent(1.2, 'fr', '4.2')).toEqual('0 120,00 %');
|
||||
expect(formatPercent(1.2, 'ar', '4.2')).toEqual('0,120.00%');
|
||||
// see issue #20136
|
||||
expect(formatPercent(0.12345674, defaultLocale, '0.0-10')).toEqual('12.345674%');
|
||||
expect(formatPercent(0, defaultLocale, '0.0-10')).toEqual('0%');
|
||||
expect(formatPercent(0.00, defaultLocale, '0.0-10')).toEqual('0%');
|
||||
expect(formatPercent(1, defaultLocale, '0.0-10')).toEqual('100%');
|
||||
expect(formatPercent(0.1, defaultLocale, '0.0-10')).toEqual('10%');
|
||||
expect(formatPercent(0.12, defaultLocale, '0.0-10')).toEqual('12%');
|
||||
expect(formatPercent(0.123, defaultLocale, '0.0-10')).toEqual('12.3%');
|
||||
expect(formatPercent(12.3456, defaultLocale, '0.0-10')).toEqual('1,234.56%');
|
||||
expect(formatPercent(12.345600, defaultLocale, '0.0-10')).toEqual('1,234.56%');
|
||||
expect(formatPercent(12.345699999, defaultLocale, '0.0-6')).toEqual('1,234.57%');
|
||||
expect(formatPercent(12.345699999, defaultLocale, '0.4-6')).toEqual('1,234.5700%');
|
||||
expect(formatPercent(100, defaultLocale, '0.4-6')).toEqual('10,000.0000%');
|
||||
expect(formatPercent(100, defaultLocale, '0.0-10')).toEqual('10,000%');
|
||||
expect(formatPercent(1.5e2, defaultLocale)).toEqual('15,000%');
|
||||
expect(formatPercent(1e100, defaultLocale)).toEqual('1E+102%');
|
||||
expect(formatPercent(0.12345674, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('12.345674%');
|
||||
expect(formatPercent(0, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('0%');
|
||||
expect(formatPercent(0.00, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('0%');
|
||||
expect(formatPercent(1, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('100%');
|
||||
expect(formatPercent(0.1, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('10%');
|
||||
expect(formatPercent(0.12, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('12%');
|
||||
expect(formatPercent(0.123, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('12.3%');
|
||||
expect(formatPercent(12.3456, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('1,234.56%');
|
||||
expect(formatPercent(12.345600, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('1,234.56%');
|
||||
expect(formatPercent(12.345699999, DEFAULT_LOCALE_ID, '0.0-6')).toEqual('1,234.57%');
|
||||
expect(formatPercent(12.345699999, DEFAULT_LOCALE_ID, '0.4-6')).toEqual('1,234.5700%');
|
||||
expect(formatPercent(100, DEFAULT_LOCALE_ID, '0.4-6')).toEqual('10,000.0000%');
|
||||
expect(formatPercent(100, DEFAULT_LOCALE_ID, '0.0-10')).toEqual('10,000%');
|
||||
expect(formatPercent(1.5e2, DEFAULT_LOCALE_ID)).toEqual('15,000%');
|
||||
expect(formatPercent(1e100, DEFAULT_LOCALE_ID)).toEqual('1E+102%');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -80,16 +79,16 @@ describe('Format number', () => {
|
||||
const defaultCurrencyCode = 'USD';
|
||||
describe('transform', () => {
|
||||
it('should return correct value for numbers', () => {
|
||||
expect(formatCurrency(123, defaultLocale, '$')).toEqual('$123.00');
|
||||
expect(formatCurrency(12, defaultLocale, 'EUR', 'EUR', '.1')).toEqual('EUR12.0');
|
||||
expect(
|
||||
formatCurrency(5.1234, defaultLocale, defaultCurrencyCode, defaultCurrencyCode, '.0-3'))
|
||||
expect(formatCurrency(123, DEFAULT_LOCALE_ID, '$')).toEqual('$123.00');
|
||||
expect(formatCurrency(12, DEFAULT_LOCALE_ID, 'EUR', 'EUR', '.1')).toEqual('EUR12.0');
|
||||
expect(formatCurrency(
|
||||
5.1234, DEFAULT_LOCALE_ID, defaultCurrencyCode, defaultCurrencyCode, '.0-3'))
|
||||
.toEqual('USD5.123');
|
||||
expect(formatCurrency(5.1234, defaultLocale, defaultCurrencyCode)).toEqual('USD5.12');
|
||||
expect(formatCurrency(5.1234, defaultLocale, '$')).toEqual('$5.12');
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'CA$')).toEqual('CA$5.12');
|
||||
expect(formatCurrency(5.1234, defaultLocale, '$')).toEqual('$5.12');
|
||||
expect(formatCurrency(5.1234, defaultLocale, '$', defaultCurrencyCode, '5.2-2'))
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, defaultCurrencyCode)).toEqual('USD5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, '$')).toEqual('$5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'CA$')).toEqual('CA$5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, '$')).toEqual('$5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, '$', defaultCurrencyCode, '5.2-2'))
|
||||
.toEqual('$00,005.12');
|
||||
expect(formatCurrency(5.1234, 'fr', '$', defaultCurrencyCode, '5.2-2'))
|
||||
.toEqual('00 005,12 $');
|
||||
@ -98,20 +97,21 @@ describe('Format number', () => {
|
||||
|
||||
it('should support any currency code name', () => {
|
||||
// currency code is unknown, default formatting options will be used
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'unexisting_ISO_code'))
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'unexisting_ISO_code'))
|
||||
.toEqual('unexisting_ISO_code5.12');
|
||||
// currency code is USD, the pipe will format based on USD but will display "Custom name"
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'Custom name')).toEqual('Custom name5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'Custom name')).toEqual('Custom name5.12');
|
||||
});
|
||||
|
||||
it('should round to the default number of digits if no digitsInfo', () => {
|
||||
// IDR has a default number of digits of 0
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'IDR', 'IDR')).toEqual('IDR5');
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'IDR', 'IDR', '.2')).toEqual('IDR5.12');
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'Custom name', 'IDR')).toEqual('Custom name5');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'IDR', 'IDR')).toEqual('IDR5');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'IDR', 'IDR', '.2')).toEqual('IDR5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'Custom name', 'IDR'))
|
||||
.toEqual('Custom name5');
|
||||
// BHD has a default number of digits of 3
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'BHD', 'BHD')).toEqual('BHD5.123');
|
||||
expect(formatCurrency(5.1234, defaultLocale, 'BHD', 'BHD', '.1-2')).toEqual('BHD5.12');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'BHD', 'BHD')).toEqual('BHD5.123');
|
||||
expect(formatCurrency(5.1234, DEFAULT_LOCALE_ID, 'BHD', 'BHD', '.1-2')).toEqual('BHD5.12');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -11,9 +11,28 @@ const shx = require('shelljs');
|
||||
const os = require('os');
|
||||
const {runCommand, setupTestDirectory} = require('./test_helpers');
|
||||
|
||||
// Nodejs toolchains were included in nodejs rules 0.33.0 so the
|
||||
// repository name for the nodejs toolchain now depends on the platform
|
||||
// being run on. The following function returns the nodejs repository
|
||||
// name of the runtime platform platform. These come from
|
||||
// https://github.com/bazelbuild/rules_nodejs/blob/2a0be492c5d506665798f04673ab1a646c883626/internal/node/node_repositories.bzl#L598.
|
||||
function nodejs_repository() {
|
||||
switch (os.platform()) {
|
||||
case 'darwin':
|
||||
return 'nodejs_darwin_amd64';
|
||||
case 'linux':
|
||||
return 'nodejs_linux_amd64';
|
||||
case 'win32':
|
||||
return 'nodejs_windows_amd64';
|
||||
default:
|
||||
throw 'Platform not supported';
|
||||
}
|
||||
}
|
||||
|
||||
const ngcBin = require.resolve('./ngc_bin');
|
||||
const xi18nBin = require.resolve('./ng_xi18n');
|
||||
const nodeBin = require.resolve(`nodejs/bin/node${(os.platform() === 'win32' ? '.cmd' : '')}`);
|
||||
const nodeBin =
|
||||
require.resolve(`${nodejs_repository()}/bin/node${(os.platform() === 'win32' ? '.cmd' : '')}`);
|
||||
const jasmineBin = require.resolve('npm/node_modules/jasmine/bin/jasmine.js');
|
||||
|
||||
// Prepare the test directory before building the integration test output. This ensures that
|
||||
|
@ -9,10 +9,10 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ClassSymbol, CtorParameter, Declaration, Decorator, Import, TypeScriptReflectionHost, isDecoratorIdentifier, reflectObjectLiteral} from '../../../src/ngtsc/reflection';
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ClassSymbol, CtorParameter, Declaration, Decorator, TypeScriptReflectionHost, isDecoratorIdentifier, reflectObjectLiteral} from '../../../src/ngtsc/reflection';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {BundleProgram} from '../packages/bundle_program';
|
||||
import {findAll, getNameText, hasNameIdentifier, isDefined} from '../utils';
|
||||
import {findAll, getNameText, hasNameIdentifier, isDefined, stripDollarSuffix} from '../utils';
|
||||
|
||||
import {ModuleWithProvidersFunction, NgccReflectionHost, PRE_R3_MARKER, SwitchableVariableDeclaration, isSwitchableVariableDeclaration} from './ngcc_host';
|
||||
|
||||
@ -73,6 +73,14 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
*/
|
||||
protected aliasedClassDeclarations = new Map<ts.Declaration, ts.Identifier>();
|
||||
|
||||
/**
|
||||
* Caches the information of the decorators on a class, as the work involved with extracting
|
||||
* decorators is complex and frequently used.
|
||||
*
|
||||
* This map is lazily populated during the first call to `acquireDecoratorInfo` for a given class.
|
||||
*/
|
||||
protected decoratorCache = new Map<ClassDeclaration, DecoratorInfo>();
|
||||
|
||||
constructor(
|
||||
protected logger: Logger, protected isCore: boolean, checker: ts.TypeChecker,
|
||||
dts?: BundleProgram|null) {
|
||||
@ -247,12 +255,8 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
|
||||
/** Gets all decorators of the given class symbol. */
|
||||
getDecoratorsOfSymbol(symbol: ClassSymbol): Decorator[]|null {
|
||||
const decoratorsProperty = this.getStaticProperty(symbol, DECORATORS);
|
||||
if (decoratorsProperty) {
|
||||
return this.getClassDecoratorsFromStaticProperty(decoratorsProperty);
|
||||
} else {
|
||||
return this.getClassDecoratorsFromHelperCall(symbol);
|
||||
}
|
||||
const {classDecorators} = this.acquireDecoratorInfo(symbol);
|
||||
return classDecorators;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -542,6 +546,72 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
return symbol.exports && symbol.exports.get(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main entry-point for obtaining information on the decorators of a given class. This
|
||||
* information is computed either from static properties if present, or using `tslib.__decorate`
|
||||
* helper calls otherwise. The computed result is cached per class.
|
||||
*
|
||||
* @param classSymbol the class for which decorators should be acquired.
|
||||
* @returns all information of the decorators on the class.
|
||||
*/
|
||||
protected acquireDecoratorInfo(classSymbol: ClassSymbol): DecoratorInfo {
|
||||
if (this.decoratorCache.has(classSymbol.valueDeclaration)) {
|
||||
return this.decoratorCache.get(classSymbol.valueDeclaration) !;
|
||||
}
|
||||
|
||||
// First attempt extracting decorators from static properties.
|
||||
let decoratorInfo = this.computeDecoratorInfoFromStaticProperties(classSymbol);
|
||||
if (decoratorInfo === null) {
|
||||
// If none were present, use the `__decorate` helper calls instead.
|
||||
decoratorInfo = this.computeDecoratorInfoFromHelperCalls(classSymbol);
|
||||
}
|
||||
|
||||
this.decoratorCache.set(classSymbol.valueDeclaration, decoratorInfo);
|
||||
return decoratorInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to compute decorator information from static properties "decorators", "propDecorators"
|
||||
* and "ctorParameters" on the class. If neither of these static properties is present the
|
||||
* library is likely not compiled using tsickle for usage with Closure compiler, in which case
|
||||
* `null` is returned.
|
||||
*
|
||||
* @param classSymbol The class symbol to compute the decorators information for.
|
||||
* @returns All information on the decorators as extracted from static properties, or `null` if
|
||||
* none of the static properties exist.
|
||||
*/
|
||||
protected computeDecoratorInfoFromStaticProperties(classSymbol: ClassSymbol): DecoratorInfo|null {
|
||||
let classDecorators: Decorator[]|null = null;
|
||||
let memberDecorators: Map<string, Decorator[]>|null = null;
|
||||
let constructorParamInfo: ParamInfo[]|null = null;
|
||||
|
||||
const decoratorsProperty = this.getStaticProperty(classSymbol, DECORATORS);
|
||||
if (decoratorsProperty !== undefined) {
|
||||
classDecorators = this.getClassDecoratorsFromStaticProperty(decoratorsProperty);
|
||||
}
|
||||
|
||||
const propDecoratorsProperty = this.getStaticProperty(classSymbol, PROP_DECORATORS);
|
||||
if (propDecoratorsProperty !== undefined) {
|
||||
memberDecorators = this.getMemberDecoratorsFromStaticProperty(propDecoratorsProperty);
|
||||
}
|
||||
|
||||
const constructorParamsProperty = this.getStaticProperty(classSymbol, CONSTRUCTOR_PARAMS);
|
||||
if (constructorParamsProperty !== undefined) {
|
||||
constructorParamInfo = this.getParamInfoFromStaticProperty(constructorParamsProperty);
|
||||
}
|
||||
|
||||
// If none of the static properties were present, no decorator info could be computed.
|
||||
if (classDecorators === null && memberDecorators === null && constructorParamInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
classDecorators,
|
||||
memberDecorators: memberDecorators || new Map<string, Decorator[]>(),
|
||||
constructorParamInfo: constructorParamInfo || [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all class decorators for the given class, where the decorators are declared
|
||||
* via a static property. For example:
|
||||
@ -570,32 +640,6 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all class decorators for the given class, where the decorators are declared
|
||||
* via the `__decorate` helper method. For example:
|
||||
*
|
||||
* ```
|
||||
* let SomeDirective = class SomeDirective {}
|
||||
* SomeDirective = __decorate([
|
||||
* Directive({ selector: '[someDirective]' }),
|
||||
* ], SomeDirective);
|
||||
* ```
|
||||
*
|
||||
* @param symbol the class whose decorators we want to get.
|
||||
* @returns an array of decorators or null if none where found.
|
||||
*/
|
||||
protected getClassDecoratorsFromHelperCall(symbol: ClassSymbol): Decorator[]|null {
|
||||
const decorators: Decorator[] = [];
|
||||
const helperCalls = this.getHelperCallsForClass(symbol, '__decorate');
|
||||
helperCalls.forEach(helperCall => {
|
||||
const {classDecorators} =
|
||||
this.reflectDecoratorsFromHelperCall(helperCall, makeClassTargetFilter(symbol.name));
|
||||
classDecorators.filter(decorator => this.isFromCore(decorator))
|
||||
.forEach(decorator => decorators.push(decorator));
|
||||
});
|
||||
return decorators.length ? decorators : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine a symbol which should be of a class, and return metadata about its members.
|
||||
*
|
||||
@ -606,7 +650,11 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
const members: ClassMember[] = [];
|
||||
|
||||
// The decorators map contains all the properties that are decorated
|
||||
const decoratorsMap = this.getMemberDecorators(symbol);
|
||||
const {memberDecorators} = this.acquireDecoratorInfo(symbol);
|
||||
|
||||
// Make a copy of the decorators as successfully reflected members delete themselves from the
|
||||
// map, so that any leftovers can be easily dealt with.
|
||||
const decoratorsMap = new Map(memberDecorators);
|
||||
|
||||
// The member map contains all the method (instance and static); and any instance properties
|
||||
// that are initialized in the class.
|
||||
@ -675,21 +723,6 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the member decorators for the given class.
|
||||
* @param classSymbol the class whose member decorators we are interested in.
|
||||
* @returns a map whose keys are the name of the members and whose values are collections of
|
||||
* decorators for the given member.
|
||||
*/
|
||||
protected getMemberDecorators(classSymbol: ClassSymbol): Map<string, Decorator[]> {
|
||||
const decoratorsProperty = this.getStaticProperty(classSymbol, PROP_DECORATORS);
|
||||
if (decoratorsProperty) {
|
||||
return this.getMemberDecoratorsFromStaticProperty(decoratorsProperty);
|
||||
} else {
|
||||
return this.getMemberDecoratorsFromHelperCalls(classSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Member decorators may be declared as static properties of the class:
|
||||
*
|
||||
@ -724,7 +757,21 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
}
|
||||
|
||||
/**
|
||||
* Member decorators may be declared via helper call statements.
|
||||
* For a given class symbol, collects all decorator information from tslib helper methods, as
|
||||
* generated by TypeScript into emitted JavaScript files.
|
||||
*
|
||||
* Class decorators are extracted from calls to `tslib.__decorate` that look as follows:
|
||||
*
|
||||
* ```
|
||||
* let SomeDirective = class SomeDirective {}
|
||||
* SomeDirective = __decorate([
|
||||
* Directive({ selector: '[someDirective]' }),
|
||||
* ], SomeDirective);
|
||||
* ```
|
||||
*
|
||||
* The extraction of member decorators is similar, with the distinction that its 2nd and 3rd
|
||||
* argument correspond with a "prototype" target and the name of the member to which the
|
||||
* decorators apply.
|
||||
*
|
||||
* ```
|
||||
* __decorate([
|
||||
@ -733,102 +780,188 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
* ], SomeDirective.prototype, "input1", void 0);
|
||||
* ```
|
||||
*
|
||||
* @param classSymbol the class whose member decorators we are interested in.
|
||||
* @returns a map whose keys are the name of the members and whose values are collections of
|
||||
* decorators for the given member.
|
||||
* @param classSymbol The class symbol for which decorators should be extracted.
|
||||
* @returns All information on the decorators of the class.
|
||||
*/
|
||||
protected getMemberDecoratorsFromHelperCalls(classSymbol: ClassSymbol): Map<string, Decorator[]> {
|
||||
const memberDecoratorMap = new Map<string, Decorator[]>();
|
||||
const helperCalls = this.getHelperCallsForClass(classSymbol, '__decorate');
|
||||
helperCalls.forEach(helperCall => {
|
||||
const {memberDecorators} = this.reflectDecoratorsFromHelperCall(
|
||||
helperCall, makeMemberTargetFilter(classSymbol.name));
|
||||
memberDecorators.forEach((decorators, memberName) => {
|
||||
if (memberName) {
|
||||
const memberDecorators =
|
||||
memberDecoratorMap.has(memberName) ? memberDecoratorMap.get(memberName) ! : [];
|
||||
const coreDecorators = decorators.filter(decorator => this.isFromCore(decorator));
|
||||
memberDecoratorMap.set(memberName, memberDecorators.concat(coreDecorators));
|
||||
}
|
||||
});
|
||||
});
|
||||
return memberDecoratorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract decorator info from `__decorate` helper function calls.
|
||||
* @param helperCall the call to a helper that may contain decorator calls
|
||||
* @param targetFilter a function to filter out targets that we are not interested in.
|
||||
* @returns a mapping from member name to decorators, where the key is either the name of the
|
||||
* member or `undefined` if it refers to decorators on the class as a whole.
|
||||
*/
|
||||
protected reflectDecoratorsFromHelperCall(
|
||||
helperCall: ts.CallExpression, targetFilter: TargetFilter):
|
||||
{classDecorators: Decorator[], memberDecorators: Map<string, Decorator[]>} {
|
||||
const classDecorators: Decorator[] = [];
|
||||
protected computeDecoratorInfoFromHelperCalls(classSymbol: ClassSymbol): DecoratorInfo {
|
||||
let classDecorators: Decorator[]|null = null;
|
||||
const memberDecorators = new Map<string, Decorator[]>();
|
||||
const constructorParamInfo: ParamInfo[] = [];
|
||||
|
||||
// First check that the `target` argument is correct
|
||||
if (targetFilter(helperCall.arguments[1])) {
|
||||
// Grab the `decorators` argument which should be an array of calls
|
||||
const decoratorCalls = helperCall.arguments[0];
|
||||
if (decoratorCalls && ts.isArrayLiteralExpression(decoratorCalls)) {
|
||||
decoratorCalls.elements.forEach(element => {
|
||||
// We only care about those elements that are actual calls
|
||||
if (ts.isCallExpression(element)) {
|
||||
const decorator = this.reflectDecoratorCall(element);
|
||||
if (decorator) {
|
||||
const keyArg = helperCall.arguments[2];
|
||||
const keyName = keyArg && ts.isStringLiteral(keyArg) ? keyArg.text : undefined;
|
||||
if (keyName === undefined) {
|
||||
classDecorators.push(decorator);
|
||||
} else {
|
||||
const decorators =
|
||||
memberDecorators.has(keyName) ? memberDecorators.get(keyName) ! : [];
|
||||
decorators.push(decorator);
|
||||
memberDecorators.set(keyName, decorators);
|
||||
}
|
||||
}
|
||||
const getConstructorParamInfo = (index: number) => {
|
||||
let param = constructorParamInfo[index];
|
||||
if (param === undefined) {
|
||||
param = constructorParamInfo[index] = {decorators: null, typeExpression: null};
|
||||
}
|
||||
return param;
|
||||
};
|
||||
|
||||
// All relevant information can be extracted from calls to `__decorate`, obtain these first.
|
||||
// Note that although the helper calls are retrieved using the class symbol, the result may
|
||||
// contain helper calls corresponding with unrelated classes. Therefore, each helper call still
|
||||
// has to be checked to actually correspond with the class symbol.
|
||||
const helperCalls = this.getHelperCallsForClass(classSymbol, '__decorate');
|
||||
|
||||
for (const helperCall of helperCalls) {
|
||||
if (isClassDecorateCall(helperCall, classSymbol.name)) {
|
||||
// This `__decorate` call is targeting the class itself.
|
||||
const helperArgs = helperCall.arguments[0];
|
||||
|
||||
for (const element of helperArgs.elements) {
|
||||
const entry = this.reflectDecorateHelperEntry(element);
|
||||
if (entry === null) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
if (entry.type === 'decorator') {
|
||||
// The helper arg was reflected to represent an actual decorator
|
||||
if (this.isFromCore(entry.decorator)) {
|
||||
(classDecorators || (classDecorators = [])).push(entry.decorator);
|
||||
}
|
||||
} else if (entry.type === 'param:decorators') {
|
||||
// The helper arg represents a decorator for a parameter. Since it's applied to the
|
||||
// class, it corresponds with a constructor parameter of the class.
|
||||
const param = getConstructorParamInfo(entry.index);
|
||||
(param.decorators || (param.decorators = [])).push(entry.decorator);
|
||||
} else if (entry.type === 'params') {
|
||||
// The helper arg represents the types of the parameters. Since it's applied to the
|
||||
// class, it corresponds with the constructor parameters of the class.
|
||||
entry.types.forEach(
|
||||
(type, index) => getConstructorParamInfo(index).typeExpression = type);
|
||||
}
|
||||
}
|
||||
} else if (isMemberDecorateCall(helperCall, classSymbol.name)) {
|
||||
// The `__decorate` call is targeting a member of the class
|
||||
const helperArgs = helperCall.arguments[0];
|
||||
const memberName = helperCall.arguments[2].text;
|
||||
|
||||
for (const element of helperArgs.elements) {
|
||||
const entry = this.reflectDecorateHelperEntry(element);
|
||||
if (entry === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.type === 'decorator') {
|
||||
// The helper arg was reflected to represent an actual decorator.
|
||||
if (this.isFromCore(entry.decorator)) {
|
||||
const decorators =
|
||||
memberDecorators.has(memberName) ? memberDecorators.get(memberName) ! : [];
|
||||
decorators.push(entry.decorator);
|
||||
memberDecorators.set(memberName, decorators);
|
||||
}
|
||||
} else {
|
||||
// Information on decorated parameters is not interesting for ngcc, so it's ignored.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {classDecorators, memberDecorators};
|
||||
|
||||
return {classDecorators, memberDecorators, constructorParamInfo};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the decorator information from a call to a decorator as a function.
|
||||
* This happens when the decorators has been used in a `__decorate` helper call.
|
||||
* For example:
|
||||
* Extract the details of an entry within a `__decorate` helper call. For example, given the
|
||||
* following code:
|
||||
*
|
||||
* ```
|
||||
* __decorate([
|
||||
* Directive({ selector: '[someDirective]' }),
|
||||
* tslib_1.__param(2, Inject(INJECTED_TOKEN)),
|
||||
* tslib_1.__metadata("design:paramtypes", [ViewContainerRef, TemplateRef, String])
|
||||
* ], SomeDirective);
|
||||
* ```
|
||||
*
|
||||
* Here the `Directive` decorator is decorating `SomeDirective` and the options for
|
||||
* the decorator are passed as arguments to the `Directive()` call.
|
||||
* it can be seen that there are calls to regular decorators (the `Directive`) and calls into
|
||||
* `tslib` functions which have been inserted by TypeScript. Therefore, this function classifies
|
||||
* a call to correspond with
|
||||
* 1. a real decorator like `Directive` above, or
|
||||
* 2. a decorated parameter, corresponding with `__param` calls from `tslib`, or
|
||||
* 3. the type information of parameters, corresponding with `__metadata` call from `tslib`
|
||||
*
|
||||
* @param call the call to the decorator.
|
||||
* @returns a decorator containing the reflected information, or null if the call
|
||||
* is not a valid decorator call.
|
||||
* @param expression the expression that needs to be reflected into a `DecorateHelperEntry`
|
||||
* @returns an object that indicates which of the three categories the call represents, together
|
||||
* with the reflected information of the call, or null if the call is not a valid decorate call.
|
||||
*/
|
||||
protected reflectDecoratorCall(call: ts.CallExpression): Decorator|null {
|
||||
const decoratorExpression = call.expression;
|
||||
if (isDecoratorIdentifier(decoratorExpression)) {
|
||||
// We found a decorator!
|
||||
const decoratorIdentifier =
|
||||
ts.isIdentifier(decoratorExpression) ? decoratorExpression : decoratorExpression.name;
|
||||
protected reflectDecorateHelperEntry(expression: ts.Expression): DecorateHelperEntry|null {
|
||||
// We only care about those elements that are actual calls
|
||||
if (!ts.isCallExpression(expression)) {
|
||||
return null;
|
||||
}
|
||||
const call = expression;
|
||||
|
||||
const helperName = getCalleeName(call);
|
||||
if (helperName === '__metadata') {
|
||||
// This is a `tslib.__metadata` call, reflect to arguments into a `ParameterTypes` object
|
||||
// if the metadata key is "design:paramtypes".
|
||||
const key = call.arguments[0];
|
||||
if (key === undefined || !ts.isStringLiteral(key) || key.text !== 'design:paramtypes') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const value = call.arguments[1];
|
||||
if (value === undefined || !ts.isArrayLiteralExpression(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
name: decoratorIdentifier.text,
|
||||
identifier: decoratorIdentifier,
|
||||
import: this.getImportOfIdentifier(decoratorIdentifier),
|
||||
node: call,
|
||||
args: Array.from(call.arguments)
|
||||
type: 'params',
|
||||
types: Array.from(value.elements),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
|
||||
if (helperName === '__param') {
|
||||
// This is a `tslib.__param` call that is reflected into a `ParameterDecorators` object.
|
||||
const indexArg = call.arguments[0];
|
||||
const index = indexArg && ts.isNumericLiteral(indexArg) ? parseInt(indexArg.text, 10) : NaN;
|
||||
if (isNaN(index)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decoratorCall = call.arguments[1];
|
||||
if (decoratorCall === undefined || !ts.isCallExpression(decoratorCall)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decorator = this.reflectDecoratorCall(decoratorCall);
|
||||
if (decorator === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'param:decorators',
|
||||
index,
|
||||
decorator,
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise attempt to reflect it as a regular decorator.
|
||||
const decorator = this.reflectDecoratorCall(call);
|
||||
if (decorator === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
type: 'decorator',
|
||||
decorator,
|
||||
};
|
||||
}
|
||||
|
||||
protected reflectDecoratorCall(call: ts.CallExpression): Decorator|null {
|
||||
const decoratorExpression = call.expression;
|
||||
if (!isDecoratorIdentifier(decoratorExpression)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We found a decorator!
|
||||
const decoratorIdentifier =
|
||||
ts.isIdentifier(decoratorExpression) ? decoratorExpression : decoratorExpression.name;
|
||||
|
||||
return {
|
||||
name: decoratorIdentifier.text,
|
||||
identifier: decoratorExpression,
|
||||
import: this.getImportOfIdentifier(decoratorIdentifier),
|
||||
node: call,
|
||||
args: Array.from(call.arguments),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1070,14 +1203,11 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
*/
|
||||
protected getConstructorParamInfo(
|
||||
classSymbol: ClassSymbol, parameterNodes: ts.ParameterDeclaration[]): CtorParameter[] {
|
||||
const paramsProperty = this.getStaticProperty(classSymbol, CONSTRUCTOR_PARAMS);
|
||||
const paramInfo: ParamInfo[]|null = paramsProperty ?
|
||||
this.getParamInfoFromStaticProperty(paramsProperty) :
|
||||
this.getParamInfoFromHelperCall(classSymbol, parameterNodes);
|
||||
const {constructorParamInfo} = this.acquireDecoratorInfo(classSymbol);
|
||||
|
||||
return parameterNodes.map((node, index) => {
|
||||
const {decorators, typeExpression} = paramInfo && paramInfo[index] ?
|
||||
paramInfo[index] :
|
||||
const {decorators, typeExpression} = constructorParamInfo[index] ?
|
||||
constructorParamInfo[index] :
|
||||
{decorators: null, typeExpression: null};
|
||||
const nameNode = node.name;
|
||||
return {
|
||||
@ -1153,58 +1283,6 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parameter type and decorators for a class where the information is stored via
|
||||
* calls to `__decorate` helpers.
|
||||
*
|
||||
* Reflect over the helpers to find the decorators and types about each of
|
||||
* the class's constructor parameters.
|
||||
*
|
||||
* @param classSymbol the class whose parameter info we want to get.
|
||||
* @param parameterNodes the array of TypeScript parameter nodes for this class's constructor.
|
||||
* @returns an array of objects containing the type and decorators for each parameter.
|
||||
*/
|
||||
protected getParamInfoFromHelperCall(
|
||||
classSymbol: ClassSymbol, parameterNodes: ts.ParameterDeclaration[]): ParamInfo[] {
|
||||
const parameters: ParamInfo[] =
|
||||
parameterNodes.map(() => ({typeExpression: null, decorators: null}));
|
||||
const helperCalls = this.getHelperCallsForClass(classSymbol, '__decorate');
|
||||
helperCalls.forEach(helperCall => {
|
||||
const {classDecorators} =
|
||||
this.reflectDecoratorsFromHelperCall(helperCall, makeClassTargetFilter(classSymbol.name));
|
||||
classDecorators.forEach(call => {
|
||||
switch (call.name) {
|
||||
case '__metadata':
|
||||
const metadataArg = call.args && call.args[0];
|
||||
const typesArg = call.args && call.args[1];
|
||||
const isParamTypeDecorator = metadataArg && ts.isStringLiteral(metadataArg) &&
|
||||
metadataArg.text === 'design:paramtypes';
|
||||
const types = typesArg && ts.isArrayLiteralExpression(typesArg) && typesArg.elements;
|
||||
if (isParamTypeDecorator && types) {
|
||||
types.forEach((type, index) => parameters[index].typeExpression = type);
|
||||
}
|
||||
break;
|
||||
case '__param':
|
||||
const paramIndexArg = call.args && call.args[0];
|
||||
const decoratorCallArg = call.args && call.args[1];
|
||||
const paramIndex = paramIndexArg && ts.isNumericLiteral(paramIndexArg) ?
|
||||
parseInt(paramIndexArg.text, 10) :
|
||||
NaN;
|
||||
const decorator = decoratorCallArg && ts.isCallExpression(decoratorCallArg) ?
|
||||
this.reflectDecoratorCall(decoratorCallArg) :
|
||||
null;
|
||||
if (!isNaN(paramIndex) && decorator) {
|
||||
const decorators = parameters[paramIndex].decorators =
|
||||
parameters[paramIndex].decorators || [];
|
||||
decorators.push(decorator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search statements related to the given class for calls to the specified helper.
|
||||
* @param classSymbol the class whose helper calls we are interested in.
|
||||
@ -1377,6 +1455,72 @@ export type ParamInfo = {
|
||||
typeExpression: ts.Expression | null
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a call to `tslib.__metadata` as present in `tslib.__decorate` calls. This is a
|
||||
* synthetic decorator inserted by TypeScript that contains reflection information about the
|
||||
* target of the decorator, i.e. the class or property.
|
||||
*/
|
||||
export interface ParameterTypes {
|
||||
type: 'params';
|
||||
types: ts.Expression[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a call to `tslib.__param` as present in `tslib.__decorate` calls. This contains
|
||||
* information on any decorators were applied to a certain parameter.
|
||||
*/
|
||||
export interface ParameterDecorators {
|
||||
type: 'param:decorators';
|
||||
index: number;
|
||||
decorator: Decorator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a call to a decorator as it was present in the original source code, as present in
|
||||
* `tslib.__decorate` calls.
|
||||
*/
|
||||
export interface DecoratorCall {
|
||||
type: 'decorator';
|
||||
decorator: Decorator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the different kinds of decorate helpers that may be present as first argument to
|
||||
* `tslib.__decorate`, as follows:
|
||||
*
|
||||
* ```
|
||||
* __decorate([
|
||||
* Directive({ selector: '[someDirective]' }),
|
||||
* tslib_1.__param(2, Inject(INJECTED_TOKEN)),
|
||||
* tslib_1.__metadata("design:paramtypes", [ViewContainerRef, TemplateRef, String])
|
||||
* ], SomeDirective);
|
||||
* ```
|
||||
*/
|
||||
export type DecorateHelperEntry = ParameterTypes | ParameterDecorators | DecoratorCall;
|
||||
|
||||
/**
|
||||
* The recorded decorator information of a single class. This information is cached in the host.
|
||||
*/
|
||||
interface DecoratorInfo {
|
||||
/**
|
||||
* All decorators that were present on the class. If no decorators were present, this is `null`
|
||||
*/
|
||||
classDecorators: Decorator[]|null;
|
||||
|
||||
/**
|
||||
* All decorators per member of the class they were present on.
|
||||
*/
|
||||
memberDecorators: Map<string, Decorator[]>;
|
||||
|
||||
/**
|
||||
* Represents the constructor parameter information, such as the type of a parameter and all
|
||||
* decorators for a certain parameter. Indices in this array correspond with the parameter's index
|
||||
* in the constructor. Note that this array may be sparse, i.e. certain constructor parameters may
|
||||
* not have any info recorded.
|
||||
*/
|
||||
constructorParamInfo: ParamInfo[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A statement node that represents an assignment.
|
||||
*/
|
||||
@ -1397,27 +1541,55 @@ export function isAssignment(node: ts.Node): node is ts.AssignmentExpression<ts.
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of a function that can be used to filter out helpers based on their target.
|
||||
* This is used in `reflectDecoratorsFromHelperCall()`.
|
||||
* Tests whether the provided call expression targets a class, by verifying its arguments are
|
||||
* according to the following form:
|
||||
*
|
||||
* ```
|
||||
* __decorate([], SomeDirective);
|
||||
* ```
|
||||
*
|
||||
* @param call the call expression that is tested to represent a class decorator call.
|
||||
* @param className the name of the class that the call needs to correspond with.
|
||||
*/
|
||||
export type TargetFilter = (target: ts.Expression) => boolean;
|
||||
export function isClassDecorateCall(call: ts.CallExpression, className: string):
|
||||
call is ts.CallExpression&{arguments: [ts.ArrayLiteralExpression, ts.Expression]} {
|
||||
const helperArgs = call.arguments[0];
|
||||
if (helperArgs === undefined || !ts.isArrayLiteralExpression(helperArgs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function that tests whether the given expression is a class target.
|
||||
* @param className the name of the class we want to target.
|
||||
*/
|
||||
export function makeClassTargetFilter(className: string): TargetFilter {
|
||||
return (target: ts.Expression): boolean => ts.isIdentifier(target) && target.text === className;
|
||||
const target = call.arguments[1];
|
||||
return target !== undefined && ts.isIdentifier(target) && target.text === className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function that tests whether the given expression is a class member target.
|
||||
* @param className the name of the class we want to target.
|
||||
* Tests whether the provided call expression targets a member of the class, by verifying its
|
||||
* arguments are according to the following form:
|
||||
*
|
||||
* ```
|
||||
* __decorate([], SomeDirective.prototype, "member", void 0);
|
||||
* ```
|
||||
*
|
||||
* @param call the call expression that is tested to represent a member decorator call.
|
||||
* @param className the name of the class that the call needs to correspond with.
|
||||
*/
|
||||
export function makeMemberTargetFilter(className: string): TargetFilter {
|
||||
return (target: ts.Expression): boolean => ts.isPropertyAccessExpression(target) &&
|
||||
ts.isIdentifier(target.expression) && target.expression.text === className &&
|
||||
target.name.text === 'prototype';
|
||||
export function isMemberDecorateCall(call: ts.CallExpression, className: string):
|
||||
call is ts.CallExpression&
|
||||
{arguments: [ts.ArrayLiteralExpression, ts.StringLiteral, ts.StringLiteral]} {
|
||||
const helperArgs = call.arguments[0];
|
||||
if (helperArgs === undefined || !ts.isArrayLiteralExpression(helperArgs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const target = call.arguments[1];
|
||||
if (target === undefined || !ts.isPropertyAccessExpression(target) ||
|
||||
!ts.isIdentifier(target.expression) || target.expression.text !== className ||
|
||||
target.name.text !== 'prototype') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const memberName = call.arguments[2];
|
||||
return memberName !== undefined && ts.isStringLiteral(memberName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1435,10 +1607,10 @@ export function getPropertyValueFromSymbol(propSymbol: ts.Symbol): ts.Expression
|
||||
*/
|
||||
function getCalleeName(call: ts.CallExpression): string|null {
|
||||
if (ts.isIdentifier(call.expression)) {
|
||||
return call.expression.text;
|
||||
return stripDollarSuffix(call.expression.text);
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(call.expression)) {
|
||||
return call.expression.name.text;
|
||||
return stripDollarSuffix(call.expression.name.text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import * as ts from 'typescript';
|
||||
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ClassSymbol, CtorParameter, Declaration, Decorator, FunctionDefinition, Parameter, TsHelperFn, isNamedVariableDeclaration, reflectObjectLiteral} from '../../../src/ngtsc/reflection';
|
||||
import {isFromDtsFile} from '../../../src/ngtsc/util/src/typescript';
|
||||
import {getNameText, hasNameIdentifier} from '../utils';
|
||||
import {getNameText, hasNameIdentifier, stripDollarSuffix} from '../utils';
|
||||
|
||||
import {Esm2015ReflectionHost, ParamInfo, getPropertyValueFromSymbol, isAssignmentStatement} from './esm2015_host';
|
||||
|
||||
@ -659,7 +659,9 @@ function reflectArrayElement(element: ts.Expression) {
|
||||
* helper.
|
||||
*/
|
||||
function getTsHelperFn(node: ts.NamedDeclaration): TsHelperFn|null {
|
||||
const name = node.name !== undefined && ts.isIdentifier(node.name) && node.name.text;
|
||||
const name = node.name !== undefined && ts.isIdentifier(node.name) ?
|
||||
stripDollarSuffix(node.name.text) :
|
||||
null;
|
||||
|
||||
if (name === '__spread') {
|
||||
return TsHelperFn.Spread;
|
||||
|
@ -82,3 +82,14 @@ export function resolveFileWithPostfixes(
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An identifier may become repeated when bundling multiple source files into a single bundle, so
|
||||
* bundlers have a strategy of suffixing non-unique identifiers with a suffix like $2. This function
|
||||
* strips off such suffixes, so that ngcc deals with the canonical name of an identifier.
|
||||
* @param value The value to strip any suffix of, if applicable.
|
||||
* @returns The canonical representation of the value, without any suffix.
|
||||
*/
|
||||
export function stripDollarSuffix(value: string): string {
|
||||
return value.replace(/\$\d+$/, '');
|
||||
}
|
||||
|
@ -78,6 +78,22 @@ export function convertToDirectTsLibImport(filesystem: TestFile[]) {
|
||||
});
|
||||
}
|
||||
|
||||
export function convertToInlineTsLib(filesystem: TestFile[], suffix: string = '') {
|
||||
return filesystem.map(file => {
|
||||
const contents = file.contents
|
||||
.replace(`import * as tslib_1 from 'tslib';`, `
|
||||
var __decorate${suffix} = null;
|
||||
var __metadata${suffix} = null;
|
||||
var __read${suffix} = null;
|
||||
var __values${suffix} = null;
|
||||
var __param${suffix} = null;
|
||||
var __extends${suffix} = null;
|
||||
var __assign${suffix} = null;
|
||||
`).replace(/tslib_1\.([_a-z]+)/gi, '$1' + suffix.replace('$', '$$'));
|
||||
return {...file, contents};
|
||||
});
|
||||
}
|
||||
|
||||
export function getRootFiles(testFiles: TestFile[]): AbsoluteFsPath[] {
|
||||
return testFiles.filter(f => f.isRoot !== false).map(f => absoluteFrom(f.name));
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ exports.OtherDirective = OtherDirective;
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('core.Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
|
@ -951,23 +951,6 @@ exports.ExternalModule = ExternalModule;
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const mockImportInfo: Import = {from: '@angular/core', name: 'Directive'};
|
||||
const spy = spyOn(host, 'getImportOfIdentifier').and.returnValue(mockImportInfo);
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
});
|
||||
|
||||
describe('(returned decorators `args`)', () => {
|
||||
it('should be an empty array if decorator has no `args` property', () => {
|
||||
loadTestFiles([INVALID_DECORATOR_ARGS_FILE]);
|
||||
@ -1185,22 +1168,17 @@ exports.ExternalModule = ExternalModule;
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const mockImportInfo = { name: 'mock', from: '@angular/core' } as Import;
|
||||
const spy = spyOn(host, 'getImportOfIdentifier').and.returnValue(mockImportInfo);
|
||||
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned prop decorators `args`)', () => {
|
||||
@ -1430,24 +1408,19 @@ exports.ExternalModule = ExternalModule;
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const mockImportInfo: Import = {from: '@angular/core', name: 'Directive'};
|
||||
const spy = spyOn(CommonJsReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
const parameters = host.getConstructorParameters(classNode);
|
||||
const decorators = parameters ![2].decorators !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Inject');
|
||||
expect(decorators[0].name).toBe('Inject');
|
||||
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -15,7 +15,7 @@ import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
import {convertToDirectTsLibImport, makeTestBundleProgram} from '../helpers/utils';
|
||||
import {convertToDirectTsLibImport, convertToInlineTsLib, makeTestBundleProgram} from '../helpers/utils';
|
||||
|
||||
import {expectTypeValueReferencesForParameters} from './util';
|
||||
|
||||
@ -111,14 +111,18 @@ runInEachFileSystem(() => {
|
||||
];
|
||||
|
||||
const DIRECT_IMPORT_FILES = convertToDirectTsLibImport(NAMESPACED_IMPORT_FILES);
|
||||
const INLINE_FILES = convertToInlineTsLib(NAMESPACED_IMPORT_FILES);
|
||||
const INLINE_SUFFIXED_FILES = convertToInlineTsLib(NAMESPACED_IMPORT_FILES, '$2');
|
||||
|
||||
FILES = {
|
||||
'namespaced': NAMESPACED_IMPORT_FILES,
|
||||
'direct import': DIRECT_IMPORT_FILES,
|
||||
'inline': INLINE_FILES,
|
||||
'inline suffixed': INLINE_SUFFIXED_FILES,
|
||||
};
|
||||
});
|
||||
|
||||
['namespaced', 'direct import'].forEach(label => {
|
||||
['namespaced', 'direct import', 'inline', 'inline suffixed'].forEach(label => {
|
||||
describe(`[${label}]`, () => {
|
||||
beforeEach(() => {
|
||||
const fs = getFileSystem();
|
||||
@ -141,35 +145,13 @@ runInEachFileSystem(() => {
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const spy =
|
||||
spyOn(Esm2015ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.callFake(
|
||||
(identifier: ts.Identifier) => identifier.getText() === 'Directive' ?
|
||||
{from: '@angular/core', name: 'Directive'} :
|
||||
{});
|
||||
|
||||
const {program} = makeTestBundleProgram(_('/some_directive.js'));
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, _('/some_directive.js'), 'SomeDirective', isNamedVariableDeclaration);
|
||||
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||
|
||||
const identifiers = spy.calls.all().map(call => (call.args[0] as ts.Identifier).text);
|
||||
expect(identifiers.some(identifier => identifier === 'Directive')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support decorators being used inside @angular/core', () => {
|
||||
const {program} =
|
||||
makeTestBundleProgram(_('/node_modules/@angular/core/some_directive.js'));
|
||||
@ -185,6 +167,7 @@ runInEachFileSystem(() => {
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
@ -272,21 +255,6 @@ runInEachFileSystem(() => {
|
||||
expect(staticProperty.value !.getText()).toEqual(`'static'`);
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const spy =
|
||||
spyOn(Esm2015ReflectionHost.prototype, 'getImportOfIdentifier').and.returnValue({});
|
||||
|
||||
const {program} = makeTestBundleProgram(_('/some_directive.js'));
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, _('/some_directive.js'), 'SomeDirective', isNamedVariableDeclaration);
|
||||
|
||||
host.getMembersOfClass(classNode);
|
||||
const identifiers = spy.calls.all().map(call => (call.args[0] as ts.Identifier).text);
|
||||
expect(identifiers.some(identifier => identifier === 'Input')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support decorators being used inside @angular/core', () => {
|
||||
const {program} =
|
||||
makeTestBundleProgram(_('/node_modules/@angular/core/some_directive.js'));
|
||||
|
@ -763,11 +763,7 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const mockImportInfo = { from: '@angular/core' } as Import;
|
||||
const spy = spyOn(Esm2015ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
@ -776,10 +772,7 @@ runInEachFileSystem(() => {
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned decorators `args`)', () => {
|
||||
@ -839,11 +832,13 @@ runInEachFileSystem(() => {
|
||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input1.isStatic).toEqual(false);
|
||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
expect(input1.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'});
|
||||
|
||||
const input2 = members.find(member => member.name === 'input2') !;
|
||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input2.isStatic).toEqual(false);
|
||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
expect(input2.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
expect(input2.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'});
|
||||
});
|
||||
|
||||
it('should find non decorated properties on a class', () => {
|
||||
@ -991,35 +986,6 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
let callCount = 0;
|
||||
const spy =
|
||||
spyOn(Esm2015ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => {
|
||||
callCount++;
|
||||
return {name: `name${callCount}`, from: '@angular/core'};
|
||||
});
|
||||
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration);
|
||||
const members = host.getMembersOfClass(classNode);
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(spy.calls.allArgs().map(arg => arg[0].getText())).toEqual([
|
||||
'Input',
|
||||
'Input',
|
||||
'HostBinding',
|
||||
'Input',
|
||||
'HostListener',
|
||||
]);
|
||||
|
||||
const member = members.find(member => member.name === 'input1') !;
|
||||
expect(member.decorators !.length).toBe(1);
|
||||
expect(member.decorators ![0].import).toEqual({name: 'name1', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned prop decorators `args`)', () => {
|
||||
it('should be an empty array if prop decorator has no `args` property', () => {
|
||||
loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]);
|
||||
@ -1311,11 +1277,7 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const mockImportInfo: Import = {name: 'mock', from: '@angular/core'};
|
||||
const spy = spyOn(Esm2015ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
@ -1325,10 +1287,7 @@ runInEachFileSystem(() => {
|
||||
const decorators = parameters[2].decorators !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Inject');
|
||||
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -14,7 +14,7 @@ import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
||||
import {Esm5ReflectionHost} from '../../src/host/esm5_host';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
import {convertToDirectTsLibImport, makeTestBundleProgram} from '../helpers/utils';
|
||||
import {convertToDirectTsLibImport, convertToInlineTsLib, makeTestBundleProgram} from '../helpers/utils';
|
||||
|
||||
import {expectTypeValueReferencesForParameters} from './util';
|
||||
|
||||
@ -132,14 +132,18 @@ export { SomeDirective };
|
||||
];
|
||||
|
||||
const DIRECT_IMPORT_FILES = convertToDirectTsLibImport(NAMESPACED_IMPORT_FILES);
|
||||
const INLINE_FILES = convertToInlineTsLib(NAMESPACED_IMPORT_FILES);
|
||||
const INLINE_SUFFIXED_FILES = convertToInlineTsLib(NAMESPACED_IMPORT_FILES, '$2');
|
||||
|
||||
FILES = {
|
||||
'namespaced': NAMESPACED_IMPORT_FILES,
|
||||
'direct import': DIRECT_IMPORT_FILES,
|
||||
'inline': INLINE_FILES,
|
||||
'inline suffixed': INLINE_SUFFIXED_FILES,
|
||||
};
|
||||
});
|
||||
|
||||
['namespaced', 'direct import'].forEach(label => {
|
||||
['namespaced', 'direct import', 'inline', 'inline suffixed'].forEach(label => {
|
||||
describe(`[${label}]`, () => {
|
||||
beforeEach(() => {
|
||||
const fs = getFileSystem();
|
||||
@ -161,34 +165,13 @@ export { SomeDirective };
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const spy =
|
||||
spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.callFake(
|
||||
(identifier: ts.Identifier) => identifier.getText() === 'Directive' ?
|
||||
{from: '@angular/core', name: 'Directive'} :
|
||||
{});
|
||||
|
||||
const {program} = makeTestBundleProgram(_('/some_directive.js'));
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, _('/some_directive.js'), 'SomeDirective', isNamedVariableDeclaration);
|
||||
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||
|
||||
const identifiers = spy.calls.all().map(call => (call.args[0] as ts.Identifier).text);
|
||||
expect(identifiers.some(identifier => identifier === 'Directive')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support decorators being used inside @angular/core', () => {
|
||||
const {program} =
|
||||
makeTestBundleProgram(_('/node_modules/@angular/core/some_directive.js'));
|
||||
@ -203,6 +186,7 @@ export { SomeDirective };
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
@ -270,20 +254,6 @@ export { SomeDirective };
|
||||
expect(staticProperty.value !.getText()).toEqual(`'static'`);
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const spy =
|
||||
spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier').and.returnValue({});
|
||||
|
||||
const {program} = makeTestBundleProgram(_('/some_directive.js'));
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, _('/some_directive.js'), 'SomeDirective', isNamedVariableDeclaration);
|
||||
|
||||
host.getMembersOfClass(classNode);
|
||||
const identifiers = spy.calls.all().map(call => (call.args[0] as ts.Identifier).text);
|
||||
expect(identifiers.some(identifier => identifier === 'Input')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support decorators being used inside @angular/core', () => {
|
||||
const {program} =
|
||||
makeTestBundleProgram(_('/node_modules/@angular/core/some_directive.js'));
|
||||
@ -319,12 +289,7 @@ export { SomeDirective };
|
||||
});
|
||||
|
||||
describe('(returned parameters `decorators`)', () => {
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const mockImportInfo = {} as Import;
|
||||
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
|
||||
it('should have import information on decorators', () => {
|
||||
const {program} = makeTestBundleProgram(_('/some_directive.js'));
|
||||
const host =
|
||||
new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
@ -334,10 +299,7 @@ export { SomeDirective };
|
||||
const decorators = parameters ![2].decorators !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Inject');
|
||||
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -942,11 +942,7 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const mockImportInfo = { name: 'mock', from: '@angular/core' } as Import;
|
||||
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
@ -955,10 +951,7 @@ runInEachFileSystem(() => {
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned decorators `args`)', () => {
|
||||
@ -1019,11 +1012,13 @@ runInEachFileSystem(() => {
|
||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input1.isStatic).toEqual(false);
|
||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
expect(input1.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'});
|
||||
|
||||
const input2 = members.find(member => member.name === 'input2') !;
|
||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input2.isStatic).toEqual(false);
|
||||
expect(input2.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
expect(input2.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'});
|
||||
});
|
||||
|
||||
it('should find decorated members on a class', () => {
|
||||
@ -1232,30 +1227,6 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
let callCount = 0;
|
||||
const spy =
|
||||
spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => {
|
||||
callCount++;
|
||||
return {name: `name${callCount}`, from: `@angular/core`};
|
||||
});
|
||||
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const members = host.getMembersOfClass(classNode);
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
spy.calls.allArgs().forEach(arg => expect(arg[0].getText()).toEqual('Input'));
|
||||
|
||||
const index = members.findIndex(member => member.name === 'input1');
|
||||
expect(members[index].decorators !.length).toBe(1);
|
||||
expect(members[index].decorators ![0].import)
|
||||
.toEqual({name: 'name1', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned prop decorators `args`)', () => {
|
||||
it('should be an empty array if prop decorator has no `args` property', () => {
|
||||
loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]);
|
||||
@ -1466,11 +1437,7 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
const mockImportInfo = { name: 'mock', from: '@angulare/core' } as Import;
|
||||
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
|
||||
.and.returnValue(mockImportInfo);
|
||||
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
@ -1480,10 +1447,7 @@ runInEachFileSystem(() => {
|
||||
const decorators = parameters ![2].decorators !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Inject');
|
||||
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1705,6 +1669,30 @@ runInEachFileSystem(() => {
|
||||
expect(definition.helper).toBe(TsHelperFn.Spread);
|
||||
expect(definition.parameters.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should recognize TypeScript __spread helper function implementation when suffixed',
|
||||
() => {
|
||||
const file: TestFile = {
|
||||
name: _('/implementation.js'),
|
||||
contents: `
|
||||
var __spread$2 = (this && this.__spread$2) || function () {
|
||||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
|
||||
return ar;
|
||||
};`,
|
||||
};
|
||||
loadTestFiles([file]);
|
||||
const {program} = makeTestBundleProgram(file.name);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
|
||||
const node =
|
||||
getDeclaration(program, file.name, '__spread$2', ts.isVariableDeclaration) !;
|
||||
|
||||
const definition = host.getDefinitionOfFunction(node) !;
|
||||
expect(definition.node).toBe(node);
|
||||
expect(definition.body).toBeNull();
|
||||
expect(definition.helper).toBe(TsHelperFn.Spread);
|
||||
expect(definition.parameters.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getImportOfIdentifier()', () => {
|
||||
|
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||
import {ClassMemberKind, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||
import {loadTestFiles} from '../../../test/helpers';
|
||||
import {UmdReflectionHost} from '../../src/host/umd_host';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
import {makeTestBundleProgram} from '../helpers/utils';
|
||||
|
||||
import {expectTypeValueReferencesForParameters} from './util';
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('UmdReflectionHost [import helper style]', () => {
|
||||
let _: typeof absoluteFrom;
|
||||
|
||||
let SOME_DIRECTIVE_FILE: TestFile;
|
||||
|
||||
beforeEach(() => {
|
||||
_ = absoluteFrom;
|
||||
|
||||
SOME_DIRECTIVE_FILE = {
|
||||
name: _('/some_directive.umd.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) :
|
||||
typeof define === 'function' && define.amd ? define('some_directive', ['exports', '@angular/core'], factory) :
|
||||
(factory(global.some_directive,global.ng.core));
|
||||
}(this, (function (exports,core) { 'use strict';
|
||||
|
||||
var __decorate = null;
|
||||
var __metadata = null;
|
||||
var __param = null;
|
||||
|
||||
var INJECTED_TOKEN = new InjectionToken('injected');
|
||||
var ViewContainerRef = {};
|
||||
var TemplateRef = {};
|
||||
|
||||
var SomeDirective = (function() {
|
||||
function SomeDirective(_viewContainer, _template, injected) {}
|
||||
__decorate([
|
||||
core.Input(),
|
||||
__metadata("design:type", String)
|
||||
], SomeDirective.prototype, "input1", void 0);
|
||||
__decorate([
|
||||
core.Input(),
|
||||
__metadata("design:type", Number)
|
||||
], SomeDirective.prototype, "input2", void 0);
|
||||
SomeDirective = __decorate([
|
||||
core.Directive({ selector: '[someDirective]' }),
|
||||
__param(2, core.Inject(INJECTED_TOKEN)),
|
||||
__metadata("design:paramtypes", [ViewContainerRef, TemplateRef, String])
|
||||
], SomeDirective);
|
||||
return SomeDirective;
|
||||
}());
|
||||
exports.SomeDirective = SomeDirective;
|
||||
})));`,
|
||||
};
|
||||
});
|
||||
|
||||
describe('getDecoratorsOfDeclaration()', () => {
|
||||
it('should find the decorators on a class', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators).toBeDefined();
|
||||
expect(decorators.length).toEqual(1);
|
||||
|
||||
const decorator = decorators[0];
|
||||
expect(decorator.name).toEqual('Directive');
|
||||
expect(decorator.identifier.getText()).toEqual('core.Directive');
|
||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
||||
'{ selector: \'[someDirective]\' }',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMembersOfClass()', () => {
|
||||
it('should find decorated members on a class', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const members = host.getMembersOfClass(classNode);
|
||||
|
||||
const input1 = members.find(member => member.name === 'input1') !;
|
||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input1.isStatic).toEqual(false);
|
||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
|
||||
const input2 = members.find(member => member.name === 'input2') !;
|
||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||
expect(input2.isStatic).toEqual(false);
|
||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
||||
});
|
||||
|
||||
describe('getConstructorParameters', () => {
|
||||
it('should find the decorated constructor parameters', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const parameters = host.getConstructorParameters(classNode);
|
||||
|
||||
expect(parameters).toBeDefined();
|
||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
||||
'_viewContainer', '_template', 'injected'
|
||||
]);
|
||||
expectTypeValueReferencesForParameters(parameters !, [
|
||||
'ViewContainerRef',
|
||||
'TemplateRef',
|
||||
null,
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1057,22 +1057,17 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const mockImportInfo: Import = {from: '@angular/core', name: 'Directive'};
|
||||
const spy = spyOn(host, 'getImportOfIdentifier').and.returnValue(mockImportInfo);
|
||||
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
});
|
||||
|
||||
it('should find decorated members on a class at the top level', () => {
|
||||
@ -1290,22 +1285,17 @@ runInEachFileSystem(() => {
|
||||
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
|
||||
});
|
||||
|
||||
it('should use `getImportOfIdentifier()` to retrieve import info', () => {
|
||||
it('should have import information on decorators', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program, host: compilerHost} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost);
|
||||
const mockImportInfo = { name: 'mock', from: '@angular/core' } as Import;
|
||||
const spy = spyOn(host, 'getImportOfIdentifier').and.returnValue(mockImportInfo);
|
||||
|
||||
const classNode = getDeclaration(
|
||||
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
||||
|
||||
expect(decorators.length).toEqual(1);
|
||||
expect(decorators[0].import).toBe(mockImportInfo);
|
||||
|
||||
const typeIdentifier = spy.calls.mostRecent().args[0] as ts.Identifier;
|
||||
expect(typeIdentifier.text).toBe('Directive');
|
||||
expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||
});
|
||||
|
||||
describe('(returned prop decorators `args`)', () => {
|
||||
|
@ -201,7 +201,7 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
|
||||
|
||||
const identifiers = ExpressionVisitor.getIdentifiers(
|
||||
attribute.value, expressionSrc, expressionAbsolutePosition, this.boundTemplate,
|
||||
this.targetToIdentifier);
|
||||
this.targetToIdentifier.bind(this));
|
||||
identifiers.forEach(id => this.identifiers.add(id));
|
||||
}
|
||||
visitBoundEvent(attribute: TmplAstBoundEvent) { this.visitExpression(attribute.handler); }
|
||||
|
@ -124,6 +124,32 @@ runInEachFileSystem(() => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should discover variables in bound attributes', () => {
|
||||
const template = '<div #div [value]="div.innerText"></div>';
|
||||
const refs = getTemplateIdentifiers(bind(template));
|
||||
const elementReference: ElementIdentifier = {
|
||||
name: 'div',
|
||||
kind: IdentifierKind.Element,
|
||||
span: new AbsoluteSourceSpan(1, 4),
|
||||
attributes: new Set(),
|
||||
usedDirectives: new Set(),
|
||||
};
|
||||
const reference: ReferenceIdentifier = {
|
||||
name: 'div',
|
||||
kind: IdentifierKind.Reference,
|
||||
span: new AbsoluteSourceSpan(6, 9),
|
||||
target: {node: elementReference, directive: null},
|
||||
};
|
||||
|
||||
const refArr = Array.from(refs);
|
||||
expect(refArr).toContain({
|
||||
name: 'div',
|
||||
kind: IdentifierKind.Property,
|
||||
span: new AbsoluteSourceSpan(19, 22),
|
||||
target: reference,
|
||||
});
|
||||
});
|
||||
|
||||
it('should discover properties in template expressions', () => {
|
||||
const template = '<div [bar]="bar ? bar1 : bar2"></div>';
|
||||
const refs = getTemplateIdentifiers(bind(template));
|
||||
|
@ -11,7 +11,7 @@ import * as ts from 'typescript';
|
||||
|
||||
import {Diagnostic} from '../src/diagnostics';
|
||||
|
||||
import {NGFOR_DECLARATION, TestDeclaration, ngForDts, typecheck} from './test_utils';
|
||||
import {TestDeclaration, ngForDeclaration, ngForDts, typecheck} from './test_utils';
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('template diagnostics', () => {
|
||||
@ -46,7 +46,7 @@ runInEachFileSystem(() => {
|
||||
|
||||
render(input: string): string { return input; }
|
||||
}`,
|
||||
[NGFOR_DECLARATION], [ngForDts()]);
|
||||
[ngForDeclaration()], [ngForDts()]);
|
||||
|
||||
expect(messages).toEqual([
|
||||
`synthetic.html(61, 64): Argument of type 'number' is not assignable to parameter of type 'string'.`,
|
||||
@ -61,7 +61,7 @@ runInEachFileSystem(() => {
|
||||
|
||||
render(input: string): string { return input; }
|
||||
}`,
|
||||
[NGFOR_DECLARATION], [ngForDts()]);
|
||||
[ngForDeclaration()], [ngForDts()]);
|
||||
|
||||
expect(messages).toEqual([]);
|
||||
});
|
||||
@ -127,7 +127,7 @@ runInEachFileSystem(() => {
|
||||
name: string;
|
||||
}[];
|
||||
}`,
|
||||
[NGFOR_DECLARATION], [ngForDts()]);
|
||||
[ngForDeclaration()], [ngForDts()]);
|
||||
|
||||
expect(messages).toEqual([
|
||||
`synthetic.html(39, 52): Property 'namme' does not exist on type '{ name: string; }'. Did you mean 'name'?`,
|
||||
|
@ -77,14 +77,16 @@ export function angularCoreDts(): TestFile {
|
||||
};
|
||||
}
|
||||
|
||||
export const NGFOR_DECLARATION: TestDeclaration = {
|
||||
type: 'directive',
|
||||
file: 'ngfor.d.ts',
|
||||
selector: '[ngForOf]',
|
||||
name: 'NgForOf',
|
||||
inputs: {ngForOf: 'ngForOf'},
|
||||
hasNgTemplateContextGuard: true,
|
||||
};
|
||||
export function ngForDeclaration(): TestDeclaration {
|
||||
return {
|
||||
type: 'directive',
|
||||
file: absoluteFrom('/ngfor.d.ts'),
|
||||
selector: '[ngForOf]',
|
||||
name: 'NgForOf',
|
||||
inputs: {ngForOf: 'ngForOf'},
|
||||
hasNgTemplateContextGuard: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function ngForDts(): TestFile {
|
||||
return {
|
||||
@ -124,10 +126,10 @@ export const ALL_ENABLED_CONFIG: TypeCheckingConfig = {
|
||||
// Remove 'ref' from TypeCheckableDirectiveMeta and add a 'selector' instead.
|
||||
export type TestDirective =
|
||||
Partial<Pick<TypeCheckableDirectiveMeta, Exclude<keyof TypeCheckableDirectiveMeta, 'ref'>>>&
|
||||
{selector: string, name: string, file?: string, type: 'directive'};
|
||||
{selector: string, name: string, file?: AbsoluteFsPath, type: 'directive'};
|
||||
export type TestPipe = {
|
||||
name: string,
|
||||
file?: string,
|
||||
file?: AbsoluteFsPath,
|
||||
pipeName: string,
|
||||
type: 'pipe',
|
||||
};
|
||||
@ -185,7 +187,7 @@ export function typecheck(
|
||||
...additionalSources,
|
||||
];
|
||||
const {program, host, options} = makeProgram(files, {strictNullChecks: true}, undefined, false);
|
||||
const sf = program.getSourceFile('main.ts') !;
|
||||
const sf = program.getSourceFile(absoluteFrom('/main.ts')) !;
|
||||
const checker = program.getTypeChecker();
|
||||
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
||||
const emitter = new ReferenceEmitter([
|
||||
|
@ -14,11 +14,14 @@ import {Console} from './console';
|
||||
import {Injector, StaticProvider} from './di';
|
||||
import {Inject, Optional, SkipSelf} from './di/metadata';
|
||||
import {ErrorHandler} from './error_handler';
|
||||
import {DEFAULT_LOCALE_ID} from './i18n/localization';
|
||||
import {LOCALE_ID} from './i18n/tokens';
|
||||
import {ivyEnabled} from './ivy_switch';
|
||||
import {ComponentFactoryResolver} from './linker';
|
||||
import {Compiler} from './linker/compiler';
|
||||
import {NgModule} from './metadata';
|
||||
import {SCHEDULER} from './render3/component_ref';
|
||||
import {setLocaleId} from './render3/i18n';
|
||||
import {NgZone} from './zone';
|
||||
|
||||
export function _iterableDiffersFactory() {
|
||||
@ -31,15 +34,21 @@ export function _keyValueDiffersFactory() {
|
||||
|
||||
export function _localeFactory(locale?: string): string {
|
||||
if (locale) {
|
||||
if (ivyEnabled) {
|
||||
setLocaleId(locale);
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
// Use `goog.LOCALE` as default value for `LOCALE_ID` token for Closure Compiler.
|
||||
// Note: default `goog.LOCALE` value is `en`, when Angular used `en-US`. In order to preserve
|
||||
// backwards compatibility, we use Angular default value over Closure Compiler's one.
|
||||
if (ngI18nClosureMode && typeof goog !== 'undefined' && goog.LOCALE !== 'en') {
|
||||
if (ivyEnabled) {
|
||||
setLocaleId(goog.LOCALE);
|
||||
}
|
||||
return goog.LOCALE;
|
||||
}
|
||||
return 'en-US';
|
||||
return DEFAULT_LOCALE_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,15 +8,16 @@
|
||||
|
||||
import {Observable, Observer, Subscription, merge} from 'rxjs';
|
||||
import {share} from 'rxjs/operators';
|
||||
|
||||
import {ApplicationInitStatus} from './application_init';
|
||||
import {APP_BOOTSTRAP_LISTENER, PLATFORM_INITIALIZER} from './application_tokens';
|
||||
import {getCompilerFacade} from './compiler/compiler_facade';
|
||||
import {Console} from './console';
|
||||
import {Injectable, InjectionToken, Injector, StaticProvider} from './di';
|
||||
import {ErrorHandler} from './error_handler';
|
||||
import {DEFAULT_LOCALE_ID} from './i18n/localization';
|
||||
import {LOCALE_ID} from './i18n/tokens';
|
||||
import {Type} from './interface/type';
|
||||
import {ivyEnabled} from './ivy_switch';
|
||||
import {COMPILER_OPTIONS, CompilerFactory, CompilerOptions} from './linker/compiler';
|
||||
import {ComponentFactory, ComponentRef} from './linker/component_factory';
|
||||
import {ComponentFactoryBoundToModule, ComponentFactoryResolver} from './linker/component_factory_resolver';
|
||||
@ -26,7 +27,7 @@ import {isComponentResourceResolutionQueueEmpty, resolveComponentResources} from
|
||||
import {WtfScopeFn, wtfCreateScope, wtfLeave} from './profile/profile';
|
||||
import {assertNgModuleType} from './render3/assert';
|
||||
import {ComponentFactory as R3ComponentFactory} from './render3/component_ref';
|
||||
import {DEFAULT_LOCALE_ID, setLocaleId} from './render3/i18n';
|
||||
import {setLocaleId} from './render3/i18n';
|
||||
import {NgModuleFactory as R3NgModuleFactory} from './render3/ng_module_ref';
|
||||
import {Testability, TestabilityRegistry} from './testability/testability';
|
||||
import {isDevMode} from './util/is_dev_mode';
|
||||
@ -264,8 +265,10 @@ export class PlatformRef {
|
||||
throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
|
||||
}
|
||||
// If the `LOCALE_ID` provider is defined at bootstrap we set the value for runtime i18n (ivy)
|
||||
const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
||||
setLocaleId(localeId);
|
||||
if (ivyEnabled) {
|
||||
const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
||||
setLocaleId(localeId || DEFAULT_LOCALE_ID);
|
||||
}
|
||||
moduleRef.onDestroy(() => remove(this._modules, moduleRef));
|
||||
ngZone !.runOutsideAngular(
|
||||
() => ngZone !.onError.subscribe(
|
||||
|
@ -16,6 +16,7 @@ export {Console as ɵConsole} from './console';
|
||||
export {inject, setCurrentInjector as ɵsetCurrentInjector, ɵɵinject} from './di/injector_compatibility';
|
||||
export {getInjectableDef as ɵgetInjectableDef, ɵɵInjectableDef, ɵɵInjectorDef} from './di/interface/defs';
|
||||
export {APP_ROOT as ɵAPP_ROOT} from './di/scope';
|
||||
export {DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID} from './i18n/localization';
|
||||
export {ivyEnabled as ɵivyEnabled} from './ivy_switch';
|
||||
export {ComponentFactory as ɵComponentFactory} from './linker/component_factory';
|
||||
export {CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver} from './linker/component_factory_resolver';
|
||||
@ -27,7 +28,6 @@ export {_sanitizeHtml as ɵ_sanitizeHtml} from './sanitization/html_sanitizer';
|
||||
export {_sanitizeStyle as ɵ_sanitizeStyle} from './sanitization/style_sanitizer';
|
||||
export {_sanitizeUrl as ɵ_sanitizeUrl} from './sanitization/url_sanitizer';
|
||||
export {global as ɵglobal} from './util/global';
|
||||
|
||||
export {looseIdentical as ɵlooseIdentical,} from './util/comparison';
|
||||
export {stringify as ɵstringify} from './util/stringify';
|
||||
export {makeDecorator as ɵmakeDecorator} from './util/decorators';
|
||||
|
@ -173,7 +173,6 @@ export {
|
||||
i18nConfigureLocalize as ɵi18nConfigureLocalize,
|
||||
ɵɵi18nLocalize,
|
||||
setLocaleId as ɵsetLocaleId,
|
||||
DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID,
|
||||
setClassMetadata as ɵsetClassMetadata,
|
||||
ɵɵresolveWindow,
|
||||
ɵɵresolveDocument,
|
||||
|
@ -57,11 +57,11 @@ export function forwardRef(forwardRefFn: ForwardRefFn): Type<any> {
|
||||
* @publicApi
|
||||
*/
|
||||
export function resolveForwardRef<T>(type: T): T {
|
||||
const fn: any = type;
|
||||
if (typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) &&
|
||||
fn.__forward_ref__ === forwardRef) {
|
||||
return fn();
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
return isForwardRef(type) ? type() : type;
|
||||
}
|
||||
|
||||
/** Checks whether a function is wrapped by a `forwardRef`. */
|
||||
export function isForwardRef(fn: any): fn is() => any {
|
||||
return typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) &&
|
||||
fn.__forward_ref__ === forwardRef;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Type} from '../../interface/type';
|
||||
import {isForwardRef, resolveForwardRef} from '../forward_ref';
|
||||
import {ɵɵinject} from '../injector_compatibility';
|
||||
import {getInjectableDef, getInjectorDef, ɵɵdefineInjectable, ɵɵdefineInjector} from '../interface/defs';
|
||||
|
||||
@ -26,6 +27,14 @@ export const angularCoreDiEnv: {[name: string]: Function} = {
|
||||
|
||||
function getFactoryOf<T>(type: Type<any>): ((type?: Type<T>) => T)|null {
|
||||
const typeAny = type as any;
|
||||
|
||||
if (isForwardRef(type)) {
|
||||
return (() => {
|
||||
const factory = getFactoryOf<T>(resolveForwardRef(typeAny));
|
||||
return factory ? factory() : null;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
const def = getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny);
|
||||
if (!def || def.factory === undefined) {
|
||||
return null;
|
||||
|
@ -29,3 +29,8 @@ export function getPluralCase(value: any, locale: string): string {
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The locale id that the application is using by default (for translations and ICU expressions).
|
||||
*/
|
||||
export const DEFAULT_LOCALE_ID = 'en-US';
|
||||
|
@ -132,6 +132,9 @@ export interface ContentChildrenDecorator {
|
||||
*
|
||||
* Content queries are set before the `ngAfterContentInit` callback is called.
|
||||
*
|
||||
* Does not retrieve elements or directives that are in other components' templates,
|
||||
* since a component's template is always a black box to its ancestors.
|
||||
*
|
||||
* **Metadata Properties**:
|
||||
*
|
||||
* * **selector** - The directive type or the name used for querying.
|
||||
@ -194,6 +197,9 @@ export interface ContentChildDecorator {
|
||||
*
|
||||
* Content queries are set before the `ngAfterContentInit` callback is called.
|
||||
*
|
||||
* Does not retrieve elements or directives that are in other components' templates,
|
||||
* since a component's template is always a black box to its ancestors.
|
||||
*
|
||||
* **Metadata Properties**:
|
||||
*
|
||||
* * **selector** - The directive type or the name used for querying.
|
||||
|
@ -22,6 +22,21 @@ Great reads:
|
||||
|
||||
See benchmark [here](https://jsperf.com/mono-vs-megamorphic-property-access).
|
||||
|
||||
## Packed vs. holey Array
|
||||
|
||||
V8 represents arrays internally in a different way depending on:
|
||||
- type of elements in the array;
|
||||
- presence of holes (indexes that were never assigned).
|
||||
|
||||
Generally speaking packed arrays (a set of continuous, initialized indexes) perform better as compared to arrays with holes. To assure that arrays are packed follow those guidelines:
|
||||
* create array literals with known values whenever possible (ex. `a = [0];` is better than `a = []; a.push[0];`;
|
||||
* don't use `Array` constructor with the size value (ex. `new Array(5)`) - this will create a `HOLEY_ELEMENTS` array (even if this array is filled in later on!);
|
||||
* don't delete elements from an array (ex. `delete a[0]`) - this will create a hole;
|
||||
* don't write past the array length as this will create holes;
|
||||
|
||||
Great reads:
|
||||
- [Elements kinds in V8](https://v8.dev/blog/elements-kinds)
|
||||
|
||||
## Exporting top level variables
|
||||
|
||||
Exporting top level variables should be avoided where possible where performance
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {isForwardRef, resolveForwardRef} from '../di/forward_ref';
|
||||
import {InjectionToken} from '../di/injection_token';
|
||||
import {Injector} from '../di/injector';
|
||||
import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
|
||||
@ -633,6 +634,14 @@ export class NodeInjector implements Injector {
|
||||
*/
|
||||
export function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T>|null {
|
||||
const typeAny = type as any;
|
||||
|
||||
if (isForwardRef(type)) {
|
||||
return (() => {
|
||||
const factory = ɵɵgetFactoryOf<T>(resolveForwardRef(typeAny));
|
||||
return factory ? factory() : null;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
const def = getComponentDef<T>(typeAny) || getDirectiveDef<T>(typeAny) ||
|
||||
getPipeDef<T>(typeAny) || getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny);
|
||||
if (!def || def.factory === undefined) {
|
||||
|
@ -185,18 +185,23 @@ export function executeHooks(
|
||||
checkNoChangesMode: boolean, initPhaseState: InitPhaseState,
|
||||
currentNodeIndex: number | null | undefined): void {
|
||||
if (checkNoChangesMode) return;
|
||||
const hooksToCall = (currentView[FLAGS] & LViewFlags.InitPhaseStateMask) === initPhaseState ?
|
||||
firstPassHooks :
|
||||
checkHooks;
|
||||
if (hooksToCall) {
|
||||
callHooks(currentView, hooksToCall, initPhaseState, currentNodeIndex);
|
||||
|
||||
if (checkHooks !== null || firstPassHooks !== null) {
|
||||
const hooksToCall = (currentView[FLAGS] & LViewFlags.InitPhaseStateMask) === initPhaseState ?
|
||||
firstPassHooks :
|
||||
checkHooks;
|
||||
if (hooksToCall !== null) {
|
||||
callHooks(currentView, hooksToCall, initPhaseState, currentNodeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// The init phase state must be always checked here as it may have been recursively updated
|
||||
if (currentNodeIndex == null &&
|
||||
(currentView[FLAGS] & LViewFlags.InitPhaseStateMask) === initPhaseState &&
|
||||
let flags = currentView[FLAGS];
|
||||
if (currentNodeIndex == null && (flags & LViewFlags.InitPhaseStateMask) === initPhaseState &&
|
||||
initPhaseState !== InitPhaseState.InitPhaseCompleted) {
|
||||
currentView[FLAGS] &= LViewFlags.IndexWithinInitPhaseReset;
|
||||
currentView[FLAGS] += LViewFlags.InitPhaseStateIncrementer;
|
||||
flags &= LViewFlags.IndexWithinInitPhaseReset;
|
||||
flags += LViewFlags.InitPhaseStateIncrementer;
|
||||
currentView[FLAGS] = flags;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@
|
||||
*/
|
||||
|
||||
import '../util/ng_i18n_closure_mode';
|
||||
|
||||
import {getPluralCase} from '../i18n/localization';
|
||||
import {DEFAULT_LOCALE_ID, getPluralCase} from '../i18n/localization';
|
||||
import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent} from '../sanitization/html_sanitizer';
|
||||
import {InertBodyHelper} from '../sanitization/inert_body';
|
||||
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
|
||||
import {addAllToArray} from '../util/array_utils';
|
||||
import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert';
|
||||
|
||||
import {attachPatchData} from './context_discovery';
|
||||
import {bind, setDelayProjection, ɵɵload} from './instructions/all';
|
||||
import {attachI18nOpCodesDebug} from './instructions/lview_debug';
|
||||
@ -1358,7 +1356,6 @@ export function ɵɵi18nLocalize(input: string, placeholders?: {[key: string]: s
|
||||
* This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
|
||||
* but is now defined as a global value.
|
||||
*/
|
||||
export const DEFAULT_LOCALE_ID = 'en-US';
|
||||
let LOCALE_ID = DEFAULT_LOCALE_ID;
|
||||
|
||||
/**
|
||||
@ -1369,7 +1366,10 @@ let LOCALE_ID = DEFAULT_LOCALE_ID;
|
||||
* @param localeId
|
||||
*/
|
||||
export function setLocaleId(localeId: string) {
|
||||
LOCALE_ID = localeId.toLowerCase().replace(/_/g, '-');
|
||||
assertDefined(localeId, `Expected localeId to be defined`);
|
||||
if (typeof localeId === 'string') {
|
||||
LOCALE_ID = localeId.toLowerCase().replace(/_/g, '-');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,7 +142,6 @@ export {
|
||||
} from './state';
|
||||
|
||||
export {
|
||||
DEFAULT_LOCALE_ID,
|
||||
ɵɵi18n,
|
||||
ɵɵi18nAttributes,
|
||||
ɵɵi18nExp,
|
||||
|
@ -63,15 +63,11 @@ export function refreshDescendantViews(lView: LView) {
|
||||
const tView = lView[TVIEW];
|
||||
const creationMode = isCreationMode(lView);
|
||||
|
||||
// This needs to be set before children are processed to support recursive components
|
||||
tView.firstTemplatePass = false;
|
||||
|
||||
// Resetting the bindingIndex of the current LView as the next steps may trigger change detection.
|
||||
lView[BINDING_INDEX] = tView.bindingStartIndex;
|
||||
|
||||
// If this is a creation pass, we should not call lifecycle hooks or evaluate bindings.
|
||||
// This will be done in the update pass.
|
||||
if (!creationMode) {
|
||||
// Resetting the bindingIndex of the current LView as the next steps may trigger change
|
||||
// detection.
|
||||
lView[BINDING_INDEX] = tView.bindingStartIndex;
|
||||
|
||||
const checkNoChangesMode = getCheckNoChangesMode();
|
||||
|
||||
executePreOrderHooks(lView, tView, checkNoChangesMode, undefined);
|
||||
@ -79,7 +75,9 @@ export function refreshDescendantViews(lView: LView) {
|
||||
refreshDynamicEmbeddedViews(lView);
|
||||
|
||||
// Content query results must be refreshed before content hooks are called.
|
||||
refreshContentQueries(tView, lView);
|
||||
if (tView.contentQueries !== null) {
|
||||
refreshContentQueries(tView, lView);
|
||||
}
|
||||
|
||||
resetPreOrderHookFlags(lView);
|
||||
executeHooks(
|
||||
@ -87,14 +85,22 @@ export function refreshDescendantViews(lView: LView) {
|
||||
InitPhaseState.AfterContentInitHooksToBeRun, undefined);
|
||||
|
||||
setHostBindings(tView, lView);
|
||||
} else {
|
||||
// This needs to be set before children are processed to support recursive components.
|
||||
// This must be set to false immediately after the first creation run because in an
|
||||
// ngFor loop, all the views will be created together before update mode runs and turns
|
||||
// off firstTemplatePass. If we don't set it here, instances will perform directive
|
||||
// matching, etc again and again.
|
||||
tView.firstTemplatePass = false;
|
||||
|
||||
// We resolve content queries specifically marked as `static` in creation mode. Dynamic
|
||||
// content queries are resolved during change detection (i.e. update mode), after embedded
|
||||
// views are refreshed (see block above).
|
||||
if (tView.staticContentQueries) {
|
||||
refreshContentQueries(tView, lView);
|
||||
}
|
||||
}
|
||||
|
||||
// We resolve content queries specifically marked as `static` in creation mode. Dynamic
|
||||
// content queries are resolved during change detection (i.e. update mode), after embedded
|
||||
// views are refreshed (see block above).
|
||||
if (creationMode && tView.staticContentQueries) {
|
||||
refreshContentQueries(tView, lView);
|
||||
}
|
||||
|
||||
// We must materialize query results before child components are processed
|
||||
// in case a child component has projected a container. The LContainer needs
|
||||
@ -103,7 +109,10 @@ export function refreshDescendantViews(lView: LView) {
|
||||
executeViewQueryFn(RenderFlags.Update, tView, lView[CONTEXT]);
|
||||
}
|
||||
|
||||
refreshChildComponents(lView, tView.components);
|
||||
const components = tView.components;
|
||||
if (components !== null) {
|
||||
refreshChildComponents(lView, components);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +120,7 @@ export function refreshDescendantViews(lView: LView) {
|
||||
export function setHostBindings(tView: TView, viewData: LView): void {
|
||||
const selectedIndex = getSelectedIndex();
|
||||
try {
|
||||
if (tView.expandoInstructions) {
|
||||
if (tView.expandoInstructions !== null) {
|
||||
let bindingRootIndex = viewData[BINDING_INDEX] = tView.expandoStartIndex;
|
||||
setBindingRoot(bindingRootIndex);
|
||||
let currentDirectiveIndex = -1;
|
||||
@ -179,11 +188,9 @@ function refreshContentQueries(tView: TView, lView: LView): void {
|
||||
}
|
||||
|
||||
/** Refreshes child components in the current view. */
|
||||
function refreshChildComponents(hostLView: LView, components: number[] | null): void {
|
||||
if (components != null) {
|
||||
for (let i = 0; i < components.length; i++) {
|
||||
componentRefresh(hostLView, components[i]);
|
||||
}
|
||||
function refreshChildComponents(hostLView: LView, components: number[]): void {
|
||||
for (let i = 0; i < components.length; i++) {
|
||||
componentRefresh(hostLView, components[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,18 +415,9 @@ export function renderEmbeddedTemplate<T>(viewToRender: LView, tView: TView, con
|
||||
// Will become true if the `try` block executes with no errors.
|
||||
let safeToRunHooks = false;
|
||||
try {
|
||||
setPreviousOrParentTNode(null !, true);
|
||||
|
||||
oldView = enterView(viewToRender, viewToRender[T_HOST]);
|
||||
resetPreOrderHookFlags(viewToRender);
|
||||
executeTemplate(viewToRender, tView.template !, getRenderFlags(viewToRender), context);
|
||||
|
||||
// This must be set to false immediately after the first creation run because in an
|
||||
// ngFor loop, all the views will be created together before update mode runs and turns
|
||||
// off firstTemplatePass. If we don't set it here, instances will perform directive
|
||||
// matching, etc again and again.
|
||||
tView.firstTemplatePass = false;
|
||||
|
||||
refreshDescendantViews(viewToRender);
|
||||
safeToRunHooks = true;
|
||||
} finally {
|
||||
@ -644,11 +642,14 @@ export function createTView(
|
||||
}
|
||||
|
||||
function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {
|
||||
const blueprint = new (ngDevMode ? LViewBlueprint ! : Array)(initialViewLength)
|
||||
.fill(null, 0, bindingStartIndex)
|
||||
.fill(NO_CHANGE, bindingStartIndex) as LView;
|
||||
const blueprint = ngDevMode ? new LViewBlueprint !() : [];
|
||||
|
||||
for (let i = 0; i < initialViewLength; i++) {
|
||||
blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
|
||||
}
|
||||
blueprint[BINDING_INDEX] = bindingStartIndex;
|
||||
return blueprint;
|
||||
|
||||
return blueprint as LView;
|
||||
}
|
||||
|
||||
export function createError(text: string, token: any) {
|
||||
@ -1494,19 +1495,20 @@ export function createLContainer(
|
||||
* by executing an associated template function.
|
||||
*/
|
||||
function refreshDynamicEmbeddedViews(lView: LView) {
|
||||
for (let current = lView[CHILD_HEAD]; current !== null; current = current[NEXT]) {
|
||||
// Note: current can be an LView or an LContainer instance, but here we are only interested
|
||||
// in LContainer. We can tell it's an LContainer because its length is less than the LView
|
||||
// header.
|
||||
if (current[ACTIVE_INDEX] === -1 && isLContainer(current)) {
|
||||
for (let i = CONTAINER_HEADER_OFFSET; i < current.length; i++) {
|
||||
const dynamicViewData = current[i];
|
||||
let viewOrContainer = lView[CHILD_HEAD];
|
||||
while (viewOrContainer !== null) {
|
||||
// Note: viewOrContainer can be an LView or an LContainer instance, but here we are only
|
||||
// interested in LContainer
|
||||
if (isLContainer(viewOrContainer) && viewOrContainer[ACTIVE_INDEX] === -1) {
|
||||
for (let i = CONTAINER_HEADER_OFFSET; i < viewOrContainer.length; i++) {
|
||||
const embeddedLView = viewOrContainer[i];
|
||||
// The directives and pipes are not needed here as an existing view is only being
|
||||
// refreshed.
|
||||
ngDevMode && assertDefined(dynamicViewData[TVIEW], 'TView must be allocated');
|
||||
renderEmbeddedTemplate(dynamicViewData, dynamicViewData[TVIEW], dynamicViewData[CONTEXT] !);
|
||||
ngDevMode && assertDefined(embeddedLView[TVIEW], 'TView must be allocated');
|
||||
renderEmbeddedTemplate(embeddedLView, embeddedLView[TVIEW], embeddedLView[CONTEXT] !);
|
||||
}
|
||||
}
|
||||
viewOrContainer = viewOrContainer[NEXT];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1563,7 +1565,7 @@ export function componentRefresh(hostLView: LView, adjustedElementIndex: number)
|
||||
function syncViewWithBlueprint(componentView: LView) {
|
||||
const componentTView = componentView[TVIEW];
|
||||
for (let i = componentView.length; i < componentTView.blueprint.length; i++) {
|
||||
componentView[i] = componentTView.blueprint[i];
|
||||
componentView.push(componentTView.blueprint[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,8 +167,8 @@ let activeDirectiveSuperClassHeight = 0;
|
||||
*/
|
||||
export function setActiveHostElement(elementIndex: number | null = null) {
|
||||
if (_selectedIndex !== elementIndex) {
|
||||
setSelectedIndex(elementIndex == null ? -1 : elementIndex);
|
||||
activeDirectiveId = elementIndex == null ? 0 : MIN_DIRECTIVE_ID;
|
||||
setSelectedIndex(elementIndex === null ? -1 : elementIndex);
|
||||
activeDirectiveId = elementIndex === null ? 0 : MIN_DIRECTIVE_ID;
|
||||
activeDirectiveSuperClassDepthPosition = 0;
|
||||
activeDirectiveSuperClassHeight = 0;
|
||||
}
|
||||
|
@ -688,7 +688,11 @@ export class DebugRenderer2 implements Renderer2 {
|
||||
constructor(private delegate: Renderer2) { this.data = this.delegate.data; }
|
||||
|
||||
destroyNode(node: any) {
|
||||
removeDebugNodeFromIndex(getDebugNode(node) !);
|
||||
const debugNode = getDebugNode(node) !;
|
||||
removeDebugNodeFromIndex(debugNode);
|
||||
if (debugNode instanceof DebugNode__PRE_R3__) {
|
||||
debugNode.listeners.length = 0;
|
||||
}
|
||||
if (this.delegate.destroyNode) {
|
||||
this.delegate.destroyNode(node);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Attribute, ChangeDetectorRef, Component, Directive, ElementRef, EventEmitter, Host, HostBinding, INJECTOR, Inject, Injectable, InjectionToken, Injector, Input, LOCALE_ID, ModuleWithProviders, NgModule, Optional, Output, Pipe, PipeTransform, Self, SkipSelf, TemplateRef, ViewChild, ViewContainerRef, forwardRef} from '@angular/core';
|
||||
import {Attribute, ChangeDetectorRef, Component, Directive, ElementRef, EventEmitter, Host, HostBinding, INJECTOR, Inject, Injectable, InjectionToken, Injector, Input, LOCALE_ID, ModuleWithProviders, NgModule, Optional, Output, Pipe, PipeTransform, Self, SkipSelf, TemplateRef, ViewChild, ViewContainerRef, forwardRef, ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID} from '@angular/core';
|
||||
import {ViewRef} from '@angular/core/src/render3/view_ref';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {ivyEnabled, onlyInIvy} from '@angular/private/testing';
|
||||
@ -1508,7 +1508,7 @@ describe('di', () => {
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
fixture.detectChanges();
|
||||
// takes `LOCALE_ID` from module injector, since we skip Component level with @SkipSelf
|
||||
expect(fixture.componentInstance.localeId).toBe('en-US');
|
||||
expect(fixture.componentInstance.localeId).toBe(DEFAULT_LOCALE_ID);
|
||||
});
|
||||
|
||||
it('should work when injecting dependency in Directives', () => {
|
||||
|
@ -9,6 +9,7 @@
|
||||
import {Component, Directive, Inject, Injectable, InjectionToken, Injector, NgModule, Optional, forwardRef} from '@angular/core';
|
||||
import {TestBed, async, inject} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {onlyInIvy} from '@angular/private/testing';
|
||||
|
||||
describe('providers', () => {
|
||||
@ -319,6 +320,54 @@ describe('providers', () => {
|
||||
expect(fixture.componentInstance.myService.dep.value).toBe('one');
|
||||
});
|
||||
|
||||
it('should support forward refs in useClass when impl version is also provided', () => {
|
||||
|
||||
@Injectable({providedIn: 'root', useClass: forwardRef(() => SomeProviderImpl)})
|
||||
abstract class SomeProvider {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class SomeProviderImpl extends SomeProvider {
|
||||
}
|
||||
|
||||
@Component({selector: 'my-app', template: ''})
|
||||
class App {
|
||||
constructor(public foo: SomeProvider) {}
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [App], providers: [{provide: SomeProvider, useClass: SomeProviderImpl}]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.foo).toBeAnInstanceOf(SomeProviderImpl);
|
||||
});
|
||||
|
||||
|
||||
onlyInIvy('VE bug (see FW-1454)')
|
||||
.it('should support forward refs in useClass when token is provided', () => {
|
||||
|
||||
@Injectable({providedIn: 'root', useClass: forwardRef(() => SomeProviderImpl)})
|
||||
abstract class SomeProvider {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class SomeProviderImpl extends SomeProvider {
|
||||
}
|
||||
|
||||
@Component({selector: 'my-app', template: ''})
|
||||
class App {
|
||||
constructor(public foo: SomeProvider) {}
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [App], providers: [{provide: SomeProvider, useClass: SomeProvider}]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.foo).toBeAnInstanceOf(SomeProviderImpl);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('flags', () => {
|
||||
|
@ -343,6 +343,21 @@ class SomeComponent {
|
||||
|
||||
expect(getLocaleId()).toEqual('ro');
|
||||
});
|
||||
|
||||
it('should wait for APP_INITIALIZER to set providers for `LOCALE_ID`', async() => {
|
||||
let locale: string = '';
|
||||
|
||||
const promise = Promise.resolve().then(() => { locale = 'fr-FR'; });
|
||||
|
||||
const testModule = createModule({
|
||||
providers: [
|
||||
{provide: APP_INITIALIZER, useValue: () => promise, multi: true},
|
||||
{provide: LOCALE_ID, useFactory: () => locale}
|
||||
]
|
||||
});
|
||||
const app = await defaultPlatform.bootstrapModule(testModule);
|
||||
expect(app.injector.get(LOCALE_ID)).toEqual('fr-FR');
|
||||
});
|
||||
});
|
||||
|
||||
describe('bootstrapModuleFactory', () => {
|
||||
|
@ -155,6 +155,9 @@
|
||||
{
|
||||
"name": "isFactoryProvider"
|
||||
},
|
||||
{
|
||||
"name": "isForwardRef"
|
||||
},
|
||||
{
|
||||
"name": "isTypeProvider"
|
||||
},
|
||||
|
@ -1043,6 +1043,9 @@
|
||||
{
|
||||
"name": "isFactory"
|
||||
},
|
||||
{
|
||||
"name": "isForwardRef"
|
||||
},
|
||||
{
|
||||
"name": "isJsObject"
|
||||
},
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
import {CommonModule, NgIfContext} from '@angular/common';
|
||||
import {Component, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
import {Component, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
@ -927,5 +927,40 @@ class TestCmptWithPropBindings {
|
||||
expect(div.attributes.foo).toBe('bar');
|
||||
});
|
||||
|
||||
it('should clear event listeners when node is destroyed', () => {
|
||||
let calls = 0;
|
||||
@Component({
|
||||
selector: 'cancel-button',
|
||||
template: '',
|
||||
})
|
||||
class CancelButton {
|
||||
@Output() cancel = new EventEmitter<void>();
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: '<cancel-button *ngIf="visible" (cancel)="cancel()"></cancel-button>',
|
||||
})
|
||||
class App {
|
||||
visible = true;
|
||||
cancel() { calls++; }
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App, CancelButton]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.directive(CancelButton));
|
||||
button.triggerEventHandler('cancel', {});
|
||||
|
||||
expect(calls).toBe(1, 'Expected calls to be 1 after one event.');
|
||||
|
||||
fixture.componentInstance.visible = false;
|
||||
fixture.detectChanges();
|
||||
|
||||
button.triggerEventHandler('cancel', {});
|
||||
|
||||
expect(calls).toBe(1, 'Expected calls to stay 1 after destroying the node.');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ ts_config(
|
||||
name = "tsconfig",
|
||||
src = "tsconfig.json",
|
||||
deps = [
|
||||
"//tools:tsconfig-test",
|
||||
"//packages:tsconfig-test",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "ng_module", "ts_library")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "jasmine_node_test", "ng_module", "ts_library")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "ng_module", "ts_library")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "ng_module", "ts_library")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractorUtils = require('@bazel/protractor/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("//tools:defaults.bzl", "ng_module", "ts_library")
|
||||
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
|
||||
|
||||
"""
|
||||
|
@ -1,3 +1,23 @@
|
||||
<a name="0.10.0"></a>
|
||||
# [0.10.0](https://github.com/angular/angular/compare/7b3bcc2...174770e) (2019-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **zone.js:** __load_patch and __symbol__ should be in zone_extern for closure compiler ([#31350](https://github.com/angular/angular/issues/31350)) ([6b51ed2](https://github.com/angular/angular/commit/6b51ed2))
|
||||
* **zone.js:** don't fire unhandledrejection if Zone handled error ([#31718](https://github.com/angular/angular/issues/31718)) ([c7542a1](https://github.com/angular/angular/commit/c7542a1)), closes [#31701](https://github.com/angular/angular/issues/31701)
|
||||
* **zone.js:** don't wrap uncaught promise error. ([#31443](https://github.com/angular/angular/issues/31443)) ([2bb9a65](https://github.com/angular/angular/commit/2bb9a65)), closes [#27840](https://github.com/angular/angular/issues/27840)
|
||||
* **zone.js:** fix zone for Jasmine 3.3. ([#31497](https://github.com/angular/angular/issues/31497)) ([c4c340a](https://github.com/angular/angular/commit/c4c340a))
|
||||
* **zone.js:** handle MSPointer event correctly ([#31722](https://github.com/angular/angular/issues/31722)) ([2c402d5](https://github.com/angular/angular/commit/2c402d5)), closes [#31699](https://github.com/angular/angular/issues/31699)
|
||||
* **zone.js:** handle new api of electron 4 ([#31669](https://github.com/angular/angular/issues/31669)) ([a445826](https://github.com/angular/angular/commit/a445826)), closes [#31668](https://github.com/angular/angular/issues/31668)
|
||||
* **zone.js:** hook should set correct current zone ([#31642](https://github.com/angular/angular/issues/31642)) ([17b32b5](https://github.com/angular/angular/commit/17b32b5)), closes [#31641](https://github.com/angular/angular/issues/31641)
|
||||
* **zone.js:** move property patch to legacy ([#31660](https://github.com/angular/angular/issues/31660)) ([716af10](https://github.com/angular/angular/commit/716af10)), closes [#31659](https://github.com/angular/angular/issues/31659)
|
||||
* **zone.js:** patch shadydom ([#31717](https://github.com/angular/angular/issues/31717)) ([35a025f](https://github.com/angular/angular/commit/35a025f)), closes [#31686](https://github.com/angular/angular/issues/31686)
|
||||
* **zone.js:** restore definition of global ([#31453](https://github.com/angular/angular/issues/31453)) ([e6f1b04](https://github.com/angular/angular/commit/e6f1b04)), closes [/github.com/angular/zone.js/commit/71b93711806000d7788e79451478e20d6086aa8a#diff-dd469785fca8680a5b33b1e81c5cfd91R1420](https://github.com//github.com/angular/zone.js/commit/71b93711806000d7788e79451478e20d6086aa8a/issues/diff-dd469785fca8680a5b33b1e81c5cfd91R1420)
|
||||
* **zone.js:** should remove on symbol property after removeAllListeners ([#31644](https://github.com/angular/angular/issues/31644)) ([a182714](https://github.com/angular/angular/commit/a182714)), closes [#31643](https://github.com/angular/angular/issues/31643)
|
||||
* **zone.js:** update dart zone link ([#31646](https://github.com/angular/angular/issues/31646)) ([7f7033b](https://github.com/angular/angular/commit/7f7033b)), closes [#31645](https://github.com/angular/angular/issues/31645)
|
||||
* **zone.js:** zone-mix should import correct browser module ([#31628](https://github.com/angular/angular/issues/31628)) ([87ce4e9](https://github.com/angular/angular/commit/87ce4e9)), closes [#31626](https://github.com/angular/angular/issues/31626)
|
||||
|
||||
<a name="0.9.1"></a>
|
||||
## [0.9.1](https://github.com/angular/zone.js/compare/v0.9.0...0.9.1) (2019-04-30)
|
||||
|
||||
@ -44,7 +64,7 @@
|
||||
|
||||
* **env:** change BLACK_LISTED_EVENTS to DISABLE_EVENTS ([9c65d25](https://github.com/angular/zone.js/commit/9c65d25))
|
||||
|
||||
### Build
|
||||
### Build
|
||||
|
||||
* **build:** build zone-evergreen.js in es2015, add terser minify support ([2ad936b](https://github.com/angular/zone.js/commit/2ad936b))
|
||||
* **build:** upgrade to pass jasmine 3.3 test ([82dfd75](https://github.com/angular/zone.js/commit/82dfd75))
|
||||
|
@ -80,10 +80,24 @@ yarn webdriver-sauce-test
|
||||
Releasing
|
||||
---------
|
||||
|
||||
- create a new tag in `angular` repo.
|
||||
|
||||
```
|
||||
$ TAG=<TAG>
|
||||
$ git tag $TAG
|
||||
```
|
||||
|
||||
- create a PR to update `changelog` of zone.js
|
||||
|
||||
```
|
||||
$ yarn gulp changelog:zonejs
|
||||
```
|
||||
|
||||
- deploy to npm
|
||||
|
||||
To make a `dry-run`, run the following commands.
|
||||
```
|
||||
$ VERSION=<version>
|
||||
$ git tag 'zone.js-$VERSION'
|
||||
$ yarn bazel --output_base=$(mktemp -d) run //packages/zone.js:npm_package.pack --workspace_status_command="echo BUILD_SCM_VERSION $VERSION"
|
||||
```
|
||||
|
||||
|
8
packages/zone.js/dist/BUILD.bazel
vendored
8
packages/zone.js/dist/BUILD.bazel
vendored
@ -100,7 +100,9 @@ genrule(
|
||||
],
|
||||
cmd = " && ".join([
|
||||
"mkdir -p $(@D)",
|
||||
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.es5umd.js $(@D)/" + b[0] + ".js",
|
||||
# remove the last line '//# sourceMappingURL=b[0].umd.js.map' because we don't release
|
||||
# source map for now
|
||||
"sed '$$d' $(@D)/" + b[0].replace("-", "_") + "_rollup.es5umd.js > $(@D)/" + b[0] + ".js",
|
||||
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.min.es5umd.js $(@D)/" + b[0] + ".min.js",
|
||||
]),
|
||||
)
|
||||
@ -174,7 +176,9 @@ genrule(
|
||||
],
|
||||
cmd = " && ".join([
|
||||
"mkdir -p $(@D)",
|
||||
"cp $(@D)/" + b.replace("-", "_") + "_rollup.umd.js $(@D)/" + b + ".js",
|
||||
# remove the last line '//# sourceMappingURL=b[0].umd.js.map' because we don't release
|
||||
# source map for now
|
||||
"sed '$$d' $(@D)/" + b.replace("-", "_") + "_rollup.umd.js > $(@D)/" + b + ".js",
|
||||
"cp $(@D)/" + b.replace("-", "_") + "_rollup.min.umd.js $(@D)/" + b + ".min.js",
|
||||
]),
|
||||
)
|
||||
|
@ -331,8 +331,9 @@ Zone.__load_patch('Error', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
|
||||
// we need to detect all zone related frames, it will
|
||||
// exceed default stackTraceLimit, so we set it to
|
||||
// larger number here, and restore it after detect finish.
|
||||
const originalStackTraceLimit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 100;
|
||||
// We cast through any so we don't need to depend on nodejs typings.
|
||||
const originalStackTraceLimit = (Error as any).stackTraceLimit;
|
||||
(Error as any).stackTraceLimit = 100;
|
||||
// we schedule event/micro/macro task, and invoke them
|
||||
// when onSchedule, so we can get all stack traces for
|
||||
// all kinds of tasks with one error thrown.
|
||||
@ -374,5 +375,5 @@ Zone.__load_patch('Error', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
|
||||
});
|
||||
});
|
||||
|
||||
Error.stackTraceLimit = originalStackTraceLimit;
|
||||
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
||||
});
|
||||
|
@ -176,25 +176,20 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
|
||||
}
|
||||
if (queue.length == 0 && state == REJECTED) {
|
||||
(promise as any)[symbolState] = REJECTED_NO_CATCH;
|
||||
let uncaughtPromiseError: any;
|
||||
if (value instanceof Error || (value && value.message)) {
|
||||
uncaughtPromiseError = value;
|
||||
} else {
|
||||
try {
|
||||
// try to print more readable error log
|
||||
throw new Error(
|
||||
'Uncaught (in promise): ' + readableObjectToString(value) +
|
||||
(value && value.stack ? '\n' + value.stack : ''));
|
||||
} catch (err) {
|
||||
uncaughtPromiseError = err;
|
||||
}
|
||||
try {
|
||||
// try to print more readable error log
|
||||
throw new Error(
|
||||
'Uncaught (in promise): ' + readableObjectToString(value) +
|
||||
(value && value.stack ? '\n' + value.stack : ''));
|
||||
} catch (err) {
|
||||
const error: UncaughtPromiseError = err;
|
||||
error.rejection = value;
|
||||
error.promise = promise;
|
||||
error.zone = Zone.current;
|
||||
error.task = Zone.currentTask !;
|
||||
_uncaughtPromiseErrors.push(error);
|
||||
api.scheduleMicroTask(); // to make sure that it is running
|
||||
}
|
||||
uncaughtPromiseError.rejection = value;
|
||||
uncaughtPromiseError.promise = promise;
|
||||
uncaughtPromiseError.zone = Zone.current;
|
||||
uncaughtPromiseError.task = Zone.currentTask !;
|
||||
_uncaughtPromiseErrors.push(uncaughtPromiseError);
|
||||
api.scheduleMicroTask(); // to make sure that it is running
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,16 @@ function renderLongStackTrace(frames: LongStackTrace[], stack?: string): string
|
||||
return longTrace.join(NEWLINE);
|
||||
}
|
||||
|
||||
// if Error.stackTraceLimit is 0, means stack trace
|
||||
// is disabled, so we don't need to generate long stack trace
|
||||
// this will improve performance in some test(some test will
|
||||
// set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698
|
||||
function stackTracesEnabled(): boolean {
|
||||
// Cast through any since this property only exists on Error in the nodejs
|
||||
// typings.
|
||||
return (Error as any).stackTraceLimit > 0;
|
||||
}
|
||||
|
||||
type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number};
|
||||
|
||||
(Zone as any)['longStackTraceZoneSpec'] = <LongStackTraceZoneSpec>{
|
||||
@ -99,11 +109,7 @@ type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number};
|
||||
|
||||
onScheduleTask: function(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any {
|
||||
if (Error.stackTraceLimit > 0) {
|
||||
// if Error.stackTraceLimit is 0, means stack trace
|
||||
// is disabled, so we don't need to generate long stack trace
|
||||
// this will improve performance in some test(some test will
|
||||
// set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698
|
||||
if (stackTracesEnabled()) {
|
||||
const currentTask = Zone.currentTask;
|
||||
let trace = currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || [];
|
||||
trace = [new LongStackTrace()].concat(trace);
|
||||
@ -127,11 +133,7 @@ type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number};
|
||||
|
||||
onHandleError: function(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): boolean {
|
||||
if (Error.stackTraceLimit > 0) {
|
||||
// if Error.stackTraceLimit is 0, means stack trace
|
||||
// is disabled, so we don't need to generate long stack trace
|
||||
// this will improve performance in some test(some test will
|
||||
// set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698
|
||||
if (stackTracesEnabled()) {
|
||||
const parentTask = Zone.currentTask || error.task;
|
||||
if (error instanceof Error && parentTask) {
|
||||
const longStack =
|
||||
@ -154,7 +156,7 @@ function captureStackTraces(stackTraces: string[][], count: number): void {
|
||||
}
|
||||
|
||||
function computeIgnoreFrames() {
|
||||
if (Error.stackTraceLimit <= 0) {
|
||||
if (!stackTracesEnabled()) {
|
||||
return;
|
||||
}
|
||||
const frames: string[][] = [];
|
||||
|
@ -321,10 +321,15 @@ interface ZoneType {
|
||||
__symbol__(name: string): string;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/**
|
||||
* Patch Function to allow user define their own monkey patch module.
|
||||
*/
|
||||
type _PatchFn = (global: Window, Zone: ZoneType, api: _ZonePrivate) => void;
|
||||
|
||||
/** @internal */
|
||||
/**
|
||||
* _ZonePrivate interface to provide helper method to help user implement
|
||||
* their own monkey patch module.
|
||||
*/
|
||||
interface _ZonePrivate {
|
||||
currentZoneFrame: () => _ZoneFrame;
|
||||
symbol: (name: string) => string;
|
||||
@ -366,7 +371,9 @@ interface _ZonePrivate {
|
||||
} | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/**
|
||||
* _ZoneFrame represents zone stack frame information
|
||||
*/
|
||||
interface _ZoneFrame {
|
||||
parent: _ZoneFrame|null;
|
||||
zone: Zone;
|
||||
@ -668,6 +675,12 @@ type AmbientZone = Zone;
|
||||
/** @internal */
|
||||
type AmbientZoneDelegate = ZoneDelegate;
|
||||
|
||||
// CommonJS / Node have global context exposed as "global" variable.
|
||||
// This code should run in a Browser, so we don't want to include the whole node.d.ts
|
||||
// typings for this compilation unit.
|
||||
// We'll just fake the global "global" var for now.
|
||||
declare var global: NodeJS.Global;
|
||||
|
||||
const Zone: ZoneType = (function(global: any) {
|
||||
const performance: {mark(name: string): void; measure(name: string, label: string): void;} =
|
||||
global['performance'];
|
||||
@ -703,6 +716,7 @@ const Zone: ZoneType = (function(global: any) {
|
||||
}
|
||||
|
||||
class Zone implements AmbientZone {
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
static __symbol__: (name: string) => string = __symbol__;
|
||||
|
||||
static assertZonePatched() {
|
||||
@ -728,6 +742,7 @@ const Zone: ZoneType = (function(global: any) {
|
||||
|
||||
static get currentTask(): Task|null { return _currentTask; }
|
||||
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
static __load_patch(name: string, fn: _PatchFn): void {
|
||||
if (patches.hasOwnProperty(name)) {
|
||||
if (checkDuplicate) {
|
||||
@ -1184,6 +1199,7 @@ const Zone: ZoneType = (function(global: any) {
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
_updateTaskCount(type: TaskType, count: number) {
|
||||
const counts = this._taskCounts;
|
||||
const prev = counts[type];
|
||||
@ -1211,9 +1227,12 @@ const Zone: ZoneType = (function(global: any) {
|
||||
public data: TaskData|undefined;
|
||||
public scheduleFn: ((task: Task) => void)|undefined;
|
||||
public cancelFn: ((task: Task) => void)|undefined;
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
_zone: Zone|null = null;
|
||||
public runCount: number = 0;
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
_zoneDelegates: ZoneDelegate[]|null = null;
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
_state: TaskState = 'notScheduled';
|
||||
|
||||
constructor(
|
||||
@ -1261,6 +1280,7 @@ const Zone: ZoneType = (function(global: any) {
|
||||
|
||||
public cancelScheduleRequest() { this._transitionTo(notScheduled, scheduling); }
|
||||
|
||||
// tslint:disable-next-line:require-internal-with-underscore
|
||||
_transitionTo(toState: TaskState, fromState1: TaskState, fromState2?: TaskState) {
|
||||
if (this._state === fromState1 || this._state === fromState2) {
|
||||
this._state = toState;
|
||||
|
@ -345,8 +345,11 @@ describe(
|
||||
});
|
||||
setTimeout((): any => null);
|
||||
setTimeout(() => {
|
||||
expect(promiseError !.message)
|
||||
.toBe(
|
||||
'Uncaught (in promise): ' + error +
|
||||
(error !.stack ? '\n' + error !.stack : ''));
|
||||
expect((promiseError as any)['rejection']).toBe(error);
|
||||
expect(promiseError).toBe(error);
|
||||
expect((promiseError as any)['zone']).toBe(zone);
|
||||
expect((promiseError as any)['task']).toBe(task);
|
||||
done();
|
||||
@ -386,39 +389,6 @@ describe(
|
||||
});
|
||||
});
|
||||
|
||||
it('should print original information when throw a not error object with a message property',
|
||||
(done) => {
|
||||
let promiseError: Error|null = null;
|
||||
let zone: Zone|null = null;
|
||||
let task: Task|null = null;
|
||||
let rejectObj: TestRejection;
|
||||
queueZone
|
||||
.fork({
|
||||
name: 'promise-error',
|
||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
|
||||
boolean => {
|
||||
promiseError = error;
|
||||
delegate.handleError(target, error);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.run(() => {
|
||||
zone = Zone.current;
|
||||
task = Zone.currentTask;
|
||||
rejectObj = new TestRejection();
|
||||
rejectObj.prop1 = 'value1';
|
||||
rejectObj.prop2 = 'value2';
|
||||
(rejectObj as any).message = 'rejectMessage';
|
||||
Promise.reject(rejectObj);
|
||||
expect(promiseError).toBe(null);
|
||||
});
|
||||
setTimeout((): any => null);
|
||||
setTimeout(() => {
|
||||
expect(promiseError).toEqual(rejectObj as any);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Promise.race', () => {
|
||||
it('should reject the value', () => {
|
||||
queueZone.run(() => {
|
||||
|
@ -49,11 +49,16 @@ describe('Zone.js npm_package', () => {
|
||||
describe('es5', () => {
|
||||
it('zone.js(es5) should not contain es6 spread code',
|
||||
() => { expect(shx.cat('zone.js')).not.toContain('let value of values'); });
|
||||
|
||||
it('zone.js(es5) should not contain source map comment',
|
||||
() => { expect(shx.cat('zone.js')).not.toContain('sourceMappingURL'); });
|
||||
});
|
||||
|
||||
describe('es2015', () => {
|
||||
it('zone-evergreen.js(es2015) should contain es6 code',
|
||||
() => { expect(shx.cat('zone-evergreen.js')).toContain('let value of values'); });
|
||||
it('zone.js(es5) should not contain source map comment',
|
||||
() => { expect(shx.cat('zone-evergreen.js')).not.toContain('sourceMappingURL'); });
|
||||
});
|
||||
|
||||
describe('dist file list', () => {
|
||||
|
@ -84,7 +84,9 @@ describe('FakeAsyncTestZoneSpec', () => {
|
||||
() => {
|
||||
fakeAsyncTestZone.run(() => {
|
||||
Promise.resolve(null).then((_) => { throw new Error('async'); });
|
||||
expect(() => { testZoneSpec.flushMicrotasks(); }).toThrowError(/async/);
|
||||
expect(() => {
|
||||
testZoneSpec.flushMicrotasks();
|
||||
}).toThrowError(/Uncaught \(in promise\): Error: async/);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1169,7 +1171,7 @@ const {fakeAsync, tick, discardPeriodicTasks, flush, flushMicrotasks} = fakeAsyn
|
||||
resolvedPromise.then((_) => { throw new Error('async'); });
|
||||
flushMicrotasks();
|
||||
})();
|
||||
}).toThrowError(/async/);
|
||||
}).toThrowError(/Uncaught \(in promise\): Error: async/);
|
||||
});
|
||||
|
||||
it('should complain if a test throws an exception', () => {
|
||||
|
23
tools/gulp-tasks/changelog-zonejs.js
Normal file
23
tools/gulp-tasks/changelog-zonejs.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
module.exports = (gulp) => () => {
|
||||
const tag = process.env.ZONE_TAG;
|
||||
const conventionalChangelog = require('gulp-conventional-changelog');
|
||||
return gulp.src('packages/zone.js/CHANGELOG.md')
|
||||
.pipe(conventionalChangelog(
|
||||
{preset: 'angular'}, {
|
||||
currentTag: tag,
|
||||
},
|
||||
{
|
||||
// Ignore commits that have a different scope than `zone.js`.
|
||||
extendedRegexp: true,
|
||||
grep: '^[^(]+\\(zone\\.js\\)',
|
||||
}))
|
||||
.pipe(gulp.dest('./packages/zone.js/'));
|
||||
};
|
101
yarn.lock
101
yarn.lock
@ -90,29 +90,31 @@
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@bazel/bazel-darwin_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.27.0.tgz#83a03c92d52ae60e48e86a1ee697e69e12ddbdf6"
|
||||
integrity sha512-CyavIbRKRa/55aMyfEM9hjbt4TVISfv7HLeymHTGTLWzS8uQokQ8W9tR/pgc7YJn8F0x64dd7nQKxhbYHM1Qfg==
|
||||
"@bazel/bazel-darwin_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.28.1.tgz#415658785e1dbd6f7ab5c8f2b98c1c99c614e1d5"
|
||||
integrity sha512-VDKWmplAfa4uCAbkIQ5nRn04MFQqtsPNuc2HkluJ8OIum773yC2dPR+OlLBKxrlBuKJYB27TtbOwOa6w/uK7aw==
|
||||
|
||||
"@bazel/bazel-linux_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.27.0.tgz#2358292aa4901f526ba9b90874256f63d6d6608c"
|
||||
integrity sha512-hO04v7C6M3Jf+qNlLE+IticZZKkkS7Nv6+pXDnENgFWrqLV2H93un6kNQnk83B0hP2cEqRQ8rw5yrIcqXNNuSQ==
|
||||
"@bazel/bazel-linux_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.28.1.tgz#f78006089e17660261088272a0e04fc886572e34"
|
||||
integrity sha512-n4XfNxagYhejQD32V4XSxT/qzuH1l/2jxslbKSak66/uQ+wad8Ew9rjNb4JUin3xtrfFtzmxx2jpQkybZsRVGA==
|
||||
|
||||
"@bazel/bazel-win32_x64@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.27.0.tgz#0e5e498de5ccccc9a6cf481cd46904ee938ab6c2"
|
||||
integrity sha512-7hIGNhdgaxRt9ceSOCs3eSTtCNi4GXz3nu6OjfgSp+QiqLbW/iAVWa8M8vD5aemZ1BSHek4/LISdWUTncLJk+w==
|
||||
"@bazel/bazel-win32_x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.28.1.tgz#60a2819618cf7582cc35ac16c01763a5e807b414"
|
||||
integrity sha512-T4xksGfKikaHS4zxnGT6r5R436mz9j2lz//L1vc5sJnaEF/1e2Gv6MLl86vfZW2Xxo6iIEi6ntSzgYxP2Blohw==
|
||||
|
||||
"@bazel/bazel@0.27.0":
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel/-/bazel-0.27.0.tgz#4e72c8e1cbb4da41022b6de1afe28731f5f58e09"
|
||||
integrity sha512-yIj64IkesNzjHsoeehQUMBOgrCK/JMSuon5CvBqo6+izPXAmt+OW05uqaLL/FPAYAFQ2mHxsYtDsPxsM8DUbqA==
|
||||
"@bazel/bazel@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel/-/bazel-0.28.1.tgz#3a6b9b7a74d566c66805242ccaa2f907592b5bff"
|
||||
integrity sha512-s4bn5/vegEec66l15ZjyUe4jNybQ5J/cg9gFzR5f8deKj8lM+2WtCfvTLO3XfUe2pbrB4BG7C31jpyFPOC+6aw==
|
||||
dependencies:
|
||||
"@bazel/hide-bazel-files" latest
|
||||
optionalDependencies:
|
||||
"@bazel/bazel-darwin_x64" "0.27.0"
|
||||
"@bazel/bazel-linux_x64" "0.27.0"
|
||||
"@bazel/bazel-win32_x64" "0.27.0"
|
||||
"@bazel/bazel-darwin_x64" "0.28.1"
|
||||
"@bazel/bazel-linux_x64" "0.28.1"
|
||||
"@bazel/bazel-win32_x64" "0.28.1"
|
||||
|
||||
"@bazel/buildifier-darwin_x64@0.26.0":
|
||||
version "0.26.0"
|
||||
@ -138,29 +140,29 @@
|
||||
"@bazel/buildifier-linux_x64" "0.26.0"
|
||||
"@bazel/buildifier-win32_x64" "0.26.0"
|
||||
|
||||
"@bazel/hide-bazel-files@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/hide-bazel-files/-/hide-bazel-files-0.32.2.tgz#a482855eafbccb56b1fce0d92ff922c2c6e0a90c"
|
||||
integrity sha512-585XY53mhMZaCjEQJ+aDqkmydWZbuXsKrZsSpoW9YeAVEH0poQY3YhdyCPmMVBo7/l1mkrqpFuOK5BpECfwdtA==
|
||||
"@bazel/hide-bazel-files@latest":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/hide-bazel-files/-/hide-bazel-files-0.34.0.tgz#368ea84db2756ff80ead23bb9eb179e9ed24b462"
|
||||
integrity sha512-suyO6cZf8iV6W2LkM1X1spWBt7CsRRXH7gU1wYNuAuHYkkfI0A6qj84yPiIXiOt/2G44kbioGyC1bUsI3fKv7A==
|
||||
|
||||
"@bazel/ibazel@~0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/ibazel/-/ibazel-0.9.0.tgz#fd60023acd36313d304cc2f8c2e181b88b5445cd"
|
||||
integrity sha512-E31cefDcdJsx/oii6p/gqKZXSVw0kEg1O73DD2McFcSvnf/p1GYWcQtVgdRQmlviBEytJkJgdX8rtThitRvcow==
|
||||
|
||||
"@bazel/jasmine@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/jasmine/-/jasmine-0.32.2.tgz#6375b5b0de3f352c2b2280c54878dd30915fc139"
|
||||
integrity sha512-izF9hBcbTOj1VhJVeo8G479dXo9KlibX0N6Yag15GaIk1fibW4iRyTBC2fy4ihm31CYIId6Zd9AABVShd+1Sgw==
|
||||
"@bazel/jasmine@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/jasmine/-/jasmine-0.34.0.tgz#74497def9766dee2c6b43e87ee288308d50bfd3f"
|
||||
integrity sha512-vNUxQ1ss0aT7S3CQvQ6U6vJF8H+Cg/jr7kVUCesHQNYaNKqxwZOlZ8cevR/xUKRTcltE6PeJA+Ezgm5mP7sckg==
|
||||
dependencies:
|
||||
jasmine "~3.3.1"
|
||||
jasmine-core "~3.3.0"
|
||||
jasmine "~3.4.0"
|
||||
jasmine-core "~3.4.0"
|
||||
v8-coverage "1.0.9"
|
||||
|
||||
"@bazel/karma@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-0.32.2.tgz#0f6adf0cf1970c50cfdcf9cb2b10a8d3e21731fe"
|
||||
integrity sha512-iWb8aqE+llpZhlreDweM7llwnSAQ9QTYdz4VvIcZBGVD0KtHxHaKiqK4Zo4Qrmr9H0kcOhT7nvRBg3QOUJVrUw==
|
||||
"@bazel/karma@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-0.34.0.tgz#ee468501a408244a2c1844b48ca5a938874d9444"
|
||||
integrity sha512-9EziieE3Zkf7D5tBuX4rO+hhpI4ypNAWReiO/fykjj5oYpLYhhhGGUyFQ8PCIfduPcGZooCTMsctmwZJUb3rRA==
|
||||
dependencies:
|
||||
jasmine-core "2.8.0"
|
||||
karma "^4.0.0"
|
||||
@ -174,10 +176,17 @@
|
||||
semver "5.6.0"
|
||||
tmp "0.0.33"
|
||||
|
||||
"@bazel/typescript@0.32.2":
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.32.2.tgz#c296bb44cb6362a0e3a08ca88752852bc9591ecf"
|
||||
integrity sha512-32zDyvHdYjIa63vtImhl6wy5ErOFVWPkjMT2T035D0UPSKI1tvENW/bRZ3QFlFHqfmJZRBpaI3GiUpO3vUvzmw==
|
||||
"@bazel/protractor@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-0.34.0.tgz#af166306518bf1319e8ca255f798712c8714b5e9"
|
||||
integrity sha512-U6O8hRlerkQ/WfnEVct1yipVQr5epdYaLiOW1eLpmiRMM4RuMhIpIyKkpum5xqFlYP5kwqwje8BS8NHvBfvZnQ==
|
||||
dependencies:
|
||||
protractor "^5.4.2"
|
||||
|
||||
"@bazel/typescript@0.34.0":
|
||||
version "0.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.34.0.tgz#ca0fdf15343a930fc1418dbbf7d6cae49e6bc89b"
|
||||
integrity sha512-GXVSADXdbPyWLskIYAzQsBB1LhZgWF5+M6WCQGOvRWjZfXgRP5QDG5pKJavRGzVd6ofigLPA1xT6Vc7dUEDNtg==
|
||||
dependencies:
|
||||
protobufjs "6.8.8"
|
||||
semver "5.6.0"
|
||||
@ -947,7 +956,7 @@ ansi-align@^2.0.0:
|
||||
|
||||
ansi-colors@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9"
|
||||
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9"
|
||||
integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==
|
||||
dependencies:
|
||||
ansi-wrap "^0.1.0"
|
||||
@ -2498,7 +2507,7 @@ compression@^1.7.0:
|
||||
|
||||
compression@~1.5.2:
|
||||
version "1.5.2"
|
||||
resolved "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395"
|
||||
resolved "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395"
|
||||
integrity sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=
|
||||
dependencies:
|
||||
accepts "~1.2.12"
|
||||
@ -3708,7 +3717,7 @@ event-emitter@^0.3.5, event-emitter@~0.3.5:
|
||||
|
||||
event-stream@^3.1.5, event-stream@^3.3.2:
|
||||
version "3.3.4"
|
||||
resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
|
||||
resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
|
||||
integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=
|
||||
dependencies:
|
||||
duplexer "~0.1.1"
|
||||
@ -6112,7 +6121,7 @@ jasmine-core@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.1.0.tgz#a4785e135d5df65024dfc9224953df585bd2766c"
|
||||
integrity sha1-pHheE11d9lAk38kiSVPfWFvSdmw=
|
||||
|
||||
jasmine-core@^3.3:
|
||||
jasmine-core@^3.3, jasmine-core@~3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.4.0.tgz#2a74618e966026530c3518f03e9f845d26473ce3"
|
||||
integrity sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==
|
||||
@ -6131,7 +6140,7 @@ jasmine@2.8.0:
|
||||
glob "^7.0.6"
|
||||
jasmine-core "~2.8.0"
|
||||
|
||||
jasmine@^3.1.0, jasmine@~3.3.1:
|
||||
jasmine@^3.1.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.3.1.tgz#d61bb1dd8888859bd11ea83074a78ee13d949905"
|
||||
integrity sha512-/vU3/H7U56XsxIXHwgEuWpCgQ0bRi2iiZeUpx7Nqo8n1TpoDHfZhkPIc7CO8I4pnMzYsi3XaSZEiy8cnTfujng==
|
||||
@ -6139,6 +6148,14 @@ jasmine@^3.1.0, jasmine@~3.3.1:
|
||||
glob "^7.0.6"
|
||||
jasmine-core "~3.3.0"
|
||||
|
||||
jasmine@~3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.4.0.tgz#0fa68903ff0c9697459cd044b44f4dcef5ec8bdc"
|
||||
integrity sha512-sR9b4n+fnBFDEd7VS2el2DeHgKcPiMVn44rtKFumq9q7P/t8WrxsVIZPob4UDdgcDNCwyDqwxCt4k9TDRmjPoQ==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
jasmine-core "~3.4.0"
|
||||
|
||||
jasminewd2@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e"
|
||||
|
Reference in New Issue
Block a user