Compare commits
39 Commits
9.1.1
...
8.0.0-rc.2
Author | SHA1 | Date | |
---|---|---|---|
9798229fde | |||
4b2fcfd5dc | |||
b4d291aa7a | |||
b0ecafdc2f | |||
6816bb62d7 | |||
4b05b8cea0 | |||
a0728aedf7 | |||
ea96f6112a | |||
b706800ea8 | |||
c6f95b1d70 | |||
d896126604 | |||
a20da5ddcc | |||
18878600ba | |||
d7e10f3f7e | |||
4d044ea5b2 | |||
e2d1e0cd98 | |||
4e056580bb | |||
e4c2e6a904 | |||
a50989832d | |||
525307b6a3 | |||
a3ab76b216 | |||
f2265d4b46 | |||
d3ac709b99 | |||
908d43a5bb | |||
71cdb0a08e | |||
c7fbbdfa99 | |||
10e4ab7712 | |||
5114c23c21 | |||
c3e585d7eb | |||
0776daec88 | |||
615e1a58b2 | |||
606758357e | |||
ba2a3595c6 | |||
a50bfe5054 | |||
c8983bc367 | |||
8d6d2c6704 | |||
6711f22e62 | |||
8dd9192fe3 | |||
870e0dab48 |
@ -269,7 +269,7 @@ jobs:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
# Deploy angular.io to production (if necessary)
|
||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run: yarn --cwd aio deploy-production
|
||||
|
||||
test_aio_local:
|
||||
@ -486,20 +486,43 @@ jobs:
|
||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -k "${KEY}" -out ~/.git_credentials'
|
||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||
|
||||
aio_monitoring:
|
||||
aio_monitoring_stable:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||
# which does not load the browser through the Bazel webtesting rules.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- checkout
|
||||
- *post_checkout
|
||||
- *restore_cache
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run:
|
||||
name: Check out `aio/` from the stable branch
|
||||
command: |
|
||||
git fetch origin $CI_STABLE_BRANCH
|
||||
git checkout --force origin/$CI_STABLE_BRANCH -- aio/
|
||||
- run:
|
||||
name: Run tests against https://angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Notify caretaker about failure
|
||||
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
||||
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL'
|
||||
when: on_fail
|
||||
|
||||
aio_monitoring_next:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||
# which does not load the browser through the Bazel webtesting rules.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- run:
|
||||
name: Run tests against the deployed apps
|
||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
name: Run tests against https://next.angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Notify caretaker about failure
|
||||
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
||||
@ -693,10 +716,16 @@ workflows:
|
||||
# More info is available here: https://github.com/angular/angular/issues/30101
|
||||
# aio_monitoring:
|
||||
# jobs:
|
||||
# - aio_monitoring
|
||||
# - setup
|
||||
# - aio_monitoring_stable:
|
||||
# requires:
|
||||
# - setup
|
||||
# - aio_monitoring_next:
|
||||
# requires:
|
||||
# - setup
|
||||
# triggers:
|
||||
# - schedule:
|
||||
# # Runs AIO monitoring job at 00:00AM every day.
|
||||
# # Runs AIO monitoring jobs at 00:00AM every day.
|
||||
# cron: "0 0 * * *"
|
||||
# filters:
|
||||
# branches:
|
||||
|
@ -36,3 +36,38 @@ function setSecretVar() {
|
||||
# Restore original shell options.
|
||||
eval "$originalShellOptions";
|
||||
}
|
||||
|
||||
|
||||
# Create a function to set an environment variable, when called.
|
||||
#
|
||||
# Use this function for creating setter for public environment variables that require expensive or
|
||||
# time-consuming computaions and may not be needed. When needed, you can call this function to set
|
||||
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
|
||||
#
|
||||
# Arguments:
|
||||
# - `<name>`: The name of the environment variable. The generated setter function will be
|
||||
# `setPublicVar_<name>`.
|
||||
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
|
||||
# executed lazily, it must be properly escaped. For example:
|
||||
# ```sh
|
||||
# # DO NOT do this:
|
||||
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
|
||||
#
|
||||
# # DO this isntead:
|
||||
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
|
||||
# ```
|
||||
#
|
||||
# Usage: `createPublicVarSetter <name> <code>`
|
||||
#
|
||||
# Example:
|
||||
# ```sh
|
||||
# createPublicVarSetter MY_VAR 'echo "FOO"';
|
||||
# echo $MY_VAR; # Not defined
|
||||
#
|
||||
# setPublicVar_MY_VAR;
|
||||
# source $BASH_ENV;
|
||||
# echo $MY_VAR; # FOO
|
||||
# ```
|
||||
function createPublicVarSetter() {
|
||||
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
|
||||
}
|
||||
|
@ -34,6 +34,13 @@ setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define "lazy" PUBLIC environment variables for CircleCI.
|
||||
# (I.e. functions to set an environment variable when called.)
|
||||
####################################################################################################
|
||||
createPublicVarSetter CI_STABLE_BRANCH "\$(npm info @angular/core dist-tags.latest | sed -r 's/^\\s*([0-9]+\\.[0-9]+)\\.[0-9]+.*$/\\1.x/')";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SECRET environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
|
@ -20,5 +20,6 @@ steps:
|
||||
# Add Bazel CI config
|
||||
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||
# Run tests
|
||||
- yarn bazel test //tools/ts-api-guardian:all
|
||||
- yarn bazel test //tools/ts-api-guardian:all //packages/language-service/test
|
||||
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
|
||||
- yarn bazel test //tools/public_api_guard/...
|
||||
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -5,5 +5,8 @@
|
||||
*.js eol=lf
|
||||
*.ts eol=lf
|
||||
|
||||
# API guardian patch must always use LF for tests to work
|
||||
*.patch eol=lf
|
||||
|
||||
# Must keep Windows line ending to be parsed correctly
|
||||
scripts/windows/packages.txt eol=crlf
|
||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,3 +1,25 @@
|
||||
<a name="8.0.0-rc.2"></a>
|
||||
# [8.0.0-rc.2](https://github.com/angular/angular/compare/8.0.0-rc.1...8.0.0-rc.2) (2019-04-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **language-service:** Remove tsserverlibrary from rollup globals ([#30123](https://github.com/angular/angular/issues/30123)) ([b706800](https://github.com/angular/angular/commit/b706800))
|
||||
* disable injectable-pipe migration ([#30180](https://github.com/angular/angular/issues/30180)) ([4b2fcfd](https://github.com/angular/angular/commit/4b2fcfd))
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-rc.1"></a>
|
||||
# [8.0.0-rc.1](https://github.com/angular/angular/compare/8.0.0-rc.0...8.0.0-rc.1) (2019-04-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Exclude common/upgrade* in metadata.tsconfig.json ([#30133](https://github.com/angular/angular/issues/30133)) ([6711f22](https://github.com/angular/angular/commit/6711f22))
|
||||
* **bazel:** update peerDep ranges ([#30155](https://github.com/angular/angular/issues/30155)) ([6067583](https://github.com/angular/angular/commit/6067583))
|
||||
|
||||
|
||||
|
||||
<a name="8.0.0-rc.0"></a>
|
||||
# [8.0.0-rc.0](https://github.com/angular/angular/compare/8.0.0-beta.14...8.0.0-rc.0) (2019-04-25)
|
||||
|
||||
|
@ -223,9 +223,7 @@ const routes: Routes = [{
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
**v8 update**: When you update to version 8, the [`ng update`](cli/update) command performs the transformation automatically. Prior to version 7, the `import()` syntax works in JIT mode (with view engine).
|
||||
|
||||
**Ivy:** If you are using Ivy, you must update your lazy routes to the new dynamic import syntax. See the [Ivy guide](guide/ivy) for more information.
|
||||
**v8 update**: When you update to version 8, the [`ng update`](cli/update) command performs the transformation automatically. Prior to version 7, the `import()` syntax only works in JIT mode (with view engine).
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -157,7 +157,7 @@ export class <%= classify(name) %>Service {
|
||||
|
||||
</code-example>
|
||||
|
||||
* The `classify` and `dasherize` methods are utility functions you schematic will use to transform your source template and filename.
|
||||
* The `classify` and `dasherize` methods are utility functions that your schematic will use to transform your source template and filename.
|
||||
|
||||
* The `name` is provided as a property from your factory function. It is the same `name` you defined in the schema.
|
||||
|
||||
|
@ -179,7 +179,7 @@ Some additional options (listed below) can only be set through the configuration
|
||||
|
||||
## Project asset configuration
|
||||
|
||||
Each `build` target configuration can include as `assets` array that lists files or folders you want to copy as-is when building your project.
|
||||
Each `build` target configuration can include an `assets` array that lists files or folders you want to copy as-is when building your project.
|
||||
By default, the `src/assets/` folder and `src/favicon.ico` are copied over.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
|
@ -54,9 +54,9 @@
|
||||
{"type": 301, "source": "/**/api/common/SelectControlValueAccessor-*", "destination": "/api/forms/SelectControlValueAccessor"},
|
||||
{"type": 301, "source": "/**/api/common/NgModel", "destination": "/api/forms/NgModel"},
|
||||
|
||||
// APIs under `http` package is deprecated and new APIs are available under `common/http` package
|
||||
{"type": 301, "source": "/api/http/:rest*", "destination": "/guide/deprecation#http"},
|
||||
{"type": 301, "source": "/api/http", "destination": "/guide/deprecation#http"},
|
||||
// `@angular/http` package was removed, and new `HttpClient` APIs are available under `@angular/common/http` package
|
||||
{"type": 301, "source": "/api/http/:rest*", "destination": "/guide/deprecations#http"},
|
||||
{"type": 301, "source": "/api/http", "destination": "/guide/deprecations#http"},
|
||||
|
||||
// Animations moves, renames and removals
|
||||
{"type": 301, "source": "/api/animate/:rest*", "destination": "/api/animations/:rest*"},
|
||||
|
@ -6,11 +6,8 @@ set +x -eu -o pipefail
|
||||
readonly aioDir="$(realpath $thisDir/..)"
|
||||
|
||||
readonly protractorConf="$aioDir/tests/deployment/e2e/protractor.conf.js"
|
||||
readonly minPwaScore="$1"
|
||||
readonly urls=(
|
||||
"https://angular.io/"
|
||||
"https://next.angular.io/"
|
||||
)
|
||||
readonly targetUrl="$1"
|
||||
readonly minPwaScore="$2"
|
||||
|
||||
cd "$aioDir"
|
||||
|
||||
@ -19,16 +16,14 @@ set +x -eu -o pipefail
|
||||
yarn install --frozen-lockfile --non-interactive
|
||||
yarn update-webdriver
|
||||
|
||||
# Run checks for all URLs.
|
||||
for url in "${urls[@]}"; do
|
||||
echo -e "\nChecking '$url'...\n-----"
|
||||
# Run checks for target URL.
|
||||
echo -e "\nChecking '$targetUrl'...\n-----"
|
||||
|
||||
# Run basic e2e and deployment config tests.
|
||||
yarn protractor "$protractorConf" --baseUrl "$url"
|
||||
# Run basic e2e and deployment config tests.
|
||||
yarn protractor "$protractorConf" --baseUrl "$targetUrl"
|
||||
|
||||
# Run PWA-score tests.
|
||||
yarn test-pwa-score "$url" "$minPwaScore"
|
||||
done
|
||||
# Run PWA-score tests.
|
||||
yarn test-pwa-score "$targetUrl" "$minPwaScore"
|
||||
|
||||
echo -e "\nAll checks passed!"
|
||||
)
|
||||
|
@ -22,11 +22,11 @@
|
||||
/api/core/testing/index/TestBed-class.html /api/core/testing/TestBed
|
||||
/api/core/testing/inject-function /api/core/testing/inject
|
||||
/api/core/testing/inject-function.html /api/core/testing/inject
|
||||
/api/http/Headers-class /guide/deprecation#http
|
||||
/api/http/Headers-class.html /guide/deprecation#http
|
||||
/api/http/HTTP_PROVIDERS-let /guide/deprecation#http
|
||||
/api/http/testing/index/MockBackend-class /guide/deprecation#http
|
||||
/api/http/testing/index/MockBackend-class.html /guide/deprecation#http
|
||||
/api/http/Headers-class /guide/deprecations#http
|
||||
/api/http/Headers-class.html /guide/deprecations#http
|
||||
/api/http/HTTP_PROVIDERS-let /guide/deprecations#http
|
||||
/api/http/testing/index/MockBackend-class /guide/deprecations#http
|
||||
/api/http/testing/index/MockBackend-class.html /guide/deprecations#http
|
||||
/api/platform-browser-dynamic/testing/index/platformBrowserDynamicTesting-let.html /api/platform-browser-dynamic/testing/platformBrowserDynamicTesting
|
||||
/api/platform-browser/AnimationDriver /api/animations/browser/AnimationDriver
|
||||
/api/router/Route-class /api/router/Route
|
||||
@ -95,15 +95,15 @@
|
||||
/docs/js/latest/api/forms/index/FormBuilder-class.html /api/forms/FormBuilder
|
||||
/docs/js/latest/api/forms/index/NG_VALIDATORS-let /api/forms/NG_VALIDATORS
|
||||
/docs/js/latest/api/forms/index/Validator-interface.html /api/forms/Validator
|
||||
/docs/js/latest/api/http/ConnectionBackend-class /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/Http-class.html /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/Jsonp-class.html /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/ResponseOptions-class.html /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/URLSearchParams-class /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/XHRConnection-class /guide/deprecation#http
|
||||
/docs/js/latest/api/http/index/XHRConnection-class.html /guide/deprecation#http
|
||||
/docs/js/latest/api/http/testing/index/MockConnection-class.html /guide/deprecation#http
|
||||
/docs/js/latest/api/http/testing/MockBackend-class /guide/deprecation#http
|
||||
/docs/js/latest/api/http/ConnectionBackend-class /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/Http-class.html /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/Jsonp-class.html /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/ResponseOptions-class.html /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/URLSearchParams-class /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/XHRConnection-class /guide/deprecations#http
|
||||
/docs/js/latest/api/http/index/XHRConnection-class.html /guide/deprecations#http
|
||||
/docs/js/latest/api/http/testing/index/MockConnection-class.html /guide/deprecations#http
|
||||
/docs/js/latest/api/http/testing/MockBackend-class /guide/deprecations#http
|
||||
/docs/js/latest/api/platform-browser-dynamic/index/platformBrowserDynamic-let.html /api/platform-browser-dynamic/platformBrowserDynamic
|
||||
/docs/js/latest/api/platform-browser-dynamic/testing/index/BrowserDynamicTestingModule-class.html /api/platform-browser-dynamic/testing/BrowserDynamicTestingModule
|
||||
/docs/js/latest/api/platform-browser/animations/index/BrowserAnimationsModule-class /api/platform-browser/animations/BrowserAnimationsModule
|
||||
@ -165,9 +165,9 @@
|
||||
/docs/ts/latest/api/core/testing/index/fakeAsync-function.html /api/core/testing/fakeAsync
|
||||
/docs/ts/latest/api/core/testing/index/TestComponentRenderer-class.html /api/core/testing/TestComponentRenderer
|
||||
/docs/ts/latest/api/core/testing/index/tick-function.html /api/core/testing/tick
|
||||
/docs/ts/latest/api/http/Connection-class.html /guide/deprecation#http
|
||||
/docs/ts/latest/api/http/testing/index/MockBackend-class.html /guide/deprecation#http
|
||||
/docs/ts/latest/api/http/testing/index/MockConnection-class.html /guide/deprecation#http
|
||||
/docs/ts/latest/api/http/Connection-class.html /guide/deprecations#http
|
||||
/docs/ts/latest/api/http/testing/index/MockBackend-class.html /guide/deprecations#http
|
||||
/docs/ts/latest/api/http/testing/index/MockConnection-class.html /guide/deprecations#http
|
||||
/docs/ts/latest/api/platform-browser-dynamic/index/workerAppDynamicPlatform-let.html /api/platform-browser-dynamic/workerAppDynamicPlatform
|
||||
/docs/ts/latest/api/testing/fakeAsync-function.html /api/core/testing/fakeAsync
|
||||
/docs/ts/latest/cookbook/ts-to-js.html https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html
|
||||
|
@ -3,7 +3,7 @@
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1497,
|
||||
"main": 167065,
|
||||
"main": 164945,
|
||||
"polyfills": 43626
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1440,
|
||||
"main": 30932,
|
||||
"main": 14487,
|
||||
"polyfills": 43567
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1440,
|
||||
"main": 157393,
|
||||
"main": 149205,
|
||||
"polyfills": 43567
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ function installLocalPackages() {
|
||||
readonly pwd=$(pwd)
|
||||
readonly packages=(
|
||||
animations common compiler core forms platform-browser
|
||||
platform-browser-dynamic router bazel compiler-cli language-service upgrade
|
||||
platform-browser-dynamic router bazel compiler-cli language-service
|
||||
)
|
||||
local local_packages=()
|
||||
for package in "${packages[@]}"; do
|
||||
|
@ -23,6 +23,7 @@
|
||||
"node_modules/@angular/core/schematics/**",
|
||||
"node_modules/@angular/compiler-cli/**",
|
||||
"node_modules/@angular/**/testing/**",
|
||||
"node_modules/@angular/common/upgrade*",
|
||||
"node_modules/@angular/router/upgrade*"
|
||||
]
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
"@angular/platform-browser": "packages-dist:platform-browser",
|
||||
"@angular/platform-browser-dynamic": "packages-dist:platform-browser-dynamic",
|
||||
"@angular/router": "packages-dist:router",
|
||||
"@angular/upgrade": "packages-dist:upgrade",
|
||||
"reflect-metadata": "0.1.12",
|
||||
"rxjs": "6.4.0",
|
||||
"tslib": "1.9.3",
|
||||
@ -31,4 +30,4 @@
|
||||
"postinstall": "ngc -p ./angular-metadata.tsconfig.json",
|
||||
"//": "TODO(gregmagolan): figure out how to keep dependencies here up to date with the root package.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
"zone.js": "file:../../node_modules/zone.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.800.0-beta.11",
|
||||
"@angular-devkit/build-angular": "0.800.0-beta.15",
|
||||
"@angular/cli": "file:../../node_modules/@angular/cli",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/language-service": "file:../../dist/packages-dist/language-service",
|
||||
|
@ -28,7 +28,7 @@
|
||||
"zone.js": "file:../../node_modules/zone.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.800.0-beta.11",
|
||||
"@angular-devkit/build-angular": "0.800.0-beta.15",
|
||||
"@angular/cli": "file:../../node_modules/@angular/cli",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/language-service": "file:../../dist/packages-dist/language-service",
|
||||
|
@ -28,7 +28,7 @@
|
||||
"zone.js": "file:../../node_modules/zone.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.800.0-beta.11",
|
||||
"@angular-devkit/build-angular": "0.800.0-beta.15",
|
||||
"@angular/cli": "file:../../node_modules/@angular/cli",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/language-service": "file:../../dist/packages-dist/language-service",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "8.0.0-rc.0",
|
||||
"version": "8.0.0-rc.2",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@ -107,7 +107,7 @@
|
||||
"tslint": "5.7.0",
|
||||
"typescript": "~3.4.2",
|
||||
"xhr2": "0.1.4",
|
||||
"yargs": "9.0.1",
|
||||
"yargs": "13.1.0",
|
||||
"zone.js": "^0.9.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -34,11 +34,11 @@
|
||||
"@types/node": "6.0.84",
|
||||
"semver": "^5.6.0",
|
||||
"shelljs": "0.8.2",
|
||||
"tsickle": "0.34.3"
|
||||
"tsickle": "^0.35.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/compiler-cli": "0.0.0-PLACEHOLDER",
|
||||
"@bazel/typescript": "0.27.12",
|
||||
"@bazel/typescript": "0.*",
|
||||
"typescript": ">=3.4 <3.5"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -20,6 +20,7 @@
|
||||
"node_modules/@angular/core/schematics/**",
|
||||
"node_modules/@angular/compiler-cli/**",
|
||||
"node_modules/@angular/**/testing/**",
|
||||
"node_modules/@angular/common/upgrade*",
|
||||
"node_modules/@angular/router/upgrade*"
|
||||
]
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
"shelljs": "^0.8.1",
|
||||
"source-map": "^0.6.1",
|
||||
"tslib": "^1.9.0",
|
||||
"yargs": "9.0.1"
|
||||
"yargs": "13.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/compiler": "0.0.0-PLACEHOLDER",
|
||||
|
@ -470,7 +470,7 @@ describe('compiler compliance: bindings', () => {
|
||||
…
|
||||
if (rf & 2) {
|
||||
i0.ɵɵselect(0);
|
||||
i0.ɵɵpropertyInterpolateV("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i", ctx.nine, "j");
|
||||
i0.ɵɵpropertyInterpolateV("title", ["a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i", ctx.nine, "j"]);
|
||||
i0.ɵɵselect(1);
|
||||
i0.ɵɵpropertyInterpolate8("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i");
|
||||
i0.ɵɵselect(2);
|
||||
|
@ -122,20 +122,21 @@ export function setupBazelTo(tmpDirPath: string) {
|
||||
fs.mkdirSync(nodeModulesPath);
|
||||
fs.mkdirSync(angularDirectory);
|
||||
|
||||
getAngularPackagesFromRunfiles().forEach(
|
||||
({pkgPath, name}) => { fs.symlinkSync(pkgPath, path.join(angularDirectory, name), 'dir'); });
|
||||
getAngularPackagesFromRunfiles().forEach(({pkgPath, name}) => {
|
||||
fs.symlinkSync(pkgPath, path.join(angularDirectory, name), 'junction');
|
||||
});
|
||||
|
||||
// Link typescript
|
||||
const typeScriptSource = resolveNpmTreeArtifact('npm/node_modules/typescript');
|
||||
const typescriptDest = path.join(nodeModulesPath, 'typescript');
|
||||
fs.symlinkSync(typeScriptSource, typescriptDest, 'dir');
|
||||
fs.symlinkSync(typeScriptSource, typescriptDest, 'junction');
|
||||
|
||||
// Link "rxjs" if it has been set up as a runfile. "rxjs" is linked optionally because
|
||||
// not all compiler-cli tests need "rxjs" set up.
|
||||
try {
|
||||
const rxjsSource = resolveNpmTreeArtifact('rxjs', 'index.js');
|
||||
const rxjsDest = path.join(nodeModulesPath, 'rxjs');
|
||||
fs.symlinkSync(rxjsSource, rxjsDest, 'dir');
|
||||
fs.symlinkSync(rxjsSource, rxjsDest, 'junction');
|
||||
} catch (e) {
|
||||
if (e.code !== 'MODULE_NOT_FOUND') throw e;
|
||||
}
|
||||
|
@ -155,16 +155,12 @@ export function convertPropertyBinding(
|
||||
localResolver = new DefaultLocalResolver();
|
||||
}
|
||||
const currValExpr = createCurrValueExpr(bindingId);
|
||||
const stmts: o.Statement[] = [];
|
||||
const visitor =
|
||||
new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
|
||||
const outputExpr: o.Expression = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
|
||||
const stmts: o.Statement[] = getStatementsFromVisitor(visitor, bindingId);
|
||||
|
||||
if (visitor.temporaryCount) {
|
||||
for (let i = 0; i < visitor.temporaryCount; i++) {
|
||||
stmts.push(temporaryDeclaration(bindingId, i));
|
||||
}
|
||||
} else if (form == BindingForm.TrySimple) {
|
||||
if (visitor.temporaryCount === 0 && form == BindingForm.TrySimple) {
|
||||
return new ConvertPropertyBindingResult([], outputExpr);
|
||||
}
|
||||
|
||||
@ -172,6 +168,58 @@ export function convertPropertyBinding(
|
||||
return new ConvertPropertyBindingResult(stmts, currValExpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given some expression, such as a binding or interpolation expression, and a context expression to
|
||||
* look values up on, visit each facet of the given expression resolving values from the context
|
||||
* expression such that a list of arguments can be derived from the found values that can be used as
|
||||
* arguments to an external update instruction.
|
||||
*
|
||||
* @param localResolver The resolver to use to look up expressions by name appropriately
|
||||
* @param contextVariableExpression The expression representing the context variable used to create
|
||||
* the final argument expressions
|
||||
* @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to
|
||||
* be resolved and what arguments list to build.
|
||||
* @param bindingId A name prefix used to create temporary variable names if they're needed for the
|
||||
* arguments generated
|
||||
* @returns An array of expressions that can be passed as arguments to instruction expressions like
|
||||
* `o.importExpr(R3.propertyInterpolate).callFn(result)`
|
||||
*/
|
||||
export function convertUpdateArguments(
|
||||
localResolver: LocalResolver, contextVariableExpression: o.Expression,
|
||||
expressionWithArgumentsToExtract: cdAst.AST, bindingId: string) {
|
||||
const visitor =
|
||||
new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId, undefined);
|
||||
const outputExpr: o.InvokeFunctionExpr =
|
||||
expressionWithArgumentsToExtract.visit(visitor, _Mode.Expression);
|
||||
|
||||
const stmts = getStatementsFromVisitor(visitor, bindingId);
|
||||
|
||||
// Removing the first argument, because it was a length for ViewEngine, not Ivy.
|
||||
let args = outputExpr.args.slice(1);
|
||||
if (expressionWithArgumentsToExtract instanceof cdAst.Interpolation) {
|
||||
// If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the
|
||||
// args returned to just the value, because we're going to pass it to a special instruction.
|
||||
const strings = expressionWithArgumentsToExtract.strings;
|
||||
if (args.length === 3 && strings[0] === '' && strings[1] === '') {
|
||||
// Single argument interpolate instructions.
|
||||
args = [args[1]];
|
||||
} else if (args.length >= 19) {
|
||||
// 19 or more arguments must be passed to the `interpolateV`-style instructions, which accept
|
||||
// an array of arguments
|
||||
args = [o.literalArr(args)];
|
||||
}
|
||||
}
|
||||
return {stmts, args};
|
||||
}
|
||||
|
||||
function getStatementsFromVisitor(visitor: _AstToIrVisitor, bindingId: string) {
|
||||
const stmts: o.Statement[] = [];
|
||||
for (let i = 0; i < visitor.temporaryCount; i++) {
|
||||
stmts.push(temporaryDeclaration(bindingId, i));
|
||||
}
|
||||
return stmts;
|
||||
}
|
||||
|
||||
function convertBuiltins(converterFactory: BuiltinConverterFactory, ast: cdAst.AST): cdAst.AST {
|
||||
const visitor = new _BuiltinAstConverter(converterFactory);
|
||||
return ast.visit(visitor);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {flatten, sanitizeIdentifier} from '../../compile_metadata';
|
||||
import {BindingForm, BuiltinFunctionCall, LocalResolver, convertActionBinding, convertPropertyBinding} from '../../compiler_util/expression_converter';
|
||||
import {BindingForm, BuiltinFunctionCall, LocalResolver, convertActionBinding, convertPropertyBinding, convertUpdateArguments} from '../../compiler_util/expression_converter';
|
||||
import {ConstantPool} from '../../constant_pool';
|
||||
import * as core from '../../core';
|
||||
import {AST, AstMemoryEfficientTransformer, BindingPipe, BindingType, FunctionCall, ImplicitReceiver, Interpolation, LiteralArray, LiteralMap, LiteralPrimitive, ParsedEventType, PropertyRead} from '../../expression_parser/ast';
|
||||
@ -750,23 +750,13 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
|
||||
if (inputType === BindingType.Property) {
|
||||
if (value instanceof Interpolation) {
|
||||
// Interpolated properties
|
||||
const {currValExpr} = convertPropertyBinding(
|
||||
this, implicit, value, this.bindingContext(), BindingForm.TrySimple);
|
||||
|
||||
let args: o.Expression[] = (currValExpr as any).args;
|
||||
args.shift(); // ViewEngine required a count, we don't need that.
|
||||
|
||||
// For interpolations like attr="{{foo}}", we don't need ["", foo, ""], just [foo].
|
||||
if (args.length === 3 && isEmptyStringExpression(args[0]) &&
|
||||
isEmptyStringExpression(args[2])) {
|
||||
args = [args[1]];
|
||||
}
|
||||
|
||||
this.updateInstruction(
|
||||
elementIndex, input.sourceSpan, propertyInterpolate(args.length), () => {
|
||||
return [o.literal(attrName), ...args, ...params];
|
||||
});
|
||||
elementIndex, input.sourceSpan, getPropertyInterpolationExpression(value),
|
||||
() =>
|
||||
[o.literal(attrName),
|
||||
...this.getUpdateInstructionArguments(o.variable(CONTEXT_NAME), value),
|
||||
...params]);
|
||||
|
||||
} else {
|
||||
// Bound, un-interpolated properties
|
||||
this.updateInstruction(elementIndex, input.sourceSpan, R3.property, () => {
|
||||
@ -1076,6 +1066,21 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
o.importExpr(R3.bind).callFn([valExpr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of argument expressions to pass to an update instruction expression. Also updates
|
||||
* the temp variables state with temp variables that were identified as needing to be created
|
||||
* while visiting the arguments.
|
||||
* @param contextExpression The expression for the context variable used to create arguments
|
||||
* @param value The original expression we will be resolving an arguments list from.
|
||||
*/
|
||||
private getUpdateInstructionArguments(contextExpression: o.Expression, value: AST):
|
||||
o.Expression[] {
|
||||
const {args, stmts} =
|
||||
convertUpdateArguments(this, contextExpression, value, this.bindingContext());
|
||||
this._tempVariables.push(...stmts);
|
||||
return args;
|
||||
}
|
||||
|
||||
private matchDirectives(tagName: string, elOrTpl: t.Element|t.Template) {
|
||||
if (this.directiveMatcher) {
|
||||
const selector = createCssSelector(tagName, getAttrsForDirectiveMatching(elOrTpl));
|
||||
@ -1646,16 +1651,12 @@ function interpolate(args: o.Expression[]): o.Expression {
|
||||
return o.importExpr(R3.interpolationV).callFn([o.literalArr(args)]);
|
||||
}
|
||||
|
||||
function isEmptyStringExpression(exp: o.Expression) {
|
||||
return exp instanceof o.LiteralExpr && exp.value === '';
|
||||
}
|
||||
|
||||
function propertyInterpolate(argsLength: number) {
|
||||
if (argsLength % 2 !== 1) {
|
||||
error(`Invalid propertyInterpolate argument length ${argsLength}`);
|
||||
}
|
||||
|
||||
switch (argsLength) {
|
||||
/**
|
||||
* Gets the instruction to generate for an interpolated property
|
||||
* @param interpolation An Interpolation AST
|
||||
*/
|
||||
function getPropertyInterpolationExpression(interpolation: Interpolation) {
|
||||
switch (getInterpolationArgsLength(interpolation)) {
|
||||
case 1:
|
||||
return R3.propertyInterpolate;
|
||||
case 3:
|
||||
@ -1679,6 +1680,22 @@ function propertyInterpolate(argsLength: number) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of arguments expected to be passed to a generated instruction in the case of
|
||||
* interpolation instructions.
|
||||
* @param interpolation An interpolation ast
|
||||
*/
|
||||
function getInterpolationArgsLength(interpolation: Interpolation) {
|
||||
const {expressions, strings} = interpolation;
|
||||
if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
|
||||
// If the interpolation has one interpolated value, but the prefix and suffix are both empty
|
||||
// strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
|
||||
// `textInterpolate`.
|
||||
return 1;
|
||||
} else {
|
||||
return expressions.length + strings.length;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Options that can be used to modify how a template is parsed by `parseTemplate()`.
|
||||
*/
|
||||
|
@ -3,6 +3,7 @@ load("//tools:defaults.bzl", "npm_package")
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
"migrations.json",
|
||||
"test-migrations.json",
|
||||
])
|
||||
|
||||
npm_package(
|
||||
|
@ -14,11 +14,6 @@
|
||||
"version": "8-beta",
|
||||
"description": "Warns developers if values are assigned to template variables",
|
||||
"factory": "./migrations/template-var-assignment/index"
|
||||
},
|
||||
"migration-v8-injectable-pipe": {
|
||||
"version": "8-beta",
|
||||
"description": "Migrates all Pipe classes so that they have an Injectable annotation",
|
||||
"factory": "./migrations/injectable-pipe/index"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {Replacement, RuleFailure, Rules} from 'tslint';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {InjectablePipeVisitor} from '../angular/injectable_pipe_visitor';
|
||||
import {INJECTABLE_DECORATOR_NAME, addNamedImport, getNamedImports} from '../util';
|
||||
import {INJECTABLE_DECORATOR_NAME, addImport, getNamedImports} from '../util';
|
||||
|
||||
/**
|
||||
* TSLint rule that flags `@Pipe` classes that haven't been marked as `@Injectable`.
|
||||
@ -37,8 +37,7 @@ export class Rule extends Rules.TypedRule {
|
||||
fixes.push(new Replacement(
|
||||
namedImports.getStart(), namedImports.getWidth(),
|
||||
printer.printNode(
|
||||
ts.EmitHint.Unspecified,
|
||||
addNamedImport(importDeclarationMissingImport, INJECTABLE_DECORATOR_NAME),
|
||||
ts.EmitHint.Unspecified, addImport(namedImports, INJECTABLE_DECORATOR_NAME),
|
||||
sourceFile)));
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {InjectablePipeVisitor} from './angular/injectable_pipe_visitor';
|
||||
import {INJECTABLE_DECORATOR_NAME, addNamedImport, getNamedImports} from './util';
|
||||
import {INJECTABLE_DECORATOR_NAME, addImport, getNamedImports} from './util';
|
||||
|
||||
/**
|
||||
* Runs a migration over a TypeScript project that adds an `@Injectable`
|
||||
@ -78,8 +78,7 @@ function runInjectablePipeMigration(tree: Tree, tsconfigPath: string, basePath:
|
||||
update.insertRight(
|
||||
namedImports.getStart(),
|
||||
printer.printNode(
|
||||
ts.EmitHint.Unspecified,
|
||||
addNamedImport(importDeclarationMissingImport, INJECTABLE_DECORATOR_NAME),
|
||||
ts.EmitHint.Unspecified, addImport(namedImports, INJECTABLE_DECORATOR_NAME),
|
||||
sourceFile));
|
||||
}
|
||||
}
|
||||
|
@ -12,28 +12,17 @@ import * as ts from 'typescript';
|
||||
export const INJECTABLE_DECORATOR_NAME = 'Injectable';
|
||||
|
||||
/**
|
||||
* Adds a named import to an import declaration node.
|
||||
* Adds an import to a named import node, if the import does not exist already.
|
||||
* @param node Node to which to add the import.
|
||||
* @param importName Name of the import that should be added.
|
||||
*/
|
||||
export function addNamedImport(node: ts.ImportDeclaration, importName: string) {
|
||||
const namedImports = getNamedImports(node);
|
||||
export function addImport(node: ts.NamedImports, importName: string) {
|
||||
const elements = node.elements;
|
||||
const isAlreadyImported = elements.some(element => element.name.text === importName);
|
||||
|
||||
if (namedImports && ts.isNamedImports(namedImports)) {
|
||||
const elements = namedImports.elements;
|
||||
const isAlreadyImported = elements.some(element => element.name.text === importName);
|
||||
|
||||
if (!isAlreadyImported) {
|
||||
// If there are named imports, there will be an import clause as well.
|
||||
const importClause = node.importClause !;
|
||||
const newImportClause = ts.createNamedImports(
|
||||
[...elements, ts.createImportSpecifier(undefined, ts.createIdentifier(importName))]);
|
||||
|
||||
return ts.updateImportDeclaration(
|
||||
node, node.decorators, node.modifiers,
|
||||
ts.updateImportClause(importClause, importClause.name, newImportClause),
|
||||
node.moduleSpecifier);
|
||||
}
|
||||
if (!isAlreadyImported) {
|
||||
return ts.updateNamedImports(
|
||||
node, [...elements, ts.createImportSpecifier(undefined, ts.createIdentifier(importName))]);
|
||||
}
|
||||
|
||||
return node;
|
||||
|
20
packages/core/schematics/test-migrations.json
Normal file
20
packages/core/schematics/test-migrations.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"schematics": {
|
||||
"migration-move-document": {
|
||||
"description": "Migrates DOCUMENT Injection token from platform-browser imports to common import",
|
||||
"factory": "./migrations/move-document/index"
|
||||
},
|
||||
"migration-static-queries": {
|
||||
"description": "Migrates ViewChild and ContentChild to explicit query timing",
|
||||
"factory": "./migrations/static-queries/index"
|
||||
},
|
||||
"migration-template-local-variables": {
|
||||
"description": "Warns developers if values are assigned to template variables",
|
||||
"factory": "./migrations/template-var-assignment/index"
|
||||
},
|
||||
"migration-injectable-pipe": {
|
||||
"description": "Migrates all Pipe classes so that they have an Injectable annotation",
|
||||
"factory": "./migrations/injectable-pipe/index"
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ ts_library(
|
||||
testonly = True,
|
||||
srcs = glob(["**/*.ts"]),
|
||||
data = [
|
||||
"//packages/core/schematics:migrations.json",
|
||||
"//packages/core/schematics:test-migrations.json",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core/schematics/migrations/injectable-pipe",
|
||||
|
@ -85,7 +85,10 @@ describe('Google3 injectable pipe TSLint rule', () => {
|
||||
`);
|
||||
|
||||
runTSLint();
|
||||
expect(getFile('/index.ts')).toContain('import { Pipe, Injectable } from \'@angular/core\'');
|
||||
|
||||
const content = getFile('/index.ts');
|
||||
expect(content).toContain('import { Pipe, Injectable } from \'@angular/core\'');
|
||||
expect((content.match(/import/g) || []).length).toBe(1, 'Expected only one import statement');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ describe('injectable pipe migration', () => {
|
||||
let previousWorkingDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
runner = new SchematicTestRunner('test', require.resolve('../migrations.json'));
|
||||
runner = new SchematicTestRunner('test', require.resolve('../test-migrations.json'));
|
||||
host = new TempScopedNodeJsSyncHost();
|
||||
tree = new UnitTestTree(new HostTree(host));
|
||||
|
||||
@ -70,8 +70,10 @@ describe('injectable pipe migration', () => {
|
||||
`);
|
||||
|
||||
runMigration();
|
||||
expect(tree.readContent('/index.ts'))
|
||||
.toContain('import { Pipe, Injectable } from \'@angular/core\'');
|
||||
|
||||
const content = tree.readContent('/index.ts');
|
||||
expect(content).toContain('import { Pipe, Injectable } from \'@angular/core\'');
|
||||
expect((content.match(/import/g) || []).length).toBe(1, 'Expected only one import statement');
|
||||
});
|
||||
|
||||
it('should not add an import for Injectable if it is imported already', () => {
|
||||
@ -121,5 +123,5 @@ describe('injectable pipe migration', () => {
|
||||
host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents));
|
||||
}
|
||||
|
||||
function runMigration() { runner.runSchematic('migration-v8-injectable-pipe', {}, tree); }
|
||||
function runMigration() { runner.runSchematic('migration-injectable-pipe', {}, tree); }
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ describe('move-document migration', () => {
|
||||
let previousWorkingDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
runner = new SchematicTestRunner('test', require.resolve('../migrations.json'));
|
||||
runner = new SchematicTestRunner('test', require.resolve('../test-migrations.json'));
|
||||
host = new TempScopedNodeJsSyncHost();
|
||||
tree = new UnitTestTree(new HostTree(host));
|
||||
|
||||
@ -151,5 +151,5 @@ describe('move-document migration', () => {
|
||||
host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents));
|
||||
}
|
||||
|
||||
function runMigration() { runner.runSchematic('migration-v8-move-document', {}, tree); }
|
||||
function runMigration() { runner.runSchematic('migration-move-document', {}, tree); }
|
||||
});
|
||||
|
@ -21,7 +21,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
let warnOutput: string[];
|
||||
|
||||
beforeEach(() => {
|
||||
runner = new SchematicTestRunner('test', require.resolve('../migrations.json'));
|
||||
runner = new SchematicTestRunner('test', require.resolve('../test-migrations.json'));
|
||||
host = new TempScopedNodeJsSyncHost();
|
||||
tree = new UnitTestTree(new HostTree(host));
|
||||
|
||||
@ -97,7 +97,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
}
|
||||
|
||||
async function runMigration() {
|
||||
await runner.runSchematicAsync('migration-v8-static-queries', {}, tree).toPromise();
|
||||
await runner.runSchematicAsync('migration-static-queries', {}, tree).toPromise();
|
||||
}
|
||||
|
||||
describe('ViewChild', () => {
|
||||
@ -105,7 +105,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect queries selecting elements through template reference', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: \`
|
||||
<ng-template>
|
||||
<button #myButton>My Button</button>
|
||||
@ -118,7 +118,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
private @ViewChild('myButton') query: any;
|
||||
private @ViewChild('myStaticButton') query2: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -134,7 +134,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect queries selecting ng-template as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: \`
|
||||
<ng-template #myTmpl>
|
||||
My template
|
||||
@ -143,7 +143,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
export class MyComp {
|
||||
private @ViewChild('myTmpl') query: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -157,7 +157,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect queries selecting component view providers through string token', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, Directive, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[myDirective]',
|
||||
providers: [
|
||||
@ -165,7 +165,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
]
|
||||
})
|
||||
export class MyDirective {}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[myDirective2]',
|
||||
providers: [
|
||||
@ -173,13 +173,13 @@ describe('static-queries migration with template strategy', () => {
|
||||
]
|
||||
})
|
||||
export class MyDirective2 {}
|
||||
|
||||
|
||||
@Component({templateUrl: './my-tmpl.html'})
|
||||
export class MyComp {
|
||||
private @ViewChild('my-token') query: any;
|
||||
private @ViewChild('my-token-2') query2: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, MyDirective, MyDirective2]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -202,28 +202,28 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect queries selecting component view providers using class token', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, Directive, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
export class MyService {}
|
||||
export class MyService2 {}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[myDirective]',
|
||||
providers: [MyService]
|
||||
})
|
||||
export class MyDirective {}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[myDirective2]',
|
||||
providers: [MyService2]
|
||||
})
|
||||
export class MyDirective2 {}
|
||||
|
||||
|
||||
@Component({templateUrl: './my-tmpl.html'})
|
||||
export class MyComp {
|
||||
private @ViewChild(MyService) query: any;
|
||||
private @ViewChild(MyService2) query2: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, MyDirective, MyDirective2]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -247,7 +247,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
import {HomeComponent, HomeComponent2} from './home-comp';
|
||||
|
||||
|
||||
@Component({
|
||||
template: \`
|
||||
<home-comp></home-comp>
|
||||
@ -260,20 +260,20 @@ describe('static-queries migration with template strategy', () => {
|
||||
private @ViewChild(HomeComponent) query: any;
|
||||
private @ViewChild(HomeComponent2) query2: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, HomeComponent, HomeComponent2]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
|
||||
writeFile(`/home-comp.ts`, `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'home-comp',
|
||||
template: '<span>Home</span>'
|
||||
})
|
||||
export class HomeComponent {}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'home-comp2',
|
||||
template: '<span>Home 2</span>'
|
||||
@ -294,12 +294,12 @@ describe('static-queries migration with template strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
import {MyLibComponent} from 'my-lib';
|
||||
|
||||
|
||||
@Component({templateUrl: './my-tmpl.html'})
|
||||
export class MyComp {
|
||||
private @ViewChild(MyLibComponent) query: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, MyLibComponent]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -319,12 +319,12 @@ describe('static-queries migration with template strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
import {MyLibComponent} from 'my-lib';
|
||||
|
||||
|
||||
@Component({templateUrl: './my-tmpl.html'})
|
||||
export class MyComp {
|
||||
private @ViewChild(MyLibComponent) query: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, MyLibComponent]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -345,16 +345,16 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect queries within structural directive', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, Directive, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[ngIf]'})
|
||||
export class FakeNgIf {}
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-tmpl.html'})
|
||||
export class MyComp {
|
||||
private @ViewChild('myRef') query: any;
|
||||
private @ViewChild('myRef2') query2: any;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp, FakeNgIf]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -375,14 +375,14 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should detect inherited queries', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
export class BaseClass {
|
||||
@ViewChild('myRef') query: any;
|
||||
}
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-tmpl.html'})
|
||||
export class MyComp extends BaseClass {}
|
||||
|
||||
|
||||
@NgModule({declarations: [MyComp]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -400,7 +400,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should add a todo if a query is not declared in any component', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild, SomeToken} from '@angular/core';
|
||||
|
||||
|
||||
export class NotAComponent {
|
||||
@ViewChild('myRef', {read: SomeToken}) query: any;
|
||||
}
|
||||
@ -420,17 +420,17 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should add a todo if a query is used multiple times with different timing', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, NgModule, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
export class BaseClass {
|
||||
@ViewChild('myRef') query: any;
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<ng-template><p #myRef></p></ng-template>'})
|
||||
export class FirstComp extends BaseClass {}
|
||||
|
||||
|
||||
@Component({template: '<span #myRef></span>'})
|
||||
export class SecondComp extends BaseClass {}
|
||||
|
||||
|
||||
@NgModule({declarations: [FirstComp, SecondComp]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
@ -448,12 +448,12 @@ describe('static-queries migration with template strategy', () => {
|
||||
it('should gracefully exit migration if queries could not be analyzed', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<ng-template><p #myRef></p></ng-template>'})
|
||||
export class MyComp {
|
||||
@ViewChild('myRef') query: any;
|
||||
}
|
||||
|
||||
|
||||
// **NOTE**: Analysis will fail as there is no "NgModule" that declares the component.
|
||||
`);
|
||||
|
||||
@ -533,7 +533,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
writeFile('/src/test.ts', `
|
||||
import {ViewChild} from '@angular/core';
|
||||
import {AppComponent} from './app.component';
|
||||
|
||||
|
||||
@Component({template: '<span #test>Test</span>'})
|
||||
class MyTestComponent {
|
||||
@ViewChild('test') query: any;
|
||||
@ -542,7 +542,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
|
||||
writeFile('/src/app.component.ts', `
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class AppComponent {
|
||||
@ViewChild('test') query: any;
|
||||
@ -552,7 +552,7 @@ describe('static-queries migration with template strategy', () => {
|
||||
writeFile('/src/app.module.ts', `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {AppComponent} from './app.component';
|
||||
|
||||
|
||||
@NgModule({declarations: [AppComponent]})
|
||||
export class MyModule {}
|
||||
`);
|
||||
|
@ -26,7 +26,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
afterAll(() => process.env['NG_STATIC_QUERY_USAGE_STRATEGY'] = '');
|
||||
|
||||
beforeEach(() => {
|
||||
runner = new SchematicTestRunner('test', require.resolve('../migrations.json'));
|
||||
runner = new SchematicTestRunner('test', require.resolve('../test-migrations.json'));
|
||||
host = new TempScopedNodeJsSyncHost();
|
||||
tree = new UnitTestTree(new HostTree(host));
|
||||
|
||||
@ -58,11 +58,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark view queries used in "ngAfterContentInit" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@ViewChild('test') query: any;
|
||||
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
@ -78,11 +78,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark view queries used in "ngAfterContentChecked" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@ViewChild('test') query: any;
|
||||
|
||||
|
||||
ngAfterContentChecked() {
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
@ -102,11 +102,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark content queries used in "ngAfterContentInit" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ContentChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@ContentChild('test') query: any;
|
||||
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
@ -122,11 +122,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark content queries used in "ngAfterContentChecked" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ContentChild} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@ContentChild('test') query: any;
|
||||
|
||||
|
||||
ngAfterContentChecked() {
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
@ -145,19 +145,19 @@ describe('static-queries migration with usage strategy', () => {
|
||||
}
|
||||
|
||||
async function runMigration() {
|
||||
await runner.runSchematicAsync('migration-v8-static-queries', {}, tree).toPromise();
|
||||
await runner.runSchematicAsync('migration-static-queries', {}, tree).toPromise();
|
||||
}
|
||||
|
||||
function createQueryTests(queryType: 'ViewChild' | 'ContentChild') {
|
||||
it('should mark queries as dynamic', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') unused: any;
|
||||
@${queryType}('dynamic') dynamic: any;
|
||||
|
||||
|
||||
onClick() {
|
||||
this.dynamicQuery.classList.add('test');
|
||||
}
|
||||
@ -175,13 +175,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark queries used in "ngOnChanges" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngOnChanges() {
|
||||
this.query.classList.add('test');
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
}
|
||||
`);
|
||||
@ -195,13 +195,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark queries used in "ngOnInit" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.query.classList.add('test');
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
}
|
||||
`);
|
||||
@ -215,13 +215,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark queries used in "ngDoCheck" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngDoCheck() {
|
||||
this.query.classList.add('test');
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
}
|
||||
`);
|
||||
@ -235,11 +235,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should keep existing query options when updating timing', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test', { /* test */ read: null }) query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.query.classList.add('test');
|
||||
}
|
||||
@ -255,7 +255,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not overwrite existing explicit query timing', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test', {static: /* untouched */ someVal}) query: any;
|
||||
@ -271,26 +271,26 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries used in deep method chain', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
// We intentionally add this comma for the second parameter in order
|
||||
// to ensure that the migration does not incorrectly create an invalid
|
||||
// decorator call with three parameters. e.g. "ViewQuery('test', {...}, )"
|
||||
@${queryType}('test', ) query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.a();
|
||||
}
|
||||
|
||||
|
||||
a() {
|
||||
this.b();
|
||||
}
|
||||
|
||||
|
||||
b() {
|
||||
this.c();
|
||||
}
|
||||
|
||||
|
||||
c() {
|
||||
console.log(this.query);
|
||||
}
|
||||
@ -306,16 +306,16 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should properly exit if recursive function is analyzed', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.recursive();
|
||||
}
|
||||
|
||||
recursive() {
|
||||
|
||||
recursive() {
|
||||
this.recursive();
|
||||
}
|
||||
}
|
||||
@ -330,27 +330,27 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries used in newly instantiated classes', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
@${queryType}('test') query2: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
new A(this);
|
||||
|
||||
|
||||
new class Inline {
|
||||
constructor(private ctx: MyComp) {
|
||||
this.a();
|
||||
}
|
||||
|
||||
|
||||
a() {
|
||||
this.ctx.query2.useStatically();
|
||||
}
|
||||
}(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class A {
|
||||
constructor(ctx: MyComp) {
|
||||
ctx.query.test();
|
||||
@ -369,16 +369,16 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries used in parenthesized new expressions', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
new ((A))(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class A {
|
||||
constructor(ctx: MyComp) {
|
||||
ctx.query.test();
|
||||
@ -395,11 +395,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries in lifecycle hook with string literal name', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
'ngOnInit'() {
|
||||
this.query.test();
|
||||
}
|
||||
@ -415,19 +415,19 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect static queries within nested inheritance', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
}
|
||||
|
||||
|
||||
export class A extends MyComp {}
|
||||
export class B extends A {
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.query.testFn();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
`);
|
||||
|
||||
@ -440,11 +440,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect static queries used within input setters', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, Input, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
@Input()
|
||||
get myVal() { return null; }
|
||||
set myVal(newVal: any) {
|
||||
@ -462,14 +462,14 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect inputs defined in metadata', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<span #test></span>',
|
||||
inputs: ["myVal"],
|
||||
})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
// We don't use the input decorator here as we want to verify
|
||||
// that it properly detects the input through the component metadata.
|
||||
get myVal() { return null; }
|
||||
@ -488,14 +488,14 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect aliased inputs declared in metadata', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<span #test></span>',
|
||||
inputs: ['prop: publicName'],
|
||||
})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
set prop(val: any) {
|
||||
this.query.test();
|
||||
}
|
||||
@ -511,11 +511,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark query as static if query is used in non-input setter', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
set myProperty(val: any) {
|
||||
this.query.test();
|
||||
}
|
||||
@ -531,13 +531,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect input decorator on setter', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Input, Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
get myProperty() { return null; }
|
||||
|
||||
|
||||
// Usually the decorator is set on the get accessor, but it's also possible
|
||||
// to declare the input on the setter. This ensures that it is handled properly.
|
||||
@Input()
|
||||
@ -556,7 +556,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect setter inputs in derived classes', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<span #test></span>',
|
||||
inputs: ['childSetter'],
|
||||
@ -564,7 +564,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
export class MyComp {
|
||||
protected @${queryType}('test') query: any;
|
||||
}
|
||||
|
||||
|
||||
export class B extends MyComp {
|
||||
set childSetter(newVal: any) {
|
||||
this.query.test();
|
||||
@ -581,7 +581,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should properly detect static query in external derived class', async() => {
|
||||
writeFile('/src/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
@ -590,7 +590,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
|
||||
writeFile('/src/external.ts', `
|
||||
import {MyComp} from './index';
|
||||
|
||||
|
||||
export class ExternalComp extends MyComp {
|
||||
ngOnInit() {
|
||||
this.query.test();
|
||||
@ -614,30 +614,30 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark queries used in promises as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
private @${queryType}('test') query2: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
const a = Promise.resolve();
|
||||
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
this.query.doSomething();
|
||||
});
|
||||
|
||||
|
||||
Promise.reject().catch(() => {
|
||||
this.query.doSomething();
|
||||
});
|
||||
|
||||
|
||||
a.then(() => {}).then(() => {
|
||||
this.query.doSomething();
|
||||
});
|
||||
|
||||
|
||||
Promise.resolve().then(this.createPromiseCb());
|
||||
}
|
||||
|
||||
|
||||
createPromiseCb() {
|
||||
this.query2.doSomething();
|
||||
return () => { /* empty callback */}
|
||||
@ -656,19 +656,19 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should handle function callbacks which statically access queries', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
ngOnInit() {
|
||||
this.callSync(() => this.query.doSomething());
|
||||
}
|
||||
|
||||
|
||||
callSync(cb: Function) {
|
||||
this.callSync2(cb);
|
||||
}
|
||||
|
||||
|
||||
callSync2(cb: Function) {
|
||||
cb();
|
||||
}
|
||||
@ -686,12 +686,12 @@ describe('static-queries migration with usage strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
import {External} from './external';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
ngOnInit() {
|
||||
new External(() => this.query.doSomething());
|
||||
}
|
||||
}
|
||||
@ -700,7 +700,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
writeFile('/external.ts', `
|
||||
export class External {
|
||||
constructor(cb: () => void) {
|
||||
// Add extra parentheses to ensure that expression is unwrapped.
|
||||
// Add extra parentheses to ensure that expression is unwrapped.
|
||||
((cb))();
|
||||
}
|
||||
}
|
||||
@ -715,21 +715,21 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should handle nested functions with arguments from parent closure', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
ngOnInit() {
|
||||
this.callSync(() => this.query.doSomething());
|
||||
}
|
||||
|
||||
|
||||
callSync(cb: Function) {
|
||||
function callSyncNested() {
|
||||
// The "cb" identifier comes from the "callSync" function.
|
||||
cb();
|
||||
}
|
||||
|
||||
|
||||
callSyncNested();
|
||||
}
|
||||
}
|
||||
@ -744,22 +744,22 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark queries used in setTimeout as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
private @${queryType}('test') query2: any;
|
||||
private @${queryType}('test') query3: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
setTimeout(function() {
|
||||
this.query.doSomething();
|
||||
});
|
||||
|
||||
|
||||
setTimeout(createCallback(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createCallback(instance: MyComp) {
|
||||
instance.query2.doSomething();
|
||||
return () => instance.query3.doSomething();
|
||||
@ -779,13 +779,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark queries used in "addEventListener" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ElementRef, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
constructor(private elementRef: ElementRef) {}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.elementRef.addEventListener(() => {
|
||||
this.query.classList.add('test');
|
||||
@ -803,13 +803,13 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark queries used in "requestAnimationFrame" as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ElementRef, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
constructor(private elementRef: ElementRef) {}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
requestAnimationFrame(() => {
|
||||
this.query.classList.add('test');
|
||||
@ -827,17 +827,17 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark queries used in immediately-invoked function expression as static', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
private @${queryType}('test') query2: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
(() => {
|
||||
this.query.usedStatically();
|
||||
})();
|
||||
|
||||
|
||||
(function(ctx) {
|
||||
ctx.query2.useStatically();
|
||||
})(this);
|
||||
@ -857,11 +857,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
import {externalFn} from './external';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
externalFn(this);
|
||||
}
|
||||
@ -870,7 +870,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
|
||||
writeFile('/external.ts', `
|
||||
import {MyComp} from './index';
|
||||
|
||||
|
||||
export function externalFn(ctx: MyComp) {
|
||||
ctx.query.usedStatically();
|
||||
}
|
||||
@ -885,15 +885,15 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect static queries used through getter property access', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
get myProp() {
|
||||
return this.query.myValue;
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myProp.test();
|
||||
}
|
||||
@ -910,17 +910,17 @@ describe('static-queries migration with usage strategy', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
import {External} from './external';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
private external = new External(this);
|
||||
|
||||
|
||||
get myProp() {
|
||||
return this.query.myValue;
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
console.log(this.external.query);
|
||||
}
|
||||
@ -929,10 +929,10 @@ describe('static-queries migration with usage strategy', () => {
|
||||
|
||||
writeFile('/external.ts', `
|
||||
import {MyComp} from './index';
|
||||
|
||||
|
||||
export class External {
|
||||
constructor(private comp: MyComp) {}
|
||||
|
||||
|
||||
set query() { /** noop */ }
|
||||
get query() { return this.comp.query; }
|
||||
}
|
||||
@ -947,16 +947,16 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should not mark queries as static if a value is assigned to accessor property', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
set myProp(value: any) { /* noop */}
|
||||
get myProp() {
|
||||
return this.query.myValue;
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myProp = true;
|
||||
}
|
||||
@ -972,16 +972,16 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should mark queries as static if non-input setter uses query', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
get myProp() { return null; }
|
||||
set myProp(value: any) {
|
||||
this.query.doSomething();
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myProp = 'newValue';
|
||||
}
|
||||
@ -997,17 +997,17 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should check setter and getter when using compound assignment', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
private @${queryType}('test') query2: any;
|
||||
|
||||
|
||||
get myProp() { return this.query2 }
|
||||
set myProp(value: any) {
|
||||
this.query.doSomething();
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myProp *= 5;
|
||||
}
|
||||
@ -1025,14 +1025,14 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should check getters when using comparison operator in binary expression', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
||||
|
||||
get myProp() { return this.query }
|
||||
set myProp(value: any) { /* noop */ }
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
if (this.myProp === 3) {
|
||||
// noop
|
||||
@ -1050,29 +1050,29 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should check derived abstract class methods', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export abstract class RootBaseClass {
|
||||
abstract getQuery(): any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.getQuery().doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export abstract class BaseClass extends RootBaseClass {
|
||||
abstract getQuery2(): any;
|
||||
|
||||
|
||||
getQuery() {
|
||||
this.getQuery2();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class Subclass extends BaseClass {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
getQuery2(): any {
|
||||
return this.query;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
`);
|
||||
@ -1086,25 +1086,25 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries accessed through deep abstract class method', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export abstract class RootBaseClass {
|
||||
abstract getQuery(): any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.getQuery().doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export abstract class BaseClass extends RootBaseClass {
|
||||
/* additional layer of indirection */
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class Subclass extends BaseClass {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
getQuery(): any {
|
||||
return this.query;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
`);
|
||||
@ -1118,19 +1118,19 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries accessed through abstract property getter', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export abstract class BaseClass {
|
||||
abstract myQuery: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myQuery.doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class Subclass extends BaseClass {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
get myQuery() { return this.query; }
|
||||
}
|
||||
`);
|
||||
@ -1144,19 +1144,19 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect queries accessed through abstract property setter', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export abstract class BaseClass {
|
||||
abstract myQuery: any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.myQuery = "trigger";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class Subclass extends BaseClass {
|
||||
@${queryType}('test') query: any;
|
||||
|
||||
|
||||
set myQuery(val: any) { this.query.doSomething() }
|
||||
get myQuery() { /* noop */ }
|
||||
}
|
||||
@ -1171,27 +1171,27 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect query usage in abstract class methods accessing inherited query', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export abstract class RootBaseClass {
|
||||
abstract getQuery(): any;
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.getQuery().doSomething();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export abstract class BaseClass extends RootBaseClass {
|
||||
@${queryType}('test') query: any;
|
||||
abstract getQuery2(): any;
|
||||
|
||||
|
||||
getQuery() {
|
||||
this.getQuery2();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class Subclass extends BaseClass {
|
||||
|
||||
|
||||
getQuery2(): any {
|
||||
return this.query;
|
||||
}
|
||||
@ -1207,7 +1207,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect query usage within component template', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent {
|
||||
@${queryType}('test') query: any;
|
||||
@ -1228,7 +1228,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect query usage with nested property read within component template', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent {
|
||||
@${queryType}('test') query: any;
|
||||
@ -1250,7 +1250,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent {
|
||||
@${queryType}('test') query: any;
|
||||
@ -1274,7 +1274,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent {
|
||||
myObject: {someProp: any};
|
||||
@ -1299,7 +1299,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should ignore queries accessed within <ng-template> element', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent {
|
||||
@${queryType}('test') query: any;
|
||||
@ -1308,7 +1308,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
|
||||
writeFile(`/my-template.html`, `
|
||||
<foo #test></foo>
|
||||
|
||||
|
||||
<ng-template>
|
||||
<my-comp [myInput]="query"></my-comp>
|
||||
</ng-template>
|
||||
@ -1323,11 +1323,11 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should detect inherited queries used in templates', async() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
export class ParentClass {
|
||||
@${queryType}('test') query: any;
|
||||
}
|
||||
|
||||
|
||||
@Component({templateUrl: 'my-template.html'})
|
||||
export class MyComponent extends ParentClass {}
|
||||
`);
|
||||
@ -1346,7 +1346,7 @@ describe('static-queries migration with usage strategy', () => {
|
||||
it('should properly handle multiple tsconfig files', async() => {
|
||||
writeFile('/src/index.ts', `
|
||||
import {Component, ${queryType}} from '@angular/core';
|
||||
|
||||
|
||||
@Component({template: '<span #test></span>'})
|
||||
export class MyComp {
|
||||
private @${queryType}('test') query: any;
|
||||
|
@ -21,7 +21,7 @@ describe('template variable assignment migration', () => {
|
||||
let warnOutput: string[];
|
||||
|
||||
beforeEach(() => {
|
||||
runner = new SchematicTestRunner('test', require.resolve('../migrations.json'));
|
||||
runner = new SchematicTestRunner('test', require.resolve('../test-migrations.json'));
|
||||
host = new TempScopedNodeJsSyncHost();
|
||||
tree = new UnitTestTree(new HostTree(host));
|
||||
|
||||
@ -58,14 +58,12 @@ describe('template variable assignment migration', () => {
|
||||
host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents));
|
||||
}
|
||||
|
||||
function runMigration() {
|
||||
runner.runSchematic('migration-v8-template-local-variables', {}, tree);
|
||||
}
|
||||
function runMigration() { runner.runSchematic('migration-template-local-variables', {}, tree); }
|
||||
|
||||
it('should warn for two-way data binding variable assignment', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<cmp *ngFor="let optionName of options" [(opt)]="optionName"></cmp>',
|
||||
})
|
||||
@ -81,7 +79,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should warn for two-way data binding assigning to "as" variable', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './tmpl.html',
|
||||
})
|
||||
@ -103,7 +101,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should warn for bound event assignments to "as" variable', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -127,7 +125,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should warn for bound event assignments to template "let" variables', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -151,7 +149,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should not warn for bound event assignments to component property', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -168,7 +166,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should not warn for bound event assignments to template variable object property', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -188,7 +186,7 @@ describe('template variable assignment migration', () => {
|
||||
() => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -213,7 +211,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should not warn for property writes with template variable name but different scope', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -236,7 +234,7 @@ describe('template variable assignment migration', () => {
|
||||
it('should not throw an error if a detected template fails parsing', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './sub_dir/tmpl.html',
|
||||
})
|
||||
@ -253,12 +251,12 @@ describe('template variable assignment migration', () => {
|
||||
it('should be able to report multiple templates within the same source file', () => {
|
||||
writeFile('/index.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<ng-template let-one><a (sayHello)="one=true"></a></ng-template>',
|
||||
})
|
||||
export class MyComp {}
|
||||
|
||||
|
||||
@Component({
|
||||
template: '<ng-template let-two><b (greet)="two=true"></b></ng-template>',
|
||||
})
|
||||
|
@ -71,10 +71,23 @@ export function injectInjectorOnly<T>(
|
||||
/**
|
||||
* Generated instruction: Injects a token from the currently active injector.
|
||||
*
|
||||
* WARNING: This function is meant to be generated by the Ivy compiler, and is not meant for
|
||||
* developer consumption!
|
||||
* Must be used in the context of a factory function such as one defined for an
|
||||
* `InjectionToken`. Throws an error if not called from such a context.
|
||||
*
|
||||
* https://github.com/angular/angular/blob/master/packages/core/src/render3/DELTA_INSTRUCTIONS.md
|
||||
* (Additional documentation moved to `inject`, as it is the public API, and an alias for this instruction)
|
||||
*
|
||||
* @see inject
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>): T;
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags): T|null;
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|
|
||||
null {
|
||||
return (_injectImplementation || injectInjectorOnly)(token, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a token from the currently active injector.
|
||||
*
|
||||
* Must be used in the context of a factory function such as one defined for an
|
||||
* `InjectionToken`. Throws an error if not called from such a context.
|
||||
@ -97,17 +110,6 @@ export function injectInjectorOnly<T>(
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>): T;
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags): T|null;
|
||||
export function ɵɵinject<T>(token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|
|
||||
null {
|
||||
return (_injectImplementation || injectInjectorOnly)(token, flags);
|
||||
}
|
||||
/**
|
||||
* @deprecated in v8, delete after v10. This API should be used only be generated code, and that
|
||||
* code should now use ɵɵinject instead.
|
||||
* @publicApi
|
||||
*/
|
||||
export const inject = ɵɵinject;
|
||||
|
||||
/**
|
||||
|
@ -110,6 +110,8 @@ function listenerInternal(
|
||||
ngDevMode && assertNodeOfPossibleTypes(
|
||||
tNode, TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer);
|
||||
|
||||
let processOutputs = true;
|
||||
|
||||
// add native event listener - applicable to elements only
|
||||
if (tNode.type === TNodeType.Element) {
|
||||
const native = getNativeByTNode(tNode, lView) as RElement;
|
||||
@ -149,6 +151,7 @@ function listenerInternal(
|
||||
// Attach a new listener at the head of the coalesced listeners list.
|
||||
(<any>listenerFn).__ngNextListenerFn__ = (<any>existingListener).__ngNextListenerFn__;
|
||||
(<any>existingListener).__ngNextListenerFn__ = listenerFn;
|
||||
processOutputs = false;
|
||||
} else {
|
||||
// The first argument of `listen` function in Procedural Renderer is:
|
||||
// - either a target name (as a string) in case of global target (window, document, body)
|
||||
@ -180,7 +183,7 @@ function listenerInternal(
|
||||
|
||||
const outputs = tNode.outputs;
|
||||
let props: PropertyAliasValue|undefined;
|
||||
if (outputs && (props = outputs[eventName])) {
|
||||
if (processOutputs && outputs && (props = outputs[eventName])) {
|
||||
const propsLength = props.length;
|
||||
if (propsLength) {
|
||||
const lCleanup = getCleanup(lView);
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
import {assertEqual, assertLessThan} from '../../util/assert';
|
||||
import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings';
|
||||
import {SanitizerFn} from '../interfaces/sanitization';
|
||||
import {BINDING_INDEX, TVIEW} from '../interfaces/view';
|
||||
import {getLView, getSelectedIndex} from '../state';
|
||||
import {NO_CHANGE} from '../tokens';
|
||||
@ -15,6 +16,7 @@ import {renderStringify} from '../util/misc_utils';
|
||||
import {TsickleIssue1009, elementPropertyInternal, storeBindingMetadata} from './shared';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create interpolation bindings with a variable number of expressions.
|
||||
*
|
||||
@ -290,12 +292,6 @@ export function ɵɵinterpolation8(
|
||||
/// NEW INSTRUCTIONS
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Shared reference to a string, used in `ɵɵpropertyInterpolate`.
|
||||
*/
|
||||
const EMPTY_STRING = '';
|
||||
|
||||
/**
|
||||
*
|
||||
* Update an interpolated property on an element with a lone bound value
|
||||
@ -321,11 +317,13 @@ const EMPTY_STRING = '';
|
||||
* @param prefix Static value used for concatenation only.
|
||||
* @param v0 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate(propName: string, v0: any): TsickleIssue1009 {
|
||||
ɵɵpropertyInterpolate1(propName, EMPTY_STRING, v0, EMPTY_STRING);
|
||||
export function ɵɵpropertyInterpolate(
|
||||
propName: string, v0: any, sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);
|
||||
return ɵɵpropertyInterpolate;
|
||||
}
|
||||
|
||||
@ -354,13 +352,15 @@ export function ɵɵpropertyInterpolate(propName: string, v0: any): TsickleIssue
|
||||
* @param prefix Static value used for concatenation only.
|
||||
* @param v0 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate1(
|
||||
propName: string, prefix: string, v0: any, suffix: string): TsickleIssue1009 {
|
||||
propName: string, prefix: string, v0: any, suffix: string,
|
||||
sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolation1(prefix, v0, suffix));
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolation1(prefix, v0, suffix), sanitizer);
|
||||
return ɵɵpropertyInterpolate1;
|
||||
}
|
||||
|
||||
@ -390,14 +390,15 @@ export function ɵɵpropertyInterpolate1(
|
||||
* @param i0 Static value used for concatenation only.
|
||||
* @param v1 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate2(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any,
|
||||
suffix: string): TsickleIssue1009 {
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string,
|
||||
sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolation2(prefix, v0, i0, v1, suffix));
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolation2(prefix, v0, i0, v1, suffix), sanitizer);
|
||||
return ɵɵpropertyInterpolate2;
|
||||
}
|
||||
|
||||
@ -430,14 +431,16 @@ export function ɵɵpropertyInterpolate2(
|
||||
* @param i1 Static value used for concatenation only.
|
||||
* @param v2 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate3(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,
|
||||
suffix: string): TsickleIssue1009 {
|
||||
suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix));
|
||||
elementPropertyInternal(
|
||||
index, propName, ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix), sanitizer);
|
||||
return ɵɵpropertyInterpolate3;
|
||||
}
|
||||
|
||||
@ -472,15 +475,16 @@ export function ɵɵpropertyInterpolate3(
|
||||
* @param i2 Static value used for concatenation only.
|
||||
* @param v3 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate4(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||
v3: any, suffix: string): TsickleIssue1009 {
|
||||
v3: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(
|
||||
index, propName, ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix));
|
||||
index, propName, ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix), sanitizer);
|
||||
return ɵɵpropertyInterpolate4;
|
||||
}
|
||||
|
||||
@ -517,15 +521,17 @@ export function ɵɵpropertyInterpolate4(
|
||||
* @param i3 Static value used for concatenation only.
|
||||
* @param v4 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate5(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||
v3: any, i3: string, v4: any, suffix: string): TsickleIssue1009 {
|
||||
v3: any, i3: string, v4: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(
|
||||
index, propName, ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix));
|
||||
index, propName, ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix),
|
||||
sanitizer);
|
||||
return ɵɵpropertyInterpolate5;
|
||||
}
|
||||
|
||||
@ -564,16 +570,18 @@ export function ɵɵpropertyInterpolate5(
|
||||
* @param i4 Static value used for concatenation only.
|
||||
* @param v5 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate6(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||
v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): TsickleIssue1009 {
|
||||
v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string,
|
||||
sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(
|
||||
index, propName,
|
||||
ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix));
|
||||
index, propName, ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix),
|
||||
sanitizer);
|
||||
return ɵɵpropertyInterpolate6;
|
||||
}
|
||||
|
||||
@ -614,17 +622,19 @@ export function ɵɵpropertyInterpolate6(
|
||||
* @param i5 Static value used for concatenation only.
|
||||
* @param v6 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate7(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any,
|
||||
suffix: string): TsickleIssue1009 {
|
||||
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string,
|
||||
sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(
|
||||
index, propName,
|
||||
ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix));
|
||||
ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix),
|
||||
sanitizer);
|
||||
return ɵɵpropertyInterpolate7;
|
||||
}
|
||||
|
||||
@ -667,17 +677,19 @@ export function ɵɵpropertyInterpolate7(
|
||||
* @param i6 Static value used for concatenation only.
|
||||
* @param v7 Value checked for change.
|
||||
* @param suffix Static value used for concatenation only.
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolate8(
|
||||
propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,
|
||||
suffix: string): TsickleIssue1009 {
|
||||
suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
elementPropertyInternal(
|
||||
index, propName,
|
||||
ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix));
|
||||
ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix),
|
||||
sanitizer);
|
||||
return ɵɵpropertyInterpolate8;
|
||||
}
|
||||
|
||||
@ -707,12 +719,14 @@ export function ɵɵpropertyInterpolate8(
|
||||
* @param values The a collection of values and the strings inbetween those values, beginning with a
|
||||
* string prefix and ending with a string suffix.
|
||||
* (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
|
||||
* @param sanitizer An optional sanitizer function
|
||||
* @returns itself, so that it may be chained.
|
||||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵpropertyInterpolateV(propName: string, values: any[]): TsickleIssue1009 {
|
||||
export function ɵɵpropertyInterpolateV(
|
||||
propName: string, values: any[], sanitizer?: SanitizerFn): TsickleIssue1009 {
|
||||
const index = getSelectedIndex();
|
||||
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolationV(values));
|
||||
elementPropertyInternal(index, propName, ɵɵinterpolationV(values), sanitizer);
|
||||
return ɵɵpropertyInterpolateV;
|
||||
}
|
||||
|
@ -905,15 +905,20 @@ export function setNgReflectProperty(
|
||||
attrName = normalizeDebugBindingName(attrName);
|
||||
const debugValue = normalizeDebugBindingValue(value);
|
||||
if (type === TNodeType.Element) {
|
||||
isProceduralRenderer(renderer) ?
|
||||
renderer.setAttribute((element as RElement), attrName, debugValue) :
|
||||
(element as RElement).setAttribute(attrName, debugValue);
|
||||
} else if (value !== undefined) {
|
||||
const value = `bindings=${JSON.stringify({[attrName]: debugValue}, null, 2)}`;
|
||||
if (isProceduralRenderer(renderer)) {
|
||||
renderer.setValue((element as RComment), value);
|
||||
if (value == null) {
|
||||
isProceduralRenderer(renderer) ? renderer.removeAttribute((element as RElement), attrName) :
|
||||
(element as RElement).removeAttribute(attrName);
|
||||
} else {
|
||||
(element as RComment).textContent = value;
|
||||
isProceduralRenderer(renderer) ?
|
||||
renderer.setAttribute((element as RElement), attrName, debugValue) :
|
||||
(element as RElement).setAttribute(attrName, debugValue);
|
||||
}
|
||||
} else {
|
||||
const textContent = `bindings=${JSON.stringify({[attrName]: debugValue}, null, 2)}`;
|
||||
if (isProceduralRenderer(renderer)) {
|
||||
renderer.setValue((element as RComment), textContent);
|
||||
} else {
|
||||
(element as RComment).textContent = textContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import {Type} from '../../interface/type';
|
||||
import {registerNgModuleType} from '../../linker/ng_module_factory_loader';
|
||||
import {Component} from '../../metadata';
|
||||
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
|
||||
import {flatten} from '../../util/array_utils';
|
||||
import {assertDefined} from '../../util/assert';
|
||||
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
|
||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
|
||||
@ -158,6 +159,7 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
|
||||
const errors: string[] = [];
|
||||
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
|
||||
const imports = maybeUnwrapFn(ngModuleDef.imports);
|
||||
flatten(imports, unwrapModuleWithProvidersImports).forEach(verifySemanticsOfNgModuleDef);
|
||||
const exports = maybeUnwrapFn(ngModuleDef.exports);
|
||||
declarations.forEach(verifyDeclarationsHaveDefinitions);
|
||||
const combinedDeclarations: Type<any>[] = [
|
||||
@ -464,18 +466,6 @@ export function transitiveScopesFor<T>(
|
||||
return scopes;
|
||||
}
|
||||
|
||||
function flatten<T>(values: any[], mapFn?: (value: T) => any): Type<T>[] {
|
||||
const out: Type<T>[] = [];
|
||||
values.forEach(value => {
|
||||
if (Array.isArray(value)) {
|
||||
out.push(...flatten<T>(value, mapFn));
|
||||
} else {
|
||||
out.push(mapFn ? mapFn(value) : value);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): Type<any> {
|
||||
if (isModuleWithProviders(value)) {
|
||||
return value.ngModule;
|
||||
|
@ -21,7 +21,7 @@ export function addAllToArray(items: any[], arr: any[]) {
|
||||
/**
|
||||
* Flattens an array in non-recursive way. Input arrays are not modified.
|
||||
*/
|
||||
export function flatten(list: any[]): any[] {
|
||||
export function flatten(list: any[], mapFn?: (value: any) => any): any[] {
|
||||
const result: any[] = [];
|
||||
let i = 0;
|
||||
while (i < list.length) {
|
||||
@ -34,7 +34,7 @@ export function flatten(list: any[]): any[] {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
result.push(item);
|
||||
result.push(mapFn ? mapFn(item) : item);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, InjectionToken} from '@angular/core';
|
||||
import {Component, ComponentFactoryResolver, ComponentRef, InjectionToken, NgModule, Type, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
|
||||
describe('component', () => {
|
||||
@ -49,4 +50,42 @@ describe('component', () => {
|
||||
expect(destroyCalls).toBe(1, 'Expected `ngOnDestroy` to only be called once.');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support entry components from another module', () => {
|
||||
@Component({selector: 'other-component', template: `bar`})
|
||||
class OtherComponent {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [OtherComponent],
|
||||
exports: [OtherComponent],
|
||||
entryComponents: [OtherComponent]
|
||||
})
|
||||
class OtherModule {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'test_component',
|
||||
template: `foo|<ng-template #vc></ng-template>`,
|
||||
entryComponents: [OtherComponent]
|
||||
})
|
||||
class TestComponent {
|
||||
@ViewChild('vc', {read: ViewContainerRef}) vcref !: ViewContainerRef;
|
||||
|
||||
constructor(private _cfr: ComponentFactoryResolver) {}
|
||||
|
||||
createComponentView<T>(cmptType: Type<T>): ComponentRef<T> {
|
||||
const cf = this._cfr.resolveComponentFactory(cmptType);
|
||||
return this.vcref.createComponent(cf);
|
||||
}
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [TestComponent], imports: [OtherModule]});
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.componentInstance.createComponentView(OtherComponent);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('foo|bar');
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -135,6 +135,86 @@ describe('exports', () => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.querySelector('span').innerHTML).toBe('First');
|
||||
});
|
||||
|
||||
describe('forward refs', () => {
|
||||
it('should work with basic text bindings', () => {
|
||||
const fixture = initWithTemplate(AppComp, '{{ myInput.value}} <input value="one" #myInput>');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('one <input value="one">');
|
||||
});
|
||||
|
||||
it('should work with element properties', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp, '<div [title]="myInput.value"></div> <input value="one" #myInput>');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('<div title="one"></div><input value="one">');
|
||||
});
|
||||
|
||||
it('should work with element attrs', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp, '<div [attr.aria-label]="myInput.value"></div> <input value="one" #myInput>');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML)
|
||||
.toEqual('<div aria-label="one"></div><input value="one">');
|
||||
});
|
||||
|
||||
it('should work with element classes', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp,
|
||||
'<div [class.red]="myInput.checked"></div> <input type="checkbox" checked #myInput>');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML).toContain('<div class="red"></div>');
|
||||
});
|
||||
|
||||
it('should work with component refs', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp, '<div [dirWithInput]="myComp"></div><comp-to-ref #myComp></comp-to-ref>');
|
||||
fixture.detectChanges();
|
||||
|
||||
const dirWithInput = fixture.debugElement.children[0].injector.get(DirWithCompInput);
|
||||
const myComp = fixture.debugElement.children[1].injector.get(ComponentToReference);
|
||||
|
||||
expect(dirWithInput.comp).toEqual(myComp);
|
||||
});
|
||||
|
||||
it('should work with multiple forward refs', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp,
|
||||
'{{ myInput.value }} {{ myComp.name }} <comp-to-ref #myComp></comp-to-ref> <input value="one" #myInput>');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML)
|
||||
.toEqual('one Nancy <comp-to-ref></comp-to-ref><input value="one">');
|
||||
});
|
||||
|
||||
it('should support local refs in nested dynamic views', () => {
|
||||
const fixture = initWithTemplate(AppComp, `
|
||||
<input value="one" #outerInput>
|
||||
<div *ngIf="outer">
|
||||
{{ outerInput.value }}
|
||||
<input value = "two" #innerInput>
|
||||
<div *ngIf="inner">
|
||||
{{ outerInput.value }} - {{ innerInput.value}}
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
fixture.detectChanges();
|
||||
fixture.componentInstance.outer = true;
|
||||
fixture.componentInstance.inner = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
// result should be <input value="one"><div>one <input value="two"><div>one - two</div></div>
|
||||
// but contains bindings comments for ngIf
|
||||
// so we check the outer div
|
||||
expect(fixture.nativeElement.innerHTML).toContain('one <input value="two">');
|
||||
// and the inner div
|
||||
expect(fixture.nativeElement.innerHTML).toContain('one - two');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function initWithTemplate(compType: Type<any>, template: string) {
|
||||
@ -149,6 +229,8 @@ class ComponentToReference {
|
||||
|
||||
@Component({selector: 'app-comp', template: ``})
|
||||
class AppComp {
|
||||
outer = false;
|
||||
inner = false;
|
||||
}
|
||||
|
||||
@Directive({selector: '[dir]', exportAs: 'dir'})
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, Directive, ErrorHandler, HostListener, QueryList, ViewChildren} from '@angular/core';
|
||||
import {Component, Directive, ErrorHandler, EventEmitter, HostListener, Input, Output, QueryList, ViewChild, ViewChildren} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {onlyInIvy} from '@angular/private/testing';
|
||||
@ -203,5 +203,40 @@ describe('event listeners', () => {
|
||||
expect(returnsFalseDir.event.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not subscribe twice to the output when there are 2 coalesced listeners', () => {
|
||||
@Directive({selector: '[foo]'})
|
||||
class FooDirective {
|
||||
@Input('foo') model: any;
|
||||
@Output('fooChange') update = new EventEmitter();
|
||||
|
||||
updateValue(value: any) { this.update.emit(value); }
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'test-component',
|
||||
template: `<div [(foo)]="someValue" (fooChange)="fooChange($event)"></div>`
|
||||
})
|
||||
class TestComponent {
|
||||
count = 0;
|
||||
someValue = -1;
|
||||
|
||||
@ViewChild(FooDirective) fooDirective: FooDirective|null = null;
|
||||
|
||||
fooChange() { this.count++; }
|
||||
|
||||
triggerUpdate(value: any) { this.fooDirective !.updateValue(value); }
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [TestComponent, FooDirective]});
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
const componentInstance = fixture.componentInstance;
|
||||
componentInstance.triggerUpdate(42);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(componentInstance.count).toEqual(1);
|
||||
expect(componentInstance.someValue).toEqual(42);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -10,8 +10,9 @@ import {Component, Input} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {of } from 'rxjs';
|
||||
|
||||
describe('elementProperty', () => {
|
||||
describe('property instructions', () => {
|
||||
it('should bind to properties whose names do not correspond to their attribute names', () => {
|
||||
@Component({template: '<label [for]="forValue"></label>'})
|
||||
class MyComp {
|
||||
@ -33,6 +34,25 @@ describe('elementProperty', () => {
|
||||
expect(labelNode.nativeElement.getAttribute('for')).toBe('some-textarea');
|
||||
});
|
||||
|
||||
it('should not allow unsanitary urls in bound properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img [src]="naughty">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
naughty = 'javascript:alert("haha, I am taking over your computer!!!");';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const img = fixture.nativeElement.querySelector('img');
|
||||
|
||||
expect(img.src.indexOf('unsafe:')).toBe(0);
|
||||
});
|
||||
|
||||
|
||||
it('should not map properties whose names do not correspond to their attribute names, ' +
|
||||
'if they correspond to inputs',
|
||||
() => {
|
||||
@ -60,4 +80,136 @@ describe('elementProperty', () => {
|
||||
expect(myCompNode.nativeElement.getAttribute('for')).toBeFalsy();
|
||||
expect(myCompNode.componentInstance.for).toBe('hej');
|
||||
});
|
||||
|
||||
it('should handle all flavors of interpolated properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i{{nine}}j"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d{{four}}e"></div>
|
||||
<div title="a{{one}}b{{two}}c{{three}}d"></div>
|
||||
<div title="a{{one}}b{{two}}c"></div>
|
||||
<div title="a{{one}}b"></div>
|
||||
<div title="{{one}}"></div>
|
||||
`
|
||||
})
|
||||
class App {
|
||||
one = 1;
|
||||
two = 2;
|
||||
three = 3;
|
||||
four = 4;
|
||||
five = 5;
|
||||
six = 6;
|
||||
seven = 7;
|
||||
eight = 8;
|
||||
nine = 9;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
|
||||
const titles = Array.from(fixture.nativeElement.querySelectorAll('div[title]'))
|
||||
.map((div: HTMLDivElement) => div.title);
|
||||
|
||||
expect(titles).toEqual([
|
||||
'a1b2c3d4e5f6g7h8i9j',
|
||||
'a1b2c3d4e5f6g7h8i',
|
||||
'a1b2c3d4e5f6g7h',
|
||||
'a1b2c3d4e5f6g',
|
||||
'a1b2c3d4e5f',
|
||||
'a1b2c3d4e',
|
||||
'a1b2c3d',
|
||||
'a1b2c',
|
||||
'a1b',
|
||||
'1',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle pipes in interpolated properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img title="{{(details | async)?.title}}" src="{{(details | async)?.url}}" />
|
||||
`
|
||||
})
|
||||
class App {
|
||||
details = of ({
|
||||
title: 'cool image',
|
||||
url: 'http://somecooldomain:1234/cool_image.png',
|
||||
});
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
|
||||
const img: HTMLImageElement = fixture.nativeElement.querySelector('img');
|
||||
expect(img.src).toBe('http://somecooldomain:1234/cool_image.png');
|
||||
expect(img.title).toBe('cool image');
|
||||
});
|
||||
|
||||
// From https://angular-team.atlassian.net/browse/FW-1287
|
||||
it('should handle multiple elvis operators', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img src="{{leadSurgeon?.getCommonInfo()?.getPhotoUrl() }}">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
/** Clearly this is a doctor of heavy metals. */
|
||||
leadSurgeon = {
|
||||
getCommonInfo() {
|
||||
return {getPhotoUrl() { return 'http://somecooldomain:1234/cool_image.png'; }};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const img = fixture.nativeElement.querySelector('img');
|
||||
|
||||
expect(img.src).toBe('http://somecooldomain:1234/cool_image.png');
|
||||
});
|
||||
|
||||
it('should not allow unsanitary urls in interpolated properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img src="{{naughty}}">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
naughty = 'javascript:alert("haha, I am taking over your computer!!!");';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const img: HTMLImageElement = fixture.nativeElement.querySelector('img');
|
||||
|
||||
expect(img.src.indexOf('unsafe:')).toBe(0);
|
||||
});
|
||||
|
||||
it('should not allow unsanitary urls in interpolated properties, even if you are tricky', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img src="{{ja}}{{va}}script:{{naughty}}">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
ja = 'ja';
|
||||
va = 'va';
|
||||
naughty = 'alert("I am a h4xx0rz1!!");';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const img = fixture.nativeElement.querySelector('img');
|
||||
|
||||
expect(img.src.indexOf('unsafe:')).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -1772,6 +1772,99 @@ function declareTests(config?: {useJit: boolean}) {
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('[ERROR]');
|
||||
});
|
||||
|
||||
it('should not reflect undefined values', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyComp, MyDir, MyDir2]});
|
||||
TestBed.overrideComponent(
|
||||
MyComp, {set: {template: `<div my-dir [elprop]="ctxProp"></div>`}});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
|
||||
fixture.componentInstance.ctxProp = 'hello';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement))
|
||||
.toContain('ng-reflect-dir-prop="hello"');
|
||||
|
||||
fixture.componentInstance.ctxProp = undefined !;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).not.toContain('ng-reflect-');
|
||||
});
|
||||
|
||||
it('should not reflect null values', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyComp, MyDir, MyDir2]});
|
||||
TestBed.overrideComponent(
|
||||
MyComp, {set: {template: `<div my-dir [elprop]="ctxProp"></div>`}});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
|
||||
fixture.componentInstance.ctxProp = 'hello';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement))
|
||||
.toContain('ng-reflect-dir-prop="hello"');
|
||||
|
||||
fixture.componentInstance.ctxProp = null !;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).not.toContain('ng-reflect-');
|
||||
});
|
||||
|
||||
it('should reflect empty strings', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyComp, MyDir, MyDir2]});
|
||||
TestBed.overrideComponent(
|
||||
MyComp, {set: {template: `<div my-dir [elprop]="ctxProp"></div>`}});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
|
||||
fixture.componentInstance.ctxProp = '';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-dir-prop=""');
|
||||
});
|
||||
|
||||
it('should not reflect in comment nodes when the value changes to undefined', () => {
|
||||
const fixture =
|
||||
TestBed.configureTestingModule({declarations: [MyComp]})
|
||||
.overrideComponent(
|
||||
MyComp, {set: {template: `<ng-template [ngIf]="ctxBoolProp"></ng-template>`}})
|
||||
.createComponent(MyComp);
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
let html = getDOM().getInnerHTML(fixture.nativeElement);
|
||||
expect(html).toContain('bindings={');
|
||||
expect(html).toContain('"ng-reflect-ng-if": "true"');
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = undefined !;
|
||||
fixture.detectChanges();
|
||||
|
||||
html = getDOM().getInnerHTML(fixture.nativeElement);
|
||||
expect(html).toContain('bindings={');
|
||||
expect(html).not.toContain('ng-reflect');
|
||||
});
|
||||
|
||||
it('should reflect in comment nodes when the value changes to null', () => {
|
||||
const fixture =
|
||||
TestBed.configureTestingModule({declarations: [MyComp]})
|
||||
.overrideComponent(
|
||||
MyComp, {set: {template: `<ng-template [ngIf]="ctxBoolProp"></ng-template>`}})
|
||||
.createComponent(MyComp);
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
let html = getDOM().getInnerHTML(fixture.nativeElement);
|
||||
expect(html).toContain('bindings={');
|
||||
expect(html).toContain('"ng-reflect-ng-if": "true"');
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = null !;
|
||||
fixture.detectChanges();
|
||||
|
||||
html = getDOM().getInnerHTML(fixture.nativeElement);
|
||||
expect(html).toContain('bindings={');
|
||||
expect(html).toContain('"ng-reflect-ng-if": null');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('property decorators', () => {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,176 +6,20 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AttributeMarker, ɵɵdefineComponent, ɵɵdefineDirective} from '../../src/render3/index';
|
||||
import {ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵelement, ɵɵelementAttribute, ɵɵelementClassProp, ɵɵelementEnd, ɵɵelementProperty, ɵɵelementStart, ɵɵelementStyling, ɵɵelementStylingApply, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵinterpolation2, ɵɵnextContext, ɵɵreference, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/instructions/all';
|
||||
import {ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵreference, ɵɵtext, ɵɵtextBinding} from '../../src/render3/instructions/all';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
|
||||
import {NgIf} from './common_with_def';
|
||||
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
|
||||
import {ComponentFixture, createComponent} from './render_util';
|
||||
|
||||
describe('exports', () => {
|
||||
// For basic use cases, see core/test/acceptance/exports_spec.ts.
|
||||
|
||||
describe('forward refs', () => {
|
||||
it('should work with basic text bindings', () => {
|
||||
/** {{ myInput.value}} <input value="one" #myInput> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵtext(0);
|
||||
ɵɵelement(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp = ɵɵreference(2) as any;
|
||||
ɵɵtextBinding(0, ɵɵbind(tmp.value));
|
||||
}
|
||||
}, 3, 1);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html).toEqual('one<input value="one">');
|
||||
});
|
||||
|
||||
|
||||
it('should work with element properties', () => {
|
||||
/** <div [title]="myInput.value"</div> <input value="one" #myInput> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelement(0, 'div');
|
||||
ɵɵelement(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp = ɵɵreference(2) as any;
|
||||
ɵɵelementProperty(0, 'title', ɵɵbind(tmp.value));
|
||||
}
|
||||
}, 3, 1);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html).toEqual('<div title="one"></div><input value="one">');
|
||||
});
|
||||
|
||||
it('should work with element attrs', () => {
|
||||
/** <div [attr.aria-label]="myInput.value"</div> <input value="one" #myInput> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelement(0, 'div');
|
||||
ɵɵelement(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp = ɵɵreference(2) as any;
|
||||
ɵɵelementAttribute(0, 'aria-label', ɵɵbind(tmp.value));
|
||||
}
|
||||
}, 3, 1);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html).toEqual('<div aria-label="one"></div><input value="one">');
|
||||
});
|
||||
|
||||
it('should work with element classes', () => {
|
||||
/** <div [class.red]="myInput.checked"</div> <input type="checkbox" checked #myInput> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'div', [AttributeMarker.Classes, 'red']);
|
||||
ɵɵelementStyling(['red']);
|
||||
ɵɵelementEnd();
|
||||
ɵɵelement(1, 'input', ['type', 'checkbox', 'checked', 'true'], ['myInput', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp = ɵɵreference(2) as any;
|
||||
ɵɵelementClassProp(0, 0, tmp.checked);
|
||||
ɵɵelementStylingApply(0);
|
||||
}
|
||||
}, 3);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html).toEqual('<div class="red"></div><input checked="true" type="checkbox">');
|
||||
});
|
||||
|
||||
it('should work with component refs', () => {
|
||||
|
||||
let myComponent: MyComponent;
|
||||
let myDir: MyDir;
|
||||
|
||||
class MyComponent {
|
||||
constructor() { myComponent = this; }
|
||||
|
||||
static ngComponentDef = ɵɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors: [['comp']],
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function(rf: RenderFlags, ctx: MyComponent) {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
}
|
||||
|
||||
class MyDir {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
myDir !: MyComponent;
|
||||
|
||||
constructor() { myDir = this; }
|
||||
|
||||
static ngDirectiveDef = ɵɵdefineDirective({
|
||||
type: MyDir,
|
||||
selectors: [['', 'myDir', '']],
|
||||
factory: () => new MyDir,
|
||||
inputs: {myDir: 'myDir'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <div [myDir]="myComp"></div><comp #myComp></comp> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelement(0, 'div', ['myDir', '']);
|
||||
ɵɵelement(1, 'comp', null, ['myComp', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp = ɵɵreference(2) as any;
|
||||
ɵɵelementProperty(0, 'myDir', ɵɵbind(tmp));
|
||||
}
|
||||
}, 3, 1, [MyComponent, MyDir]);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(myDir !.myDir).toEqual(myComponent !);
|
||||
});
|
||||
|
||||
it('should work with multiple forward refs', () => {
|
||||
let myComponent: MyComponent;
|
||||
|
||||
class MyComponent {
|
||||
name = 'Nancy';
|
||||
|
||||
constructor() { myComponent = this; }
|
||||
|
||||
static ngComponentDef = ɵɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors: [['comp']],
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function() {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
}
|
||||
|
||||
/** {{ myInput.value }} {{ myComp.name }} <comp #myComp></comp> <input value="one" #myInput>
|
||||
*/
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵtext(0);
|
||||
ɵɵtext(1);
|
||||
ɵɵelement(2, 'comp', null, ['myComp', '']);
|
||||
ɵɵelement(4, 'input', ['value', 'one'], ['myInput', '']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tmp1 = ɵɵreference(3) as any;
|
||||
const tmp2 = ɵɵreference(5) as any;
|
||||
ɵɵtextBinding(0, ɵɵbind(tmp2.value));
|
||||
ɵɵtextBinding(1, ɵɵbind(tmp1.name));
|
||||
}
|
||||
}, 6, 2, [MyComponent]);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html).toEqual('oneNancy<comp></comp><input value="one">');
|
||||
});
|
||||
|
||||
/**
|
||||
* This test needs to be moved to acceptance/exports_spec.ts
|
||||
* when Ivy compiler supports inline views.
|
||||
*/
|
||||
it('should work inside a view container', () => {
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
@ -214,74 +58,5 @@ describe('exports', () => {
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<div></div>');
|
||||
});
|
||||
|
||||
it('should support local refs in nested dynamic views', () => {
|
||||
/**
|
||||
* <input value="one" #outerInput>
|
||||
* <div *ngIf="outer">
|
||||
* {{ outerInput.value }}
|
||||
*
|
||||
* <input value = "two" #innerInput>
|
||||
*
|
||||
* <div *ngIf="inner">
|
||||
* {{ outerInput.value }} - {{ innerInput.value}}
|
||||
* </div>
|
||||
* </div>
|
||||
*/
|
||||
const App = createComponent('app', function(rf: RenderFlags, app: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'input', ['value', 'one'], ['outerInput', '']);
|
||||
ɵɵelementEnd();
|
||||
ɵɵtemplate(2, outerTemplate, 5, 2, 'div', [AttributeMarker.Template, 'ngIf']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
ɵɵelementProperty(2, 'ngIf', ɵɵbind(app.outer));
|
||||
}
|
||||
}, 3, 1, [NgIf]);
|
||||
|
||||
function outerTemplate(rf: RenderFlags, outer: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'div');
|
||||
{
|
||||
ɵɵtext(1);
|
||||
ɵɵelementStart(2, 'input', ['value', 'two'], ['innerInput', '']);
|
||||
ɵɵelementEnd();
|
||||
ɵɵtemplate(4, innerTemplate, 2, 2, 'div', [AttributeMarker.Template, 'ngIf']);
|
||||
}
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
|
||||
if (rf & RenderFlags.Update) {
|
||||
const app = ɵɵnextContext();
|
||||
const outerInput = ɵɵreference(1) as any;
|
||||
ɵɵtextBinding(1, ɵɵbind(outerInput.value));
|
||||
ɵɵelementProperty(4, 'ngIf', ɵɵbind(app.inner));
|
||||
}
|
||||
}
|
||||
|
||||
function innerTemplate(rf: RenderFlags, inner: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'div');
|
||||
{ ɵɵtext(1); }
|
||||
ɵɵelementEnd();
|
||||
}
|
||||
|
||||
if (rf & RenderFlags.Update) {
|
||||
ɵɵnextContext();
|
||||
const innerInput = ɵɵreference(3) as any;
|
||||
ɵɵnextContext();
|
||||
const outerInput = ɵɵreference(1) as any;
|
||||
ɵɵtextBinding(1, ɵɵinterpolation2('', outerInput.value, ' - ', innerInput.value, ''));
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
fixture.component.outer = true;
|
||||
fixture.component.inner = true;
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual(`<input value="one"><div>one<input value="two"><div>one - two</div></div>`);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -7,7 +7,6 @@ ls_rollup_bundle(
|
||||
"fs": "fs",
|
||||
"path": "path",
|
||||
"typescript": "ts",
|
||||
"typescript/lib/tsserverlibrary": "tsserverlibrary",
|
||||
},
|
||||
license_banner = "banner.js.txt",
|
||||
visibility = ["//packages/language-service:__pkg__"],
|
||||
|
@ -6,15 +6,16 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as ts from 'typescript/lib/tsserverlibrary';
|
||||
import * as ts from 'typescript'; // used as value, passed in by tsserver at runtime
|
||||
import * as tss from 'typescript/lib/tsserverlibrary'; // used as type only
|
||||
|
||||
import {createLanguageService} from './language_service';
|
||||
import {Completion, Diagnostic, DiagnosticMessageChain} from './types';
|
||||
import {TypeScriptServiceHost} from './typescript_host';
|
||||
|
||||
const projectHostMap = new WeakMap<ts.server.Project, TypeScriptServiceHost>();
|
||||
const projectHostMap = new WeakMap<tss.server.Project, TypeScriptServiceHost>();
|
||||
|
||||
export function getExternalFiles(project: ts.server.Project): string[]|undefined {
|
||||
export function getExternalFiles(project: tss.server.Project): string[]|undefined {
|
||||
const host = projectHostMap.get(project);
|
||||
if (host) {
|
||||
const externalFiles = host.getTemplateReferences();
|
||||
@ -63,7 +64,7 @@ function diagnosticToDiagnostic(d: Diagnostic, file: ts.SourceFile): ts.Diagnost
|
||||
return result;
|
||||
}
|
||||
|
||||
export function create(info: ts.server.PluginCreateInfo): ts.LanguageService {
|
||||
export function create(info: tss.server.PluginCreateInfo): ts.LanguageService {
|
||||
const oldLS: ts.LanguageService = info.languageService;
|
||||
const proxy: ts.LanguageService = Object.assign({}, oldLS);
|
||||
const logger = info.project.projectService.logger;
|
||||
|
@ -7,12 +7,8 @@
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {createLanguageService} from '../src/language_service';
|
||||
import {ReflectorHost} from '../src/reflector_host';
|
||||
import {Completions, LanguageService} from '../src/types';
|
||||
import {TypeScriptServiceHost} from '../src/typescript_host';
|
||||
|
||||
import {toh} from './test_data';
|
||||
import {MockTypescriptHost} from './test_utils';
|
||||
@ -25,12 +21,14 @@ describe('reflector_host_spec', () => {
|
||||
let mockHost = new MockTypescriptHost(
|
||||
['/app/main.ts', '/app/parsing-cases.ts'], toh, 'app/node_modules',
|
||||
{...path, join: (...args: string[]) => originalJoin.apply(path, args)});
|
||||
let service = ts.createLanguageService(mockHost);
|
||||
let ngHost = new TypeScriptServiceHost(mockHost, service);
|
||||
let ngService = createLanguageService(ngHost);
|
||||
const reflectorHost = new ReflectorHost(() => undefined as any, mockHost, {basePath: '\\app'});
|
||||
|
||||
spyOn(path, 'join').and.callFake((...args: string[]) => { return path.win32.join(...args); });
|
||||
if (process.platform !== 'win32') {
|
||||
// If we call this in Windows it will cause a 'Maximum call stack size exceeded error'
|
||||
// Because we are spying on the same function that we are call faking
|
||||
spyOn(path, 'join').and.callFake((...args: string[]) => { return path.win32.join(...args); });
|
||||
}
|
||||
|
||||
const result = reflectorHost.moduleNameToFileName('@angular/core');
|
||||
expect(result).not.toBeNull('could not find @angular/core using path.win32');
|
||||
});
|
||||
|
@ -36,10 +36,19 @@ function _ngProbeTokensToMap(tokens: core.NgProbeToken[]): {[name: string]: any}
|
||||
return tokens.reduce((prev: any, t: any) => (prev[t.name] = t.token, prev), {});
|
||||
}
|
||||
|
||||
/**
|
||||
* In Ivy, we don't support NgProbe because we have our own set of testing utilities
|
||||
* with more robust functionality.
|
||||
*
|
||||
* We shouldn't bring in NgProbe because it prevents DebugNode and friends from
|
||||
* tree-shaking properly.
|
||||
*/
|
||||
export const ELEMENT_PROBE_PROVIDERS__POST_R3__ = [];
|
||||
|
||||
/**
|
||||
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
|
||||
*/
|
||||
export const ELEMENT_PROBE_PROVIDERS: core.Provider[] = [
|
||||
export const ELEMENT_PROBE_PROVIDERS__PRE_R3__: core.Provider[] = [
|
||||
{
|
||||
provide: core.APP_INITIALIZER,
|
||||
useFactory: _createNgProbe,
|
||||
@ -49,3 +58,5 @@ export const ELEMENT_PROBE_PROVIDERS: core.Provider[] = [
|
||||
multi: true,
|
||||
},
|
||||
];
|
||||
|
||||
export const ELEMENT_PROBE_PROVIDERS = ELEMENT_PROBE_PROVIDERS__PRE_R3__;
|
||||
|
@ -18,3 +18,5 @@ export {DomSanitizer, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl,
|
||||
|
||||
export * from './private_export';
|
||||
export {VERSION} from './version';
|
||||
// This must be exported so it doesn't get tree-shaken away prematurely
|
||||
export {ELEMENT_PROBE_PROVIDERS__POST_R3__ as ɵELEMENT_PROBE_PROVIDERS__POST_R3__} from './dom/debug/ng_probe';
|
||||
|
21
tools/public_api_guard/core/core.d.ts
vendored
21
tools/public_api_guard/core/core.d.ts
vendored
@ -383,7 +383,6 @@ export interface HostListenerDecorator {
|
||||
new (eventName: string, args?: string[]): any;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export declare const inject: typeof ɵɵinject;
|
||||
|
||||
export interface Inject {
|
||||
@ -944,25 +943,25 @@ export declare function ɵɵprojectionDef(selectors?: CssSelectorList[]): void;
|
||||
|
||||
export declare function ɵɵproperty<T>(propName: string, value: T, sanitizer?: SanitizerFn | null, nativeOnly?: boolean): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate(propName: string, v0: any): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate(propName: string, v0: any, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate1(propName: string, prefix: string, v0: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate1(propName: string, prefix: string, v0: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate2(propName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate2(propName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate3(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate3(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate4(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate4(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate5(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate5(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate6(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate6(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate7(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate7(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolate8(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, suffix: string): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolate8(propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, suffix: string, sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵpropertyInterpolateV(propName: string, values: any[]): TsickleIssue1009;
|
||||
export declare function ɵɵpropertyInterpolateV(propName: string, values: any[], sanitizer?: SanitizerFn): TsickleIssue1009;
|
||||
|
||||
export declare function ɵɵProvidersFeature<T>(providers: Provider[], viewProviders?: Provider[]): (definition: DirectiveDef<T>) => void;
|
||||
|
||||
|
@ -43,7 +43,7 @@ function main(argv: [string, string, string] | [string, string]): boolean {
|
||||
const defineFlag = (compile !== 'legacy') ? `--define=compile=${compile} ` : '';
|
||||
console.error(`TEST FAILED!`);
|
||||
console.error(` To update the golden file run: `);
|
||||
console.error(` yarn bazel run ${defineFlag}${process.env['BAZEL_TARGET']}.accept`);
|
||||
console.error(` yarn bazel run ${defineFlag}${process.env['TEST_TARGET']}.accept`);
|
||||
}
|
||||
}
|
||||
return passed;
|
||||
|
@ -3,12 +3,11 @@
|
||||
# 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
|
||||
|
||||
"""This test verifies that a set of top level symbols from a javascript file match a gold file.
|
||||
"""
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "nodejs_test")
|
||||
|
||||
# This does a deep import under //internal because of not wanting the wrapper macro
|
||||
# because it introduces an extra target_bin target.
|
||||
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_binary", "nodejs_test")
|
||||
"""
|
||||
This test verifies that a set of top level symbols from a javascript file match a gold file.
|
||||
"""
|
||||
|
||||
def js_expected_symbol_test(name, src, golden, data = [], **kwargs):
|
||||
"""This test verifies that a set of top level symbols from a javascript file match a gold file.
|
||||
@ -17,7 +16,6 @@ def js_expected_symbol_test(name, src, golden, data = [], **kwargs):
|
||||
src,
|
||||
golden,
|
||||
Label("//tools/symbol-extractor:lib"),
|
||||
Label("@bazel_tools//tools/bash/runfiles"),
|
||||
Label("@npm//typescript"),
|
||||
]
|
||||
entry_point = "angular/tools/symbol-extractor/cli.js"
|
||||
|
@ -37,6 +37,11 @@ def ts_api_guardian_test(
|
||||
# But it will replaced to @npm//ts-api-guardian when publishing
|
||||
"@angular//tools/ts-api-guardian:lib",
|
||||
"@angular//tools/ts-api-guardian:bin",
|
||||
# The below are required during runtime
|
||||
"@npm//chalk",
|
||||
"@npm//diff",
|
||||
"@npm//minimist",
|
||||
"@npm//typescript",
|
||||
]
|
||||
|
||||
args = [
|
||||
@ -46,7 +51,8 @@ def ts_api_guardian_test(
|
||||
]
|
||||
|
||||
for i in strip_export_pattern:
|
||||
args += ["--stripExportPattern", i]
|
||||
# The below replacement is needed because under Windows '^' needs to be escaped twice
|
||||
args += ["--stripExportPattern", i.replace("^", "^^^^")]
|
||||
|
||||
for i in allow_module_identifiers:
|
||||
args += ["--allowModuleIdentifiers", i]
|
||||
|
@ -298,7 +298,7 @@ class ResolvedDeclarationEmitter {
|
||||
const jsdocComment = this.processJsDocTags(node, tagOptions);
|
||||
if (jsdocComment) {
|
||||
// Add the annotation after the leading whitespace
|
||||
output = output.replace(/^(\n\s*)/, `$1${jsdocComment} `);
|
||||
output = output.replace(/^(\r?\n\s*)/, `$1${jsdocComment} `);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,11 @@ function execute(args: string[]): {stdout: string, stderr: string, status: numbe
|
||||
// We need to determine the directory that includes the `ts-api-guardian` npm_package that
|
||||
// will be used to spawn the CLI binary. This is a workaround because technically we shouldn't
|
||||
// spawn a child process that doesn't have the custom NodeJS module resolution for Bazel.
|
||||
const nodePath = path.join(path.dirname(require.resolve('../lib/cli.js')), '../');
|
||||
const nodePath = [
|
||||
path.join(require.resolve('npm/node_modules/chalk/package.json'), '../../'),
|
||||
path.join(require.resolve('../lib/cli.js'), '../../'),
|
||||
].join(process.platform === 'win32' ? ';' : ':');
|
||||
|
||||
const output = child_process.spawnSync(process.execPath, [BINARY_PATH, ...args], {
|
||||
env: {
|
||||
'NODE_PATH': nodePath,
|
||||
|
232
yarn.lock
232
yarn.lock
@ -952,6 +952,11 @@ ansi-regex@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9"
|
||||
integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==
|
||||
|
||||
ansi-regex@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||
|
||||
ansi-styles@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||
@ -1851,6 +1856,11 @@ camelcase@^4.0.0, camelcase@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
|
||||
|
||||
camelcase@^5.0.0:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
canonical-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d"
|
||||
@ -2158,15 +2168,6 @@ cliui@^2.1.0:
|
||||
right-align "^0.1.1"
|
||||
wordwrap "0.0.2"
|
||||
|
||||
cliui@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
|
||||
integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
|
||||
dependencies:
|
||||
string-width "^1.0.1"
|
||||
strip-ansi "^3.0.1"
|
||||
wrap-ansi "^2.0.0"
|
||||
|
||||
cliui@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
|
||||
@ -2840,7 +2841,7 @@ cross-spawn@^5.0.1:
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^6.0.5:
|
||||
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
|
||||
@ -3004,7 +3005,7 @@ decamelize-keys@^1.0.0:
|
||||
decamelize "^1.1.0"
|
||||
map-obj "^1.0.0"
|
||||
|
||||
decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2:
|
||||
decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||
@ -3300,6 +3301,11 @@ ee-first@1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emojis-list@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||
@ -3663,6 +3669,19 @@ execa@^0.7.0:
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
|
||||
dependencies:
|
||||
cross-spawn "^6.0.0"
|
||||
get-stream "^4.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
exit-code@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/exit-code/-/exit-code-1.0.2.tgz#ce165811c9f117af6a5f882940b96ae7f9aecc34"
|
||||
@ -4014,6 +4033,13 @@ find-up@^2.0.0, find-up@^2.1.0:
|
||||
dependencies:
|
||||
locate-path "^2.0.0"
|
||||
|
||||
find-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
||||
integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
|
||||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
findup-sync@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
|
||||
@ -4495,9 +4521,14 @@ genfun@^5.0.0:
|
||||
integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==
|
||||
|
||||
get-caller-file@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
|
||||
integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
|
||||
|
||||
get-caller-file@^2.0.1:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-func-name@^2.0.0:
|
||||
version "2.0.0"
|
||||
@ -4525,7 +4556,7 @@ get-stream@3.0.0, get-stream@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
|
||||
|
||||
get-stream@^4.1.0:
|
||||
get-stream@^4.0.0, get-stream@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
|
||||
@ -5530,6 +5561,11 @@ invert-kv@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
|
||||
integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
|
||||
|
||||
invert-kv@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
|
||||
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
|
||||
|
||||
ip@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
@ -6502,6 +6538,13 @@ lcid@^1.0.0:
|
||||
dependencies:
|
||||
invert-kv "^1.0.0"
|
||||
|
||||
lcid@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
|
||||
integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
|
||||
dependencies:
|
||||
invert-kv "^2.0.0"
|
||||
|
||||
levn@~0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
||||
@ -6547,16 +6590,6 @@ load-json-file@^1.0.0:
|
||||
pinkie-promise "^2.0.0"
|
||||
strip-bom "^2.0.0"
|
||||
|
||||
load-json-file@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
|
||||
integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
parse-json "^2.2.0"
|
||||
pify "^2.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
load-json-file@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
|
||||
@ -6594,6 +6627,14 @@ locate-path@^2.0.0:
|
||||
p-locate "^2.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
|
||||
dependencies:
|
||||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash._basecopy@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
|
||||
@ -7000,6 +7041,13 @@ make-iterator@^1.0.0:
|
||||
dependencies:
|
||||
kind-of "^6.0.2"
|
||||
|
||||
map-age-cleaner@^0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
|
||||
integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
|
||||
dependencies:
|
||||
p-defer "^1.0.0"
|
||||
|
||||
map-cache@^0.2.0, map-cache@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
||||
@ -7062,6 +7110,15 @@ mem@^1.1.0:
|
||||
dependencies:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
mem@^4.0.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
|
||||
integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
|
||||
dependencies:
|
||||
map-age-cleaner "^0.1.1"
|
||||
mimic-fn "^2.0.0"
|
||||
p-is-promise "^2.0.0"
|
||||
|
||||
memoizeasync@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/memoizeasync/-/memoizeasync-1.1.0.tgz#9d7028a6f266deb733510bb7dbba5f51878c561e"
|
||||
@ -7264,6 +7321,11 @@ mimic-fn@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
|
||||
|
||||
mimic-fn@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-response@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
@ -8025,6 +8087,15 @@ os-locale@^2.0.0:
|
||||
lcid "^1.0.0"
|
||||
mem "^1.1.0"
|
||||
|
||||
os-locale@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
|
||||
integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
|
||||
dependencies:
|
||||
execa "^1.0.0"
|
||||
lcid "^2.0.0"
|
||||
mem "^4.0.0"
|
||||
|
||||
os-shim@^0.1.2:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917"
|
||||
@ -8053,6 +8124,11 @@ p-cancelable@^0.4.0:
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0"
|
||||
integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==
|
||||
|
||||
p-defer@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
|
||||
integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
|
||||
|
||||
p-finally@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||
@ -8063,6 +8139,11 @@ p-is-promise@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
|
||||
integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=
|
||||
|
||||
p-is-promise@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5"
|
||||
integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==
|
||||
|
||||
p-limit@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
|
||||
@ -8070,6 +8151,13 @@ p-limit@^1.1.0:
|
||||
dependencies:
|
||||
p-try "^1.0.0"
|
||||
|
||||
p-limit@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2"
|
||||
integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==
|
||||
dependencies:
|
||||
p-try "^2.0.0"
|
||||
|
||||
p-locate@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
|
||||
@ -8077,6 +8165,13 @@ p-locate@^2.0.0:
|
||||
dependencies:
|
||||
p-limit "^1.1.0"
|
||||
|
||||
p-locate@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
|
||||
integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
|
||||
dependencies:
|
||||
p-limit "^2.0.0"
|
||||
|
||||
p-timeout@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038"
|
||||
@ -8089,6 +8184,11 @@ p-try@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
|
||||
|
||||
p-try@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
package-json@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
|
||||
@ -8304,13 +8404,6 @@ path-type@^1.0.0:
|
||||
pify "^2.0.0"
|
||||
pinkie-promise "^2.0.0"
|
||||
|
||||
path-type@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
|
||||
integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=
|
||||
dependencies:
|
||||
pify "^2.0.0"
|
||||
|
||||
path-type@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||
@ -8787,14 +8880,6 @@ read-pkg-up@^1.0.1:
|
||||
find-up "^1.0.0"
|
||||
read-pkg "^1.0.0"
|
||||
|
||||
read-pkg-up@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
|
||||
integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=
|
||||
dependencies:
|
||||
find-up "^2.0.0"
|
||||
read-pkg "^2.0.0"
|
||||
|
||||
read-pkg-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
|
||||
@ -8812,15 +8897,6 @@ read-pkg@^1.0.0, read-pkg@^1.1.0:
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^1.0.0"
|
||||
|
||||
read-pkg@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
|
||||
integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=
|
||||
dependencies:
|
||||
load-json-file "^2.0.0"
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^2.0.0"
|
||||
|
||||
read-pkg@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
|
||||
@ -9143,6 +9219,11 @@ require-main-filename@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
|
||||
integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
|
||||
|
||||
require-main-filename@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
requirejs@2.3.5:
|
||||
version "2.3.5"
|
||||
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.5.tgz#617b9acbbcb336540ef4914d790323a8d4b861b0"
|
||||
@ -10220,6 +10301,15 @@ string-width@^1.0.1:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string-width@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
|
||||
dependencies:
|
||||
emoji-regex "^7.0.1"
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^5.1.0"
|
||||
|
||||
string_decoder@~0.10.25, string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
@ -10258,6 +10348,13 @@ strip-ansi@^5.0.0:
|
||||
dependencies:
|
||||
ansi-regex "^4.0.0"
|
||||
|
||||
strip-ansi@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
|
||||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-bom-buf@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572"
|
||||
@ -11614,12 +11711,13 @@ yallist@^3.0.0, yallist@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
|
||||
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
|
||||
|
||||
yargs-parser@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
|
||||
integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k=
|
||||
yargs-parser@^13.0.0:
|
||||
version "13.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b"
|
||||
integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==
|
||||
dependencies:
|
||||
camelcase "^4.1.0"
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^9.0.2:
|
||||
version "9.0.2"
|
||||
@ -11646,24 +11744,22 @@ yargs@11.0.0:
|
||||
y18n "^3.2.1"
|
||||
yargs-parser "^9.0.2"
|
||||
|
||||
yargs@9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c"
|
||||
integrity sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=
|
||||
yargs@13.1.0:
|
||||
version "13.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.1.0.tgz#b2729ce4bfc0c584939719514099d8a916ad2301"
|
||||
integrity sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==
|
||||
dependencies:
|
||||
camelcase "^4.1.0"
|
||||
cliui "^3.2.0"
|
||||
decamelize "^1.1.1"
|
||||
get-caller-file "^1.0.1"
|
||||
os-locale "^2.0.0"
|
||||
read-pkg-up "^2.0.0"
|
||||
cliui "^4.0.0"
|
||||
find-up "^3.0.0"
|
||||
get-caller-file "^2.0.1"
|
||||
os-locale "^3.1.0"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^1.0.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^2.0.0"
|
||||
string-width "^3.0.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^3.2.1"
|
||||
yargs-parser "^7.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.0.0"
|
||||
|
||||
yargs@^11.0.0:
|
||||
version "11.1.0"
|
||||
|
Reference in New Issue
Block a user