Compare commits

...

58 Commits

Author SHA1 Message Date
a3dac6f8f0 release: cut the v7.2.16 release 2020-01-08 12:04:47 -08:00
9c8dda5e30 test: remove bazel-schematics tests due to unpinned deps
The bazel-schematics integration test in the 7.2.x branch no longer runs
successfully as unpinned dependencies are now being pulled in as newer
versions, which require a newer version of NodeJS than is provisioned on
CI. Since Bazel is a Labs project in 7.x there's no reason to keep these
tests around.
2020-01-07 14:04:23 -08:00
795108c64e build: add is-builtin-module dependency, repin karma-sauce-launcher dependency 2020-01-07 14:04:23 -08:00
6f28e6e971 ci: update gcp_token (#31405)
PR Close #31405
2020-01-07 14:03:31 -08:00
7f78c16578 build: remove duplicate aio_monitoring workflow 2020-01-07 14:03:26 -08:00
b7bacf02a0 build: upgrade yargs package to 13.1.0
Update yargs, because the old version was transitively (via os-local)
depending on a vulnerable version of the mem package:
https://app.snyk.io/vuln/npm:mem:20180117

Fixes #33933
2020-01-07 14:03:18 -08:00
41e56c964a fixup! refactor(docs-infra): make archive redirection tests DRY 2019-06-11 00:08:33 +00:00
d2ec449d46 refactor(docs-infra): avoid hard-coding URLs to redirect on archive mode
Related discussion:
https://github.com/angular/angular/pull/30894#pullrequestreview-246731995
2019-06-11 00:08:33 +00:00
ebf7174c19 fix(docs-infra): do not redirect docs URLs on archive deployments
To avoid showing outdated info (such as events, resources, etc.) but
still allow people to see docs for older versions, we redirect
non-documentation URLs to `/docs`. Recently(-ish) we have added
documentation content under the `/cli/...` and `/start/...`
path-prefixes, but we haven't added them to the list of documentation
URLs that should not be redirected. As a result, on archive deployments
(e.g. https://v7.angular.io/cli), they are redirected to `/docs`, making
it impossible to see the documentation for these versions (unless you
know about the `?mode=stable` work-around).

This commit fixes it by adding `cli` and `start` to the list of
documentation URLs that are excluded from redirection.
2019-06-11 00:08:33 +00:00
df6b4ab5b2 refactor(docs-infra): make archive redirection tests DRY 2019-06-11 00:08:33 +00:00
b62a9d0bc6 build(docs-infra): ensure hidden cli commands are excluded from sitemap.xml (#30395)
Previously, the processor that excludes certain cli commands
(`filterHiddenCommand`) was being run after the `createSitemap`
processor, resulting in those commands to be present in `sitemap.xml`,
while the actual pages where missing. This also resulted in 404s, when
search engine crawlers tried to index the missing URLs.

This commit fixes it by ensuring that the `filterHiddenCommand`
processor is run before the `createSitemap` processor.

PR Close #30395
2019-05-10 11:58:37 -07:00
51955bf620 release: cut the v7.2.15 release 2019-05-07 14:00:53 -07:00
b4a2cbb65b ci(docs-infra): use the tests from the stable branch in aio_monitoring_stable CircleCI job (#30110)
Previously, the `aio_monitoring_stable` job (which runs tests against
https://angular.io/) was using the tests from the master branch. As a
result, if the master branch included changes in those tests that were
not yet backported to the stable branch (and thus deployed to
https://angular.io/), the tests would fail.

This commit fixes this by using the tests from the stable branch to test
against https://angular.io/.

Fixes #30101

PR Close #30110
2019-04-30 16:16:41 -07:00
9fe0417103 ci(docs-infra): split the aio_monitoring CircleCI job into two jobs (#30110)
Previously, the `aio_monitoring` job was testing both the stable
(https://angular.io/) and the @next (https://next.angular.io/) versions.

This commit splits the tests into two separate jobs (still run as part
of the same workflow). This speeds up the tests (since the two jobs can
now run in parallel) and makes it easier to isolate failures (e.g.
identify which branch is failing, disable one of the two, etc.).
(Credits to @petebacondarwin 😉)

PR Close #30110
2019-04-30 16:16:37 -07:00
fb0d88715a ci(docs-infra): re-use setup CircleCI job in aio_monitoring (#30110)
PR Close #30110
2019-04-30 16:16:31 -07:00
0c61e5e205 ci(docs-infra): re-enable aio_monitoring CircleCI job (#30110)
The job started failing for https://angular.io/, due to changes in tests
that only affected https://next.angular.io/, and was disabled in #30102.

This commit re-enables the job (since it does not block anything and it
will be fixed in a subsequent commit).

PR Close #30110
2019-04-30 16:16:25 -07:00
07f03850fb test(upgrade): rename angular.module() to angular.module_() (#30107)
With #30058, the ngUpgrade internal `angular.module()` method wa
renamed to `angular.module_()` (to avoid a webpack bug).

Merging #29794 afterwards resulted in some broken tests, because it
still used the old `angular.module()` method name. (The PR had been
tested on CI against a revision that did not contain the rename.)

This commit fixes the broken tests by renaming the remaining occurrences
of `angular.module()`.

PR Close #30107
2019-04-25 12:06:04 -07:00
1084c193e7 fix(upgrade): do not break if onMicrotaskEmpty emits while a $digest is in progress (#29794) (#30107)
Previously, under certain circumstances, `NgZone#onMicrotaskEmpty` could
emit while a `$digest` was in progress, thus triggering another
`$digest`, which in turn would throw a `$digest already in progress`
error. Furthermore, throwing an error from inside the `onMicrotaskEmpty`
subscription would result in unsubscribing and stop triggering further
`$digest`s, when `onMicrotaskEmpty` emitted.

Usually, emitting while a `$digest` was already in progress was a result
of unintentionally running some part of AngularJS outside the Angular
zone, but there are valid (if rare) usecases where this can happen
(see #24680 for details).

This commit addresses the issue as follows:
- If a `$digest` is in progress when `onMicrotaskEmpty` emits, do not
  trigger another `$digest` (to avoid the error). `$evalAsync()` is used
  instead, to ensure that the bindings are evaluated at least once more.
- Since there is still a high probability that the situation is a result
  of programming error (i.e. some AngularJS part running outside the
  Angular Zone), a warning will be logged, but only if the app is in
  [dev mode][1].

[1]: https://github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12

Fixes #24680

PR Close #29794

PR Close #30107
2019-04-25 12:06:04 -07:00
bdf5367899 refactor(upgrade): rename module constant to avoid webpack bug (#30058) (#30107)
When targeting ES2015 (as is the default in cli@8), `const` is not
downleveled to `var` and thus declaring `const module` throws an error
due to webpack wrapping the code in a function call with a `module`
argument (even when compiling for the `web` environment).

Related: webpack/webpack#7369

Fixes #30050

PR Close #30058

PR Close #30107
2019-04-25 12:06:04 -07:00
d025159d61 ci(docs-infra): loosen conditions to reduce flakiness on CI (#29757)
The exact messages depend on the timing of several events and may vary
between runs. This occasionally causes flakes on CI.
This commit reduces the risk of flakes by loosen the conditions to only
check for what we actually care about.

Fixes #29544

PR Close #29757
2019-04-25 10:58:14 -07:00
7496a8311c ci(docs-infra): wait for conditions to reduce flakiness on CI (#29757)
PR Close #29757
2019-04-25 10:58:14 -07:00
91beb6f0a8 refactor(docs-infra): switch from promises to async/await in tests (#29757)
PR Close #29757
2019-04-25 10:58:14 -07:00
8275442874 docs(docs-infra): add jennifer to fw-docs-intro codeowners, add codeowners for schematics docs (#28992)
PR Close #28992
2019-04-24 17:12:06 -07:00
fe5e226f99 build(docs-infra): upgrade RxJS in docs examples to 6.5.1 (#30048) (#30096)
Related to #30043.

PR Close #30048

PR Close #30096
2019-04-24 17:08:46 -07:00
e8bdbf7963 build(docs-infra): upgrade RxJS to 6.5.1 (#30048) (#30096)
Related to #30043.

PR Close #30048

PR Close #30096
2019-04-24 17:08:46 -07:00
7368dc1664 docs(docs-infra): fix typo in the aio/tools/examples/README (#30041)
Remove an 'a' that was accidentally repeated twice in the aio/tools/examples/README.md file.

PR Close #30041
2019-04-24 11:33:24 -07:00
644f89821a docs: add Andrew Kushnir to Angular team (#30045)
PR Close #30045
2019-04-24 11:04:14 -07:00
451d4bf4ee ci: add aio/content/examples/* to docs-infra group (#30087)
This directory contains some top-level files (`.gitignore`,
`tsconfig.json`, `tslint.json`) that are related to the examples
infrastructure (building, linting, etc.).

They had previously no owner; now they are owned by the `docs-infra`
group.

PR Close #30087
2019-04-24 10:50:02 -07:00
8de9d571b9 docs: remove outdated docs change log (#26102)
PR Close #26102
2019-04-23 15:19:11 -07:00
769c132d22 release: cut the v7.2.14 release 2019-04-23 13:10:31 -07:00
ee65d0d4ab fix(common): prevent repeated application of HttpParams mutations (#29045)
Previously, an instance of HttpParams would retain its list of mutations
after they have been materialized as a result of a read operation. Not
only does this unnecessarily hold onto memory, more importantly does it
introduce a bug where branching of off a materialized instance would
reconsider the set of mutations that had already been applied, resulting
in repeated application of mutations.

This commit fixes the bug by clearing the list of pending mutations
after they have been materialized, such that they will not be considered
once again for branched off instances.

Fixes #20430

PR Close #29045
2019-04-23 08:43:54 -07:00
cd48a5383d build(docs-infra): pin versions of packages installed in preview server docker image (#29976)
This minimises the risk of unexpected failures due to breaking changes,
when building a new image (e.g. as a result of an unrelated config
change in Dockerfile).

PR Close #29976
2019-04-23 08:33:28 -07:00
0323affe18 build(docs-infra): upgrade preview server docker image to Debian 9 (#29976)
Previously, the preview server docker image was based on Debian 8
(jessie). Recently, `jessie-updates` and `jessie-backborts` were removed
from the Debian mirrors ([more info][1]), thus breaking new builds of
the image.

Instead of updating `/etc/apt/sources.list` to remove the obsolete
sources, this commit upgrades to Debian 9 (stretch).

(The GCE VM running the preview server docker container was also
upgraded from Debian 8 to 9 this morning.)

---
Other changes:
- Removed dependency on `chkconfig`, which is not supported on Debian 9.
- Installing `nginx` from the regular repositories (instead of
  `*-backports).
- Upgraded to `pm2` v3, which can handle hooking itself up to system
  startup better (without `chkconfig` - see above).
- Updated tests to reflect the fact that `nginx` has dropped the reason
  phrase in response status lines for HTTP/2 (in compliance with
  [the spec][2]). (HTTP/1.1: `HTTP/1.1 200 OK` | HTTP/2: `HTTP/2 200`)

[1]: https://www.lucas-nussbaum.net/blog/?p=947
[2]: https://http2.github.io/http2-spec/#rfc.section.8.1.2.4

PR Close #29976
2019-04-23 08:33:28 -07:00
b793aa3f85 build(docs-infra): increase build artifact size limit for preview server (#29976)
In #29926, the size of the build artifacts has increased due to turning
on differential loading (which generates an es2015/es5 pair for each JS
resource).

To avoid the preview server's rejecting the build artifacts (as in
[288181][1]), this commit increases the max allowed artifact size from
20MB to 25MB (current artifact size after #29926 is ~22MB).

[1]: https://circleci.com/gh/angular/angular/288181

PR Close #29976
2019-04-23 08:33:28 -07:00
4382ceae02 docs: fix grammatical errors in the guides and API documentation (#29928)
Fix grammatical errors in the DI and HttpClient guides as well as the Resolve API documentaiton.

There is no associated issue.

PR Close #29928
2019-04-22 17:32:31 -07:00
9a81e52eac docs: fixed typo on HttpParamsOptions (#29930)
PR Close #29930
2019-04-22 16:36:53 -07:00
903aef07f4 docs: fix typo in routing section of Tour of Heroes (#29961)
PR Close #29961
2019-04-22 11:18:45 -07:00
7f15c014d3 docs: change doc for address form group in reactive forms guide (#30007)
Closes #29925

PR Close #30007
2019-04-22 11:17:38 -07:00
546299b6f2 docs: add ng-japan 2019 event (#30021)
PR Close #30021
2019-04-22 08:45:45 -07:00
a593b3f877 ci(docs-infra): do not build with Ivy on 7.2.x (#29993)
The 7.2.x does not include the code necessary to build with Ivy. The
`test_aio_local_ivy` job needs to be skipped on 7.2.x.

The job was accidentally enabled while rebasing 1cdffbdc2.

PR Close #29993
2019-04-19 14:15:03 -07:00
2bb4263a26 ci(docs-infra): increase wait for SW on all origins to avoid CI flakes (#29988)
In #29953, the wait period for SW on localhost was increased to avoid CI
flakes for the PWA score tests.

This commit expands the fix to non-localhost origins to avoid flakes in
the `aio_monitoring` job, when CircleCI VMs/network are slow.
(For reference, example failures: [289127], [289238])

[289127]: https://circleci.com/gh/angular/angular/289127
[289238]: https://circleci.com/gh/angular/angular/289238

PR Close #29988
2019-04-19 09:59:37 -07:00
0c4430b384 build(docs-infra): make tsconfig path detection in switch-to-ivy more robust (#29989)
In light of #29926, that will change the path of `tsconfig.app.json`,
this commit switches from a hard-coded `tsconfig.app.json` path to
looking it up in `angular.json` (to be more future-proof).

PR Close #29989
2019-04-19 09:51:09 -07:00
c68826059c build(docs-infra): change build-with-ivy script to switch-to-ivy (#29989)
Previously, the `build-with-ivy` script could be used to build the `aio`
project with Ivy (once it had been prepared with `ivy-ngcc`, etc.) and
then restored the configuration (e.g. `tsconfig.json`) to non-ivy mode.

As a result, it was not useful for running other commands (e.g. unit/e2e
tests) in Ivy mode.

This commit renames the script to `switch-to-ivy` and employs a
different model (similar to `ng-packages-installer`), where the project
is setup to run in Ivy mode and then all subsequent commands are
executed in that mode (until restored).

Since this is currently only used on CI, there is no automatic way to
switch back to non-ivy mode (but it could be implemented in the future
if needed).

Finally, the script now modifies `src/tsconfig.app/json` instead of
`tsconfig.json` to ensure that the `angularCompilerOptions` are not
ignored/overwritten. This is also closer to what the cli generates
with the `--enable-ivy` option.

PR Close #29989
2019-04-19 09:50:43 -07:00
1cdffbdc2e ci(docs-infra): use pre-ivy packages in test_aio_local_ivy to test ngcc (#29989)
To better test ngcc (in addition to Ivy) on angular.io, change the
`test_aio_local_ivy` CircleCI job to use the pre-ivy Angular packages
(and have ngcc transform them to Ivy ones).

PR Close #29989
2019-04-19 09:49:10 -07:00
00f44ee6d4 refactor(docs-infra): remove unnecessary cast to any (#29989)
PR Close #29989
2019-04-19 09:46:48 -07:00
dcfde77de5 docs(animations): fixed some closing brackets on query animation page (#29854) (#29855)
PR Close #29855
2019-04-18 18:19:49 -07:00
4994527e71 docs: add Muhammad Ahsan Ayaz to GDE contributors group (#29838)
PR Close #29838
2019-04-18 18:18:17 -07:00
69eb46ad97 docs: update extra options available for RouterModule.forRoot() method (#29846)
PR Close #29846
2019-04-17 17:25:32 -07:00
6e190b1a3f ci(docs-infra): increase wait for SW on localhost to avoid CI flakes (#29953)
The server used for testing on localhost has less optimizations (e.g.
serves uncompressed files), so we need to wait longer the ServiceWorker
to be loaded and registered to allow Lighthouse to reliably detect it,
especially on slower environments (e.g. CI).

Related: https://github.com/GoogleChrome/lighthouse/issues/5527#issuecomment-483710849

Fixes #29910

PR Close #29953
2019-04-17 12:14:40 -07:00
2b1820dfea refactor(docs-infra): switch test-pwa-score.js to async/await (#29953)
PR Close #29953
2019-04-17 12:14:40 -07:00
9af4dcc442 docs: use correct values from code-example in i18n (#29920)
PR Close #29920
2019-04-16 10:31:17 -07:00
16ba4ae2a7 docs(service-worker): fix small typo in devops guide (#29866)
PR Close #29866
2019-04-16 10:30:53 -07:00
cd95db482d ci(docs-infra): temporarily lower the min required PWA score for localhost tests (#29911)
The PWA score tests have been occasionally failing on CI recently
(possibly due to CI VM/network issues).

This commit temporarily disables them, until we investigate the
root-cause and/or put a work-around in place.

The PWA score tests are still run against the deployed versions (which
don't suffer as much) or PRs with public previews (as part of the
`test_aio_preview` job) and on upstream builds (as part of the
`deploy_aio` job).

Related to #29910.

[1]: https://github.com/angular/angular/blob/3a836c362/.circleci/config.yml#L390

PR Close #29911
2019-04-15 12:34:43 -07:00
e5cbc9b22b build(docs-infra): convert search-worker.js to TypeScript (#29908)
PR Close #29908
2019-04-15 11:18:00 -07:00
cd2a2f7989 build(docs-infra): update to CLI 8 beta.13 (#29908)
PR Close #29908
2019-04-15 11:18:00 -07:00
8031e58410 fix(docs-infra): add missing ng-conf image (#29902)
As of b9fead7f8, the image is referenced in `announcements.json`, but it
was already removed (as it wasn't used at the time) in 7f905da33.

PR Close #29902
2019-04-15 09:12:59 -07:00
508db0f467 build(docs-infra): add missing dependencies (chrome-launcher, lighthouse-logger) (#29904)
We are using `chrome-launcher` and `lighthouse-logger` in
[test-pwa-score][1], but we do not explicitly list them as
`devDependencies`, so we are relying on the fact that they happen to be
hoisted in `node_modules/` by yarn. This may unexpectedly break in the
future.

This commit fixes this, by explicitly listing them as `devDependencies`.

[1]: https://github.com/angular/angular/blob/ea70d41ac/aio/scripts/test-pwa-score.js#L14-L18

PR Close #29904
2019-04-15 09:12:38 -07:00
57047acf17 build(docs-infra): upgrade lighthouse to 4.3.0 (#29904)
Also, log the Lighthouse version in `test-pwa-score` to aid in
debugging.

PR Close #29904
2019-04-15 09:12:38 -07:00
84 changed files with 1942 additions and 4797 deletions

View File

@ -240,7 +240,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:
@ -266,12 +266,6 @@ jobs:
steps:
- *attach_workspace
- *init_environment
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
# package installer picks up the locally built packages from that location.
# *Note*: We could also adjust the packages installer, but given we won't have
# two different folders of Angular distributions in the future, it's likely not
# worth the efforts to change the AIO packages installer.
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
# Build aio with Ivy (using local Angular packages)
- run: yarn --cwd aio build-with-ivy --progress=false
@ -463,7 +457,32 @@ 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:
- *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
@ -473,8 +492,8 @@ jobs:
- *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.
@ -552,7 +571,7 @@ workflows:
- build-npm-packages
# - test_aio_local_ivy:
# requires:
# - build-ivy-npm-packages
# - build-npm-packages
- test_aio_tools:
requires:
- build-npm-packages
@ -598,10 +617,16 @@ workflows:
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:

View File

@ -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;
}

View File

@ -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.
####################################################################################################

Binary file not shown.

26
.github/CODEOWNERS vendored
View File

@ -275,6 +275,7 @@
# @angular/fw-docs-intro
# ===========================================================
#
# - jenniferfell
# - brandonroberts
# - IgorMinar
# - stephenfluin
@ -307,6 +308,18 @@
# - mgechev
# ===========================================================
# @angular/tools-docs-schematics
# ===========================================================
#
# - alan-agius4
# - alexeagle
# - hansl
# - IgorMinar
# - mgechev
# ===========================================================
# @angular/fw-docs-marketing
# ===========================================================
@ -725,6 +738,7 @@ testing/** @angular/fw-test
/aio/* @angular/docs-infra @angular/framework-global-approvers
/aio/aio-builds-setup/** @angular/docs-infra @angular/framework-global-approvers
/aio/content/examples/* @angular/docs-infra @angular/framework-global-approvers
/aio/scripts/** @angular/docs-infra @angular/framework-global-approvers
/aio/src/** @angular/docs-infra @angular/framework-global-approvers
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
@ -758,7 +772,6 @@ testing/** @angular/fw-test
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# Docs: observables
# ================================================
@ -803,6 +816,17 @@ testing/** @angular/fw-test
/aio/content/guide/using-libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# Docs: schematics
# ================================================
/aio/content/guide/schematics.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/schematics-authoring.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/schematics-for-libraries.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/schematics/** @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/schematics-for-libraries/** @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# Docs: marketing

View File

@ -1,3 +1,33 @@
<a name="7.2.16"></a>
## [7.2.16](https://github.com/angular/angular/compare/7.2.15...7.2.16) (2020-01-08)
### Security Fixes
* build: upgrade yargs package to 13.1.0 ([#31457](https://github.com/angular/angular/issues/34157))
This release backports a security patch which fixes a transitive dependency on a vulnerable version of the `mem` package. See [#33933](https://github.com/angular/angular/issues/33933) for details.
<a name="7.2.15"></a>
## [7.2.15](https://github.com/angular/angular/compare/7.2.14...7.2.15) (2019-05-07)
### Bug Fixes
* **upgrade:** do not break if `onMicrotaskEmpty` emits while a `$digest` is in progress ([#29794](https://github.com/angular/angular/issues/29794)) ([#30107](https://github.com/angular/angular/issues/30107)) ([1084c19](https://github.com/angular/angular/commit/1084c19)), closes [#24680](https://github.com/angular/angular/issues/24680) [/github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts#L12](https://github.com//github.com/angular/angular/blob/78146c189/packages/core/src/util/ng_dev_mode.ts/issues/L12) [#24680](https://github.com/angular/angular/issues/24680)
<a name="7.2.14"></a>
## [7.2.14](https://github.com/angular/angular/compare/7.2.13...7.2.14) (2019-04-23)
### Bug Fixes
* **common:** prevent repeated application of HttpParams mutations ([#29045](https://github.com/angular/angular/issues/29045)) ([ee65d0d](https://github.com/angular/angular/commit/ee65d0d)), closes [#20430](https://github.com/angular/angular/issues/20430)
<a name="7.2.13"></a>
## [7.2.13](https://github.com/angular/angular/compare/7.2.12...7.2.13) (2019-04-12)

View File

@ -1,5 +1,5 @@
# Image metadata and config
FROM debian:jessie
FROM debian:stretch
LABEL name="angular.io PR preview" \
description="This image implements the PR preview functionality for angular.io." \
@ -40,7 +40,7 @@ ARG AIO_TRUSTED_PR_LABEL="aio: preview"
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG AIO_ARTIFACT_MAX_SIZE=20971520
ARG AIO_ARTIFACT_MAX_SIZE=26214400
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
ARG AIO_PREVIEW_SERVER_PORT=3000
ARG TEST_AIO_PREVIEW_SERVER_PORT=3001
@ -76,21 +76,20 @@ RUN apt-get update -y && apt-get install -y curl
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_10.x | bash -
RUN curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/backports.list
RUN echo "deb http://ftp.debian.org/debian stretch-backports main" | tee /etc/apt/sources.list.d/backports.list
# Install packages
RUN apt-get update -y && apt-get install -y \
chkconfig \
cron \
dnsmasq \
nano \
nodejs \
openssl \
rsyslog \
yarn
RUN apt-get install -t jessie-backports -y nginx
RUN yarn global add pm2@2
cron=3.0pl1-128+deb9u1 \
dnsmasq=2.76-5+deb9u2 \
nano=2.7.4-1 \
nginx=1.10.3-1+deb9u2 \
nodejs=10.15.3-1nodesource1 \
openssl=1.1.0j-1~deb9u1 \
rsyslog=8.24.0-1 \
yarn=1.15.2-1
RUN yarn global add pm2@3.5.0
# Set up log rotation
@ -151,8 +150,7 @@ RUN sed -i "s|{{\$AIO_PREVIEW_SERVER_PORT}}|$TEST_AIO_PREVIEW_SERVER_PORT|g" /et
# Set up pm2
RUN pm2 startup systemv -u root > /dev/null
RUN chkconfig pm2-root on
RUN pm2 startup --user root > /dev/null
# Set up the shell scripts

View File

@ -1,7 +1,6 @@
// Imports
import * as cp from 'child_process';
import * as fs from 'fs';
import * as http from 'http';
import * as path from 'path';
import * as shell from 'shelljs';
import {AIO_DOWNLOADS_DIR, HIDDEN_DIR_PREFIX} from '../common/constants';
@ -105,18 +104,7 @@ class Helper {
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
}
public verifyResponse(status: number | [number, string], regex: string | RegExp = /^/): VerifyCmdResultFn {
let statusCode: number;
let statusText: string;
if (Array.isArray(status)) {
statusCode = status[0];
statusText = status[1];
} else {
statusCode = status;
statusText = http.STATUS_CODES[statusCode] || 'UNKNOWN_STATUS_CODE';
}
public verifyResponse(status: number, regex: string | RegExp = /^/): VerifyCmdResultFn {
return (result: CmdResult) => {
const [headers, body] = result.stdout.
split(/(?:\r?\n){2,}/).
@ -131,7 +119,7 @@ class Helper {
}
expect(result.success).toBe(true);
expect(headers).toContain(`${statusCode} ${statusText}`);
expect(headers).toMatch(new RegExp(`HTTP/(?:1\\.1|2) ${status} `));
expect(body).toMatch(regex);
};
}

View File

@ -259,10 +259,10 @@ describe(`nginx`, () => {
it('should disallow non-GET requests', async () => {
await Promise.all([
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse(405)),
]);
});
@ -295,10 +295,10 @@ describe(`nginx`, () => {
const url = `${scheme}://${host}/circle-build`;
Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]).then(done);
});
@ -334,10 +334,10 @@ describe(`nginx`, () => {
it('should disallow non-POST requests', done => {
Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]).then(done);
});

View File

@ -1,5 +1,5 @@
{
"$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"packageManager": "yarn",
@ -21,6 +21,7 @@
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"webWorkerTsConfig": "src/tsconfig.worker.json",
"aot": true,
"optimization": true,
"buildOptimizer": true,
@ -35,7 +36,6 @@
"assets": [
"src/assets",
"src/generated",
"src/app/search/search-worker.js",
"src/pwa-manifest.json",
"src/google385281288605d160.html",
{
@ -123,6 +123,7 @@
"karmaConfig": "src/karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"webWorkerTsConfig": "src/tsconfig.worker.json",
"scripts": [],
"styles": [
"src/styles.scss"
@ -130,7 +131,6 @@
"assets": [
"src/assets",
"src/generated",
"src/app/search/search-worker.js",
"src/pwa-manifest.json",
"src/google385281288605d160.html",
{

View File

@ -2,30 +2,31 @@
import { browser, element, by } from 'protractor';
describe('Attribute directives', function () {
describe('Attribute directives', () => {
let _title = 'My First Attribute Directive';
beforeAll(function () {
beforeAll(() => {
browser.get('');
});
it(`should display correct title: ${_title}`, function () {
it(`should display correct title: ${_title}`, () => {
expect(element(by.css('h1')).getText()).toEqual(_title);
});
it('should be able to select green highlight', function () {
let highlightedEle = element(by.cssContainingText('p', 'Highlight me!'));
let lightGreen = 'rgba(144, 238, 144, 1)';
it('should be able to select green highlight', () => {
const highlightedEle = element(by.cssContainingText('p', 'Highlight me!'));
const lightGreen = 'rgba(144, 238, 144, 1)';
const getBgColor = () => highlightedEle.getCssValue('background-color');
expect(highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen);
// let greenRb = element(by.cssContainingText('input', 'Green'));
let greenRb = element.all(by.css('input')).get(0);
greenRb.click().then(function() {
// TypeScript Todo: find the right type for highlightedEle
browser.actions().mouseMove(highlightedEle as any).perform();
expect(highlightedEle.getCssValue('background-color')).toEqual(lightGreen);
});
const greenRb = element.all(by.css('input')).get(0);
greenRb.click();
browser.actions().mouseMove(highlightedEle).perform();
// Wait for up to 2s for the background color to be updated,
// to account for slow environments (e.g. CI).
browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 2000);
});
});

View File

@ -73,8 +73,12 @@ describe('Dependency Injection Cookbook', function () {
let yellow = 'rgba(255, 255, 0, 1)';
expect(target.getCssValue('background-color')).not.toEqual(yellow);
browser.actions().mouseMove(target.getWebElement()).perform();
expect(target.getCssValue('background-color')).toEqual(yellow);
browser.actions().mouseMove(target).perform();
// Wait for up to 2s for the background color to be updated,
// to account for slow environments (e.g. CI).
browser.wait(() => target.getCssValue('background-color').then(c => c === yellow), 2000);
});
describe('in Parent Finder', function () {

View File

@ -1,39 +1,42 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
import { browser, element, ElementFinder, by } from 'protractor';
describe('Lifecycle hooks', function () {
describe('Lifecycle hooks', () => {
const sendKeys = (el: ElementFinder, input: string) =>
input.split('').reduce((prev, c) => prev.then(() => el.sendKeys(c)), Promise.resolve());
beforeAll(function () {
beforeAll(() => {
browser.get('');
});
it('should open correctly', function () {
it('should open correctly', () => {
expect(element.all(by.css('h2')).get(0).getText()).toEqual('Peek-A-Boo');
});
it('should support peek-a-boo', function () {
it('should support peek-a-boo', async () => {
let pabComp = element(by.css('peek-a-boo-parent peek-a-boo'));
expect(pabComp.isPresent()).toBe(false, 'should not be able to find the "peek-a-boo" component');
let pabButton = element.all(by.css('peek-a-boo-parent button')).get(0);
let updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1);
expect(pabButton.getText()).toContain('Create Peek');
pabButton.click().then(function () {
expect(pabButton.getText()).toContain('Destroy Peek');
expect(pabComp.isDisplayed()).toBe(true, 'should be able to see the "peek-a-boo" component');
expect(pabComp.getText()).toContain('Windstorm');
expect(pabComp.getText()).not.toContain('Windstorm!');
expect(updateHeroButton.isPresent()).toBe(true, 'should be able to see the update hero button');
return updateHeroButton.click();
}).then(function () {
expect(pabComp.getText()).toContain('Windstorm!');
return pabButton.click();
}).then(function () {
expect(pabComp.isPresent()).toBe(false, 'should no longer be able to find the "peek-a-boo" component');
});
await pabButton.click();
expect(pabButton.getText()).toContain('Destroy Peek');
expect(pabComp.isDisplayed()).toBe(true, 'should be able to see the "peek-a-boo" component');
expect(pabComp.getText()).toContain('Windstorm');
expect(pabComp.getText()).not.toContain('Windstorm!');
expect(updateHeroButton.isPresent()).toBe(true, 'should be able to see the update hero button');
await updateHeroButton.click();
expect(pabComp.getText()).toContain('Windstorm!');
await pabButton.click();
expect(pabComp.isPresent()).toBe(false, 'should no longer be able to find the "peek-a-boo" component');
});
it('should support OnChanges hook', function () {
it('should support OnChanges hook', () => {
let onChangesViewEle = element.all(by.css('on-changes div')).get(0);
let inputEles = element.all(by.css('on-changes-parent input'));
let heroNameInputEle = inputEles.get(1);
@ -52,7 +55,7 @@ describe('Lifecycle hooks', function () {
expect(changeLogEles.count()).toEqual(7, 'should have 7 messages now');
});
it('should support DoCheck hook', function () {
it('should support DoCheck hook', async () => {
let doCheckViewEle = element.all(by.css('do-check div')).get(0);
let inputEles = element.all(by.css('do-check-parent input'));
let heroNameInputEle = inputEles.get(1);
@ -62,26 +65,25 @@ describe('Lifecycle hooks', function () {
let logCount: number;
expect(titleEle.getText()).toContain('Windstorm can sing');
changeLogEles.count().then(function(count: number) {
// 3 messages to start
expect(count).toEqual(3, 'should start with 3 messages');
logCount = count;
return heroNameInputEle.sendKeys('-foo-');
}).then(function () {
expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
return changeLogEles.count();
}).then(function(count: number) {
// one more for each keystroke
expect(count).toEqual(logCount + 5, 'should add 5 more messages');
logCount = count;
return powerInputEle.sendKeys('-bar-');
}).then(function () {
expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
expect(changeLogEles.count()).toEqual(logCount + 6, 'should add 6 more messages');
});
let count = await changeLogEles.count();
// 3 messages to start
expect(count).toEqual(3, 'should start with 3 messages');
logCount = count;
await sendKeys(heroNameInputEle, '-foo-');
count = await changeLogEles.count();
expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
expect(count).toBeGreaterThanOrEqual(logCount + 5, 'should add at least one more message for each keystroke');
logCount = count;
await sendKeys(powerInputEle, '-bar-');
count = await changeLogEles.count();
expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
expect(count).toBeGreaterThanOrEqual(logCount + 5, 'should add at least one more message for each keystroke');
});
it('should support AfterView hooks', function () {
it('should support AfterView hooks', async () => {
let parentEle = element(by.tagName('after-view-parent'));
let buttonEle = parentEle.element(by.tagName('button')); // Reset
let commentEle = parentEle.element(by.className('comment'));
@ -92,90 +94,81 @@ describe('Lifecycle hooks', function () {
expect(childViewInputEle.getAttribute('value')).toContain('Magneta');
expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM');
logEles.count().then(function(count: number) {
logCount = count;
return childViewInputEle.sendKeys('-test-');
}).then(function() {
expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name');
return logEles.count();
}).then(function(count: number) {
expect(logCount + 7).toBeGreaterThan(count - 3,
'7 additional log messages should have been added');
expect(logCount + 7).toBeLessThan(count + 3,
'7 additional log messages should have been added');
logCount = count;
return buttonEle.click();
}).then(function() {
expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
});
logCount = await logEles.count();
await childViewInputEle.sendKeys('-test-');
expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name');
let count = await logEles.count();
expect(logCount + 7).toBeGreaterThan(count - 3, '7 additional log messages should have been added');
expect(logCount + 7).toBeLessThan(count + 3, '7 additional log messages should have been added');
logCount = count;
await buttonEle.click();
expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
});
it('should support AfterContent hooks', function () {
it('should support AfterContent hooks', async () => {
let parentEle = element(by.tagName('after-content-parent'));
let buttonEle = parentEle.element(by.tagName('button')); // Reset
let commentEle = parentEle.element(by.className('comment'));
let logEles = parentEle.all(by.css('h4 ~ div'));
let childViewInputEle = parentEle.element(by.css('app-child input'));
let logCount: number;
let logCount = await logEles.count();
expect(childViewInputEle.getAttribute('value')).toContain('Magneta');
expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM');
logEles.count().then(function(count: number) {
logCount = count;
return childViewInputEle.sendKeys('-test-');
}).then(function() {
expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name');
return logEles.count();
}).then(function(count: number) {
expect(logCount + 5).toEqual(count, '5 additional log messages should have been added');
logCount = count;
return buttonEle.click();
}).then(function() {
expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
});
await sendKeys(childViewInputEle, '-test-');
let count = await logEles.count();
expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name');
expect(count).toBeGreaterThanOrEqual(logCount + 5, 'additional log messages should have been added');
logCount = count;
await buttonEle.click();
expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
});
it('should support spy\'s OnInit & OnDestroy hooks', function () {
it('should support spy\'s OnInit & OnDestroy hooks', async () => {
let inputEle = element(by.css('spy-parent input'));
let addHeroButtonEle = element(by.cssContainingText('spy-parent button', 'Add Hero'));
let resetHeroesButtonEle = element(by.cssContainingText('spy-parent button', 'Reset Heroes'));
let heroEles = element.all(by.css('spy-parent div[mySpy'));
let logEles = element.all(by.css('spy-parent h4 ~ div'));
expect(heroEles.count()).toBe(2, 'should have two heroes displayed');
expect(logEles.count()).toBe(2, 'should have two log entries');
inputEle.sendKeys('-test-').then(function() {
return addHeroButtonEle.click();
}).then(function() {
expect(heroEles.count()).toBe(3, 'should have added one hero');
expect(heroEles.get(2).getText()).toContain('-test-');
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
return resetHeroesButtonEle.click();
}).then(function() {
expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
});
await inputEle.sendKeys('-test-');
await addHeroButtonEle.click();
expect(heroEles.count()).toBe(3, 'should have added one hero');
expect(heroEles.get(2).getText()).toContain('-test-');
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
await resetHeroesButtonEle.click();
expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
});
it('should support "spy counter"', function () {
it('should support "spy counter"', async () => {
let updateCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Update'));
let resetCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Reset'));
let textEle = element(by.css('counter-parent app-counter > div'));
let logEles = element.all(by.css('counter-parent h4 ~ div'));
expect(textEle.getText()).toContain('Counter = 0');
expect(logEles.count()).toBe(2, 'should start with two log entries');
updateCounterButtonEle.click().then(function() {
expect(textEle.getText()).toContain('Counter = 1');
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
return resetCounterButtonEle.click();
}).then(function() {
expect(textEle.getText()).toContain('Counter = 0');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
});
await updateCounterButtonEle.click();
expect(textEle.getText()).toContain('Counter = 1');
expect(logEles.count()).toBe(3, 'should now have 3 log entries');
await resetCounterButtonEle.click();
expect(textEle.getText()).toContain('Counter = 0');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
});
});

View File

@ -1,221 +0,0 @@
# Change Log
The Angular documentation is a living document with continuous improvements.
This log calls attention to recent significant changes.
## Updated to Angular 4.0. Documentation for Angular 2.x can be found at [v2.angular.io](https://v2.angular.io).
## All mention of moduleId removed. "Component relative paths" guide deleted (2017-03-13)
We added a new SystemJS plugin (systemjs-angular-loader.js) to our recommended SystemJS configuration.
This plugin dynamically converts "component-relative" paths in templateUrl and styleUrls to "absolute paths" for you.
We strongly encourage you to only write component-relative paths.
That is the only form of URL discussed in these docs. You no longer need to write @Component({ moduleId: module.id }), nor should you.
## NEW: Downloadable examples for each guide (2017-02-28)
Now you can download the sample code for any guide and run it locally.
Look for the new download links next to the "live example" links.
## Template Syntax/Structural Directives: refreshed (2017-02-06)
The [_Template-Syntax_](guide/template-syntax) and [_Structural Directives_](guide/structural-directives)
guides were significantly revised for clarity, accuracy, and current recommended practices.
Discusses `<ng-container>`.
Revised samples are more clear and cover all topics discussed.
## NEW: Samples re-structured with `src/` folder (2017-02-02)
All documentation samples have been realigned with the default folder structure of the Angular CLI.
That's a step along the road to basing the sample in the Angular CLI.
But it's also good in its own right.
It helps clearly separate app code from setup and configuration files.
All samples now have a `src/` folder at the project root.
The former `app/` folder moves under `src/`.
Read about moving your existing project to this structure in
<a href="https://github.com/angular/quickstart#updating-to-a-newer-version-of-the-quickstart-repo" target="Migrating samples/quickstart app to the src folder">
the QuickStart repo update instructions</a>.
Notably:
* `app/main.ts` moved to `src/main.ts`.
* `app/` moved to `src/app/`.
* `index.html`, `styles.css` and `tsconfig.json` moved inside `src/`.
* `systemjs.config.js` now imports `main.js` instead of `app`.
* Added `lite-server` configuration (`bs-config.json`) to serve `src/`.
## NEW: Reactive Forms guide (2017-01-31)
The new [**Reactive Forms**](guide/reactive-forms) guide explains how and why to build a "reactive form".
"Reactive Forms" are the code-based counterpart to the declarative "Template Driven" forms approach
introduced in the [Forms](guide/forms) guide.
Check it out before you decide how to add forms to your app.
Remember also that you can use both techniques in the same app,
choosing the approach that best fits each scenario.
## NEW: Deployment guide (2017-01-30)
The new [Deployment](guide/deployment) guide describes techniques for putting your application on a server.
It includes important advice on optimizing for production.
## Hierarchical Dependency Injection: refreshed (2017-01-13)
[Hierarchical Dependency Injection](guide/hierarchical-dependency-injection) guide is significantly revised.
Closes issue #3086.
Revised samples are clearer and cover all topics discussed.
## Miscellaneous (2017-01-05)
* [Setup](guide/setup) guide:
added (optional) instructions on how to remove _non-essential_ files.
* No longer consolidate RxJS operator imports in `rxjs-extensions` file; each file should import what it needs.
* All samples prepend template/style URLs with `./` as a best practice.
* [Style Guide](guide/styleguide): copy edits and revised rules.
## Router: more detail (2016-12-21)
Added more information to the [Router](guide/router) guide
including sections named outlets, wildcard routes, and preload strategies.
## HTTP: how to set default request headers (and other request options) (2016-12-14)
Added section on how to set default request headers (and other request options) to
HTTP guide.
## Testing: added component test plunkers (2016-12-02)
Added two plunkers that each test _one simple component_ so you can write a component test plunker of your own: <live-example name="setup" plnkr="quickstart-specs">one</live-example> for the QuickStart seed's `AppComponent` and <live-example name="testing" plnkr="banner-specs">another</live-example> for the Testing guide's `BannerComponent`.
Linked to these plunkers in "Testing" and "Setup anatomy" guides.
## Internationalization: pluralization and _select_ (2016-11-30)
The [Internationalization (i18n)](guide/i18n) guide explains how to handle pluralization and
translation of alternative texts with `select`.
The sample demonstrates these features too.
## Testing: karma file updates (2016-11-30)
* `karma.config` + `karma-test-shim` can handle multiple spec source paths;
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294).
* Displays Jasmine Runner output in the karma-launched browser.
## QuickStart Rewrite (2016-11-18)
The QuickStart is completely rewritten so that it actually is quick.
It references a minimal "Hello Angular" app running in Plunker.
The new [Setup](guide/setup) page tells you how to install a local development environment
by downloading (or cloning) the QuickStart github repository.
You are no longer asked to copy-and-paste code into setup files that were not explained anyway.
## Sync with Angular v.2.2.0 (2016-11-14)
Docs and code samples updated and tested with Angular v.2.2.0.
## UPDATE: NgUpgrade Guide for the AOT friendly _upgrade/static_ module (2016-11-14)
The updated [NgUpgrade Guide](guide/upgrade) guide covers the
new AOT friendly `upgrade/static` module
released in v.2.2.0, which is the recommended
facility for migrating from AngularJS to Angular.
The documentation for the version prior to v.2.2.0 has been removed.
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
The updated TypeScript to JavaScript guide explains how to write apps in ES6/7
by translating the common idioms in the TypeScript documentation examples
(and elsewhere on the web) to ES6/7 and ES5.
This was [removed in August 2017](https://github.com/angular/angular/pull/18694) but can still be
viewed in the [v2 documentation](https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html).
## Sync with Angular v.2.1.1 (2016-10-21)
Docs and code samples updated and tested with Angular v.2.1.1.
## npm _@types_ packages replace _typings_ (2016-10-20)
Documentation samples now get TypeScript type information for 3rd party libraries
from npm `@types` packages rather than with the _typings_ tooling.
The `typings.json` file is gone.
The [AngularJS Upgrade](guide/upgrade) guide reflects this change.
The `package.json` installs `@types/angular` and several `@types/angular-...`
packages in support of upgrade; these are not needed for pure Angular development.
## "Template Syntax" explains two-way data binding syntax (2016-10-20)
Demonstrates how to two-way data bind to a custom Angular component and
re-explains `[(ngModel)]` in terms of the basic `[()]` syntax.
## BREAKING CHANGE: `in-memory-web-api` (v.0.1.11) delivered as esm umd (2016-10-19)
This change supports ES6 developers and aligns better with typical Angular libraries.
It does not affect the module's API but it does affect how you load and import it.
See the <a href="https://github.com/angular/in-memory-web-api/blob/master/CHANGELOG.md#0113-2016-10-20">change note</a>
in the `in-memory-web-api` repo.
## "Router" _preload_ syntax and _:enter_/_:leave_ animations (2016-10-19)
The router can lazily _preload_ modules _after_ the app starts and
_before_ the user navigates to them for improved perceived performance.
New `:enter` and `:leave` aliases make animation more natural.
## Sync with Angular v.2.1.0 (2016-10-12)
Docs and code samples updated and tested with Angular v.2.1.0.
## NEW "Ahead of time (AOT) Compilation" guide (2016-10-11)
The NEW [Ahead of time (AOT) Compilation](guide/aot-compiler) guide
explains what AOT compilation is and why you'd want it.
It demonstrates the basics with a QuickStart app
followed by the more advanced considerations of compiling and bundling the Tour of Heroes.
## Sync with Angular v.2.0.2 (2016-10-6)
Docs and code samples updated and tested with Angular v.2.0.2.
## "Routing and Navigation" guide with the _Router Module_ (2016-10-5)
The [Routing and Navigation](guide/router) guide now locates route configuration
in a _Routing Module_.
The _Routing Module_ replaces the previous _routing object_ involving the `ModuleWithProviders`.
All guided samples with routing use the _Routing Module_ and prose content has been updated,
most conspicuously in the
[NgModule](guide/ngmodules) guide and [NgModule FAQ](guide/ngmodule-faq) guide.
## New "Internationalization" guide (2016-09-30)
Added a new [Internationalization (i18n)](guide/i18n) guide that shows how
to use Angular "i18n" facilities to translate template text into multiple languages.
## "angular-in-memory-web-api" package rename (2016-09-27)
Many samples use the `angular-in-memory-web-api` to simulate a remote server.
This library is also useful to you during early development before you have a server to talk to.
The package name was changed from "angular2-in-memory-web-api" which is still frozen-in-time on npm.
The new "angular-in-memory-web-api" has new features.
<a href="https://github.com/angular/in-memory-web-api/blob/master/README.md">Read about them on github</a>.
## "Style Guide" with _NgModules_ (2016-09-27)
[StyleGuide](guide/styleguide) explains recommended conventions for NgModules.
Barrels now are far less useful and have been removed from the style guide;
they remain valuable but are not a matter of Angular style.
Also relaxed the rule that discouraged use of the `@Component.host` property.
## _moduleId: module.id_ everywhere (2016-09-25)
Sample components that get their templates or styles with `templateUrl` or `styleUrls`
have been converted to _module-relative_ URLs.
Added the `moduleId: module.id` property-and-value to their `@Component` metadata.
This change is a requirement for compilation with AOT compiler when the app loads
modules with SystemJS as the samples currently do.
## "Lifecycle Hooks" guide simplified (2016-09-24)
The [Lifecycle Hooks](guide/lifecycle-hooks) guide is shorter, simpler, and
draws more attention to the order in which Angular calls the hooks.

View File

@ -209,7 +209,7 @@ Learn more in the [Testing](guide/testing) guide.
## Services that need other services
Service can have their own dependencies. `HeroService` is very simple and doesn't have any dependencies of its own. Suppose, however, that you want it to report its activities through a logging service. You can apply the same *constructor injection* pattern,
Services can have their own dependencies. `HeroService` is very simple and doesn't have any dependencies of its own. Suppose, however, that you want it to report its activities through a logging service. You can apply the same *constructor injection* pattern,
adding a constructor that takes a `Logger` parameter.
Here is the revised `HeroService` that injects `Logger`, side by side with the previous service for comparison.

View File

@ -750,7 +750,7 @@ with the injected `MessageService`.
header="app/http-interceptors/logging-interceptor.ts)">
</code-example>
The RxJS `tap` operator captures whether the request succeed or failed.
The RxJS `tap` operator captures whether the request succeeded or failed.
The RxJS `finalize` operator is called when the response observable either errors or completes (which it must),
and reports the outcome to the `MessageService`.

View File

@ -369,7 +369,7 @@ except that you choose among alternative translations based on a string value in
and you define those string values.
The following format message in the component template binds to the component's `gender` property,
which outputs one of the following string values: "m", "f" or "o".
which outputs one of the following string values: "male", "female" or "other".
The message maps those values to the appropriate translations:
<code-example path="i18n/src/app/app.component.html" region="i18n-select" header="src/app/app.component.html" linenums="false">

View File

@ -230,7 +230,7 @@ In this example, `address group` combines the current `firstName` and `lastName`
After you update the model in the component class, update the template to connect the form group instance and its input elements.
Add the `address` form group containing the `firstName` and `lastName` fields to the `ProfileEditor` template.
Add the `address` form group containing the `street`, `city`, `state`, and `zip` fields to the `ProfileEditor` template.
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.1.html" region="formgroupname" linenums="false" header="src/app/profile-editor/profile-editor.component.html (template nested form group)">

View File

@ -1,6 +1,6 @@
# Service worker in production
This page is a reference for deploying and supporting production apps that use the Angular service worker. It explains how the Angular service worker fits into the larger production environment, the service worker's behavior under various conditions, and available recourses and fail-safes.
This page is a reference for deploying and supporting production apps that use the Angular service worker. It explains how the Angular service worker fits into the larger production environment, the service worker's behavior under various conditions, and available resources and fail-safes.
#### Prerequisites

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -778,5 +778,20 @@
"groups": ["Collaborators"],
"mentor": "gregmagolan",
"picture": "globegitter.jpg"
},
"ahsanayaz": {
"name": "Muhammad Ahsan Ayaz",
"picture": "ahsanayaz.jpg",
"twitter": "ahsan_ayz",
"website": "https://medium.com/@ahsan.ayaz",
"bio": "Muhammad Ahsan Ayaz is Software Architect at Modus Create. He is absolutely passionate about Angular and Web Technologies. Uses Angular daily and talks about it everywhere. Runs NodeSchool Karachi and is a co-organizer of NgPakistan",
"groups": ["GDE"]
},
"andrewkushnir": {
"name": "Andrew Kushnir",
"picture": "andrew-kushnir.jpg",
"bio": "Andrew is a software engineer at Google on the Angular Core team.",
"groups": ["Angular"],
"lead": "kara"
}
}

View File

@ -25,6 +25,12 @@
<td>Copenhagen, Denmark</td>
<td>May 26 (workshops), 27-28 (conference), 2019</td>
</tr>
<!-- ngJapan-->
<tr>
<th><a href="https://ngjapan.org" title="ng-japan">ng-japan</a></th>
<td>Tokyo, Japan</td>
<td>July 13, 2019</td>
</tr>
<!-- AngularConnect 2019-->
<tr>
<th><a href="https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral" title="AngularConnect">AngularConnect</a></th>

View File

@ -679,12 +679,6 @@
"title": "API",
"tooltip": "Details of the Angular packages, classes, interfaces, and other types.",
"url": "api"
},
{
"url": "guide/change-log",
"title": "Change Log",
"tooltip": "Angular Documentation Change Log",
"hidden": true
}
],

View File

@ -101,7 +101,7 @@ configure it with the `routes` in one step by calling
## Add _RouterOutlet_
Open the `AppComponent` template replace the `<app-heroes>` element with a `<router-outlet>` element.
Open the `AppComponent` template and replace the `<app-heroes>` element with a `<router-outlet>` element.
<code-example path="toh-pt5/src/app/app.component.html"
region="outlet"

View File

@ -27,6 +27,7 @@
{"type": 301, "source": "/guide/service-worker-configref", "destination": "/guide/service-worker-config"},
{"type": 301, "source": "/guide/webpack", "destination": "https://v5.angular.io/guide/webpack"},
{"type": 301, "source": "/guide/setup-systemjs-anatomy", "destination": "/guide/file-structure"},
{"type": 301, "source": "/guide/change-log", "destination": "https://github.com/angular/angular/blob/master/CHANGELOG.md"},
// some top level guide pages on old site were moved below the guide folder
{"type": 301, "source": "/styleguide", "destination": "/guide/styleguide"},
@ -39,7 +40,7 @@
{"type": 301, "source": "/docs/*/latest/cookbook", "destination": "/docs"},
{"type": 301, "source": "/docs/*/latest/cookbook/", "destination": "/docs"},
{"type": 301, "source": "/docs/*/latest/cookbook/index.html", "destination": "/docs"},
{"type": 301, "source": "/**/cookbook/ts-to-js*", "destination": "https://github.com/angular/angular/blob/master/aio/content/guide/change-log.md#es6--described-in-typescript-to-javascript-2016-11-14"},
{"type": 301, "source": "/**/cookbook/ts-to-js*", "destination": "https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html"},
{"type": 301, "source": "/docs/*/latest/cookbook/a1-a2-quick-reference.html", "destination": "/guide/ajs-quick-reference"},
{"type": 301, "source": "/docs/*/latest/cookbook/component-communication.html", "destination": "/guide/component-interaction"},
{"type": 301, "source": "/docs/*/latest/cookbook/dependency-injection.html", "destination": "/guide/dependency-injection-in-action"},

View File

@ -9,10 +9,8 @@
"files": [
"/index.html",
"/pwa-manifest.json",
"/app/search/search-worker.js",
"/assets/images/favicons/favicon.ico",
"/assets/js/*.js",
"/generated/lunr.min.js",
"/*.css",
"/*.js"
],
@ -93,6 +91,7 @@
"!/api/testing/**",
"!/docs/?*",
"!/docs/*/**",
"!/guide/change-log",
"!/guide/cli-quickstart",
"!/guide/cli-quickstart.html",
"!/guide/cli-quickstart/",

View File

@ -17,8 +17,8 @@
"build": "yarn ~~build",
"prebuild-local": "yarn setup-local",
"build-local": "yarn ~~build",
"prebuild-with-ivy": "yarn setup-local && yarn ivy-ngcc --formats fesm2015 fesm5",
"build-with-ivy": "node scripts/build-with-ivy",
"prebuild-with-ivy": "yarn setup-local && node scripts/switch-to-ivy",
"build-with-ivy": "yarn ~~build",
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js b5e796a03",
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
"test": "yarn check-env && ng test",
@ -26,7 +26,7 @@
"e2e": "ng e2e --no-webdriver-update",
"presetup": "yarn --cwd .. install && yarn install --frozen-lockfile && yarn ~~check-env && yarn ~~clean-generated && yarn boilerplate:remove",
"setup": "yarn aio-use-npm && yarn example-use-npm",
"postsetup": "yarn ~~build-ie-polyfills && yarn ~~minify-lunr && yarn boilerplate:add && yarn extract-cli-command-docs && yarn docs",
"postsetup": "yarn ~~build-ie-polyfills && yarn boilerplate:add && yarn extract-cli-command-docs && yarn docs",
"presetup-local": "yarn presetup",
"setup-local": "yarn aio-use-local && yarn example-use-local",
"postsetup-local": "yarn postsetup",
@ -69,8 +69,7 @@
"~~build": "ng build --configuration=stable",
"post~~build": "yarn build-404-page",
"~~build-ie-polyfills": "webpack-cli src/ie-polyfills.js -o src/generated/ie-polyfills.min.js --mode production",
"~~http-server": "http-server",
"~~minify-lunr": "uglifyjs node_modules/lunr/lunr.js -c -m -o src/generated/lunr.min.js --source-map"
"~~http-server": "http-server"
},
"engines": {
"node": ">=10.9.0 <11.0.0",
@ -89,16 +88,17 @@
"@angular/platform-browser-dynamic": "^7.0.0",
"@angular/router": "^7.0.0",
"@angular/service-worker": "^7.0.0",
"@types/lunr": "^2.3.2",
"@webcomponents/custom-elements": "^1.2.0",
"classlist.js": "^1.1.20150312",
"core-js": "^2.4.1",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"tslib": "^1.9.0",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.12.1",
"@angular/cli": "7.2.1",
"@angular-devkit/build-angular": "0.800.0-beta.13",
"@angular/cli": "8.0.0-beta.13",
"@angular/compiler": "^7.0.0",
"@angular/compiler-cli": "^7.0.0",
"@angular/language-service": "^7.0.0",
@ -109,6 +109,7 @@
"archiver": "^1.3.0",
"canonical-path": "1.0.0",
"chalk": "^2.1.0",
"chrome-launcher": "^0.10.5",
"cjson": "^0.5.0",
"codelyzer": "~4.5.0",
"cross-spawn": "^5.1.0",
@ -142,7 +143,8 @@
"karma-coverage-istanbul-reporter": "^1.3.0",
"karma-jasmine": "^1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"lighthouse": "^3.2.1",
"lighthouse": "^4.3.0",
"lighthouse-logger": "^1.2.0",
"lodash": "^4.17.4",
"lunr": "^2.1.0",
"npm-run-all": "^4.1.5",

View File

@ -3,7 +3,7 @@
"master": {
"uncompressed": {
"runtime": 3713,
"main": 509261,
"main": 484710,
"polyfills": 53926
}
}

View File

@ -1,46 +0,0 @@
#!/usr/bin/env node
// Imports
const {extend, parse} = require('cjson');
const {readFileSync, writeFileSync} = require('fs');
const {join, resolve} = require('path');
const {exec, set} = require('shelljs');
set('-e');
// Constants
const ROOT_DIR = resolve(__dirname, '..');
const TS_CONFIG_PATH = join(ROOT_DIR, 'tsconfig.json');
const NG_COMPILER_OPTS = {
angularCompilerOptions: {
// Related Jira issue: FW-737
allowEmptyCodegenFiles: true,
enableIvy: 'ngtsc',
},
};
// Run
_main(process.argv.slice(2));
// Functions - Definitions
function _main(buildArgs) {
console.log('\nModifying `tsconfig.json`...');
const oldTsConfigStr = readFileSync(TS_CONFIG_PATH, 'utf8');
const oldTsConfigObj = parse(oldTsConfigStr);
const newTsConfigObj = extend(true, oldTsConfigObj, NG_COMPILER_OPTS);
const newTsConfigStr = JSON.stringify(newTsConfigObj, null, 2);
writeFileSync(TS_CONFIG_PATH, newTsConfigStr);
console.log(newTsConfigStr);
try {
const buildArgsStr = buildArgs.join(' ');
console.log(`\nBuilding${buildArgsStr && ` with args \`${buildArgsStr}\``}...`);
exec(`yarn ~~build ${buildArgsStr}`, {cwd: ROOT_DIR});
} finally {
console.log('\nRestoring `tsconfig.json`...');
writeFileSync(TS_CONFIG_PATH, oldTsConfigStr);
}
console.log('\nDone!');
}

View File

@ -0,0 +1,49 @@
#!/usr/bin/env node
// Imports
const {extend, parse} = require('cjson');
const {readFileSync, writeFileSync} = require('fs');
const {join, resolve} = require('path');
const {exec, set} = require('shelljs');
set('-e');
// Constants
const ROOT_DIR = resolve(__dirname, '..');
const NG_JSON = join(ROOT_DIR, 'angular.json');
const NG_COMPILER_OPTS = {
angularCompilerOptions: {
// Related Jira issue: FW-737
allowEmptyCodegenFiles: true,
enableIvy: true,
},
};
// Run
_main(process.argv.slice(2));
// Functions - Definitions
function _main() {
// Detect path to `tsconfig.app.json`.
const ngConfig = parse(readFileSync(NG_JSON, 'utf8'));
const tsConfigPath = join(ROOT_DIR, ngConfig.projects.site.architect.build.options.tsConfig);
// Enable Ivy in TS config.
console.log(`\nModifying \`${tsConfigPath}\`...`);
const oldTsConfigStr = readFileSync(tsConfigPath, 'utf8');
const oldTsConfigObj = parse(oldTsConfigStr);
const newTsConfigObj = extend(true, oldTsConfigObj, NG_COMPILER_OPTS);
const newTsConfigStr = JSON.stringify(newTsConfigObj, null, 2);
console.log(`\nNew config: ${newTsConfigStr}`);
writeFileSync(tsConfigPath, newTsConfigStr);
// Run ngcc.
const ngccArgs = '--loglevel debug --properties es2015 module';
console.log(`\nRunning ngcc (with args: ${ngccArgs})...`);
exec(`yarn ivy-ngcc ${ngccArgs}`);
// Done.
console.log('\nReady to build with Ivy!');
console.log('(To switch back to ViewEngine (with packages from npm), undo the changes in ' +
`\`${tsConfigPath}\` and run \`yarn aio-use-npm && yarn example-use-npm\`.)`);
}

View File

@ -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!"
)

View File

@ -2,7 +2,9 @@
/**
* Usage:
* node scripts/test-pwa-score <url> <min-score> [<log-file>]
* ```sh
* node scripts/test-pwa-score <url> <min-score> [<log-file>]
* ```
*
* Fails if the score is below `<min-score>`.
* If `<log-file>` is defined, the full results will be logged there.
@ -14,7 +16,6 @@
const chromeLauncher = require('chrome-launcher');
const lighthouse = require('lighthouse');
const printer = require('lighthouse/lighthouse-cli/printer');
const config = require('lighthouse/lighthouse-core/config/default-config.js');
const logger = require('lighthouse-logger');
// Constants
@ -22,6 +23,7 @@ const CHROME_LAUNCH_OPTS = {};
const LIGHTHOUSE_FLAGS = {logLevel: 'info'};
const SKIPPED_HTTPS_AUDITS = ['redirects-http'];
const VIEWER_URL = 'https://googlechrome.github.io/lighthouse/viewer/';
const WAIT_FOR_SW_DELAY = 5000;
// Be less verbose on CI.
if (process.env.CI) {
@ -32,22 +34,31 @@ if (process.env.CI) {
_main(process.argv.slice(2));
// Functions - Definitions
function _main(args) {
async function _main(args) {
const {url, minScore, logFile} = parseInput(args);
const isOnHttp = /^http:/.test(url);
const config = {
extends: 'lighthouse:default',
// Since the Angular ServiceWorker waits for the app to stabilize before registering,
// wait a few seconds after load to allow Lighthouse to reliably detect it.
passes: [{passName: 'defaultPass', pauseAfterLoadMs: WAIT_FOR_SW_DELAY}],
}
console.log(`Running PWA audit for '${url}'...`);
if (isOnHttp) {
skipHttpsAudits(config);
}
// If testing on HTTP, skip HTTPS-specific tests.
// (Note: Browsers special-case localhost and run ServiceWorker even on HTTP.)
if (isOnHttp) skipHttpsAudits(config);
logger.setLevel(LIGHTHOUSE_FLAGS.logLevel);
launchChromeAndRunLighthouse(url, LIGHTHOUSE_FLAGS, config).
then(results => processResults(results, logFile)).
then(score => evaluateScore(minScore, score)).
catch(onError);
try {
const results = await launchChromeAndRunLighthouse(url, LIGHTHOUSE_FLAGS, config);
const score = await processResults(results, logFile);
evaluateScore(minScore, score);
} catch (err) {
onError(err);
}
}
function evaluateScore(expectedScore, actualScore) {
@ -60,13 +71,15 @@ function evaluateScore(expectedScore, actualScore) {
}
}
function launchChromeAndRunLighthouse(url, flags, config) {
return chromeLauncher.launch(CHROME_LAUNCH_OPTS).then(chrome => {
flags.port = chrome.port;
return lighthouse(url, flags, config).
then(results => chrome.kill().then(() => results)).
catch(err => chrome.kill().then(() => { throw err; }, () => { throw err; }));
});
async function launchChromeAndRunLighthouse(url, flags, config) {
const chrome = await chromeLauncher.launch(CHROME_LAUNCH_OPTS);
flags.port = chrome.port;
try {
return await lighthouse(url, flags, config);
} finally {
await chrome.kill();
}
}
function onError(err) {
@ -88,34 +101,35 @@ function parseInput(args) {
return {url, minScore, logFile};
}
function processResults(results, logFile) {
async function processResults(results, logFile) {
const lhVersion = results.lhr.lighthouseVersion;
const categories = results.lhr.categories;
const report = results.report;
return Promise.resolve().
then(() => {
if (logFile) {
console.log(`Saving results in '${logFile}'...`);
console.log(`(LightHouse viewer: ${VIEWER_URL})`);
if (logFile) {
console.log(`\nSaving results in '${logFile}'...`);
console.log(`(LightHouse viewer: ${VIEWER_URL})`);
return printer.write(report, printer.OutputMode.json, logFile);
}
}).
then(() => {
const categoryData = Object.keys(categories).map(name => categories[name]);
const maxTitleLen = Math.max(...categoryData.map(({title}) => title.length));
await printer.write(report, printer.OutputMode.json, logFile);
}
console.log('\nAudit scores:');
categoryData.forEach(({title, score}) => {
const paddedTitle = `${title}:`.padEnd(maxTitleLen + 1);
const paddedScore = (score * 100).toFixed(0).padStart(3);
console.log(` - ${paddedTitle} ${paddedScore} / 100`);
});
}).
then(() => categories.pwa.score * 100);
const categoryData = Object.keys(categories).map(name => categories[name]);
const maxTitleLen = Math.max(...categoryData.map(({title}) => title.length));
console.log(`\nLighthouse version: ${lhVersion}`);
console.log('\nAudit scores:');
categoryData.forEach(({title, score}) => {
const paddedTitle = `${title}:`.padEnd(maxTitleLen + 1);
const paddedScore = (score * 100).toFixed(0).padStart(3);
console.log(` - ${paddedTitle} ${paddedScore} / 100`);
});
return categories.pwa.score * 100;
}
function skipHttpsAudits(config) {
console.info(`Skipping HTTPS-related audits (${SKIPPED_HTTPS_AUDITS.join(', ')})...`);
config.settings.skipAudits = SKIPPED_HTTPS_AUDITS;
const settings = config.settings || (config.settings = {});
settings.skipAudits = SKIPPED_HTTPS_AUDITS;
}

View File

@ -6,11 +6,12 @@ import { HttpClient } from '@angular/common/http';
import { MatProgressBar, MatSidenav } from '@angular/material';
import { By } from '@angular/platform-browser';
import { of, timer } from 'rxjs';
import { Subject, of, timer } from 'rxjs';
import { first, mapTo } from 'rxjs/operators';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
import { CurrentNodes } from 'app/navigation/navigation.model';
import { DocumentService } from 'app/documents/document.service';
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
import { Deployment } from 'app/shared/deployment.service';
@ -21,7 +22,7 @@ import { Logger } from 'app/shared/logger.service';
import { MockLocationService } from 'testing/location.service';
import { MockLogger } from 'testing/logger.service';
import { MockSearchService } from 'testing/search.service';
import { NavigationNode } from 'app/navigation/navigation.service';
import { NavigationNode, NavigationService } from 'app/navigation/navigation.service';
import { ScrollService } from 'app/shared/scroll.service';
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
import { SearchResultsComponent } from 'app/shared/search-results/search-results.component';
@ -808,106 +809,43 @@ describe('AppComponent', () => {
});
describe('archive redirection', () => {
it('should redirect to `docs` if deployment mode is `archive` and not at a docs page', () => {
createTestingModule('', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).toHaveBeenCalledWith('docs');
const redirectionPerMode: {[mode: string]: boolean} = {
archive: true,
next: false,
stable: false,
};
createTestingModule('resources', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).toHaveBeenCalledWith('docs');
Object.keys(redirectionPerMode).forEach(mode => {
const doRedirect = redirectionPerMode[mode];
const description =
`should ${doRedirect ? '' : 'not '}redirect to 'docs' if deployment mode is '${mode}' ` +
'and at a marketing page';
const verifyNoRedirection = () => expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
const verifyRedirection = () => expect(TestBed.get(LocationService).replace).toHaveBeenCalledWith('docs');
const verifyPossibleRedirection = doRedirect ? verifyRedirection : verifyNoRedirection;
createTestingModule('guide/aot-compiler', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
it(description, () => {
createTestingModule('', mode);
createTestingModule('tutorial', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
const navService = TestBed.get(NavigationService) as NavigationService;
const testCurrentNodes = navService.currentNodes = new Subject<CurrentNodes>();
createTestingModule('tutorial/toh-pt1', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
initializeTest(false);
createTestingModule('docs', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
testCurrentNodes.next({SideNav: {url: 'foo', view: 'SideNav', nodes: []}});
verifyNoRedirection();
createTestingModule('api', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
testCurrentNodes.next({NoSideNav: {url: 'bar', view: 'SideNav', nodes: []}});
verifyPossibleRedirection();
createTestingModule('api/core/getPlatform', 'archive');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
});
locationService.replace.calls.reset();
testCurrentNodes.next({});
verifyPossibleRedirection();
it('should not redirect if deployment mode is `next`', () => {
createTestingModule('', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('resources', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('guide/aot-compiler', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('tutorial', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('tutorial/toh-pt1', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('docs', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('api', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('api/core/getPlatform', 'next');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
});
it('should not redirect to `docs` if deployment mode is `stable`', () => {
createTestingModule('', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('resources', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('guide/aot-compiler', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('tutorial', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('tutorial/toh-pt1', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('docs', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('api', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
createTestingModule('api/core/getPlatform', 'stable');
initializeTest(false);
expect(TestBed.get(LocationService).replace).not.toHaveBeenCalled();
locationService.replace.calls.reset();
testCurrentNodes.next({SideNav: {url: 'baz', view: 'SideNav', nodes: []}});
verifyNoRedirection();
});
});
});
});

View File

@ -110,7 +110,7 @@ export class AppComponent implements OnInit {
// Do not initialize the search on browsers that lack web worker support
if ('Worker' in window) {
// Delay initialization by up to 2 seconds
this.searchService.initWorker('app/search/search-worker.js', 2000);
this.searchService.initWorker(2000);
}
this.onResize(window.innerWidth);
@ -120,11 +120,6 @@ export class AppComponent implements OnInit {
this.documentService.currentDocument.subscribe(doc => this.currentDocument = doc);
this.locationService.currentPath.subscribe(path => {
// Redirect to docs if we are in archive mode and are not hitting a docs page
// (i.e. we have arrived at a marketing page)
if (this.deployment.mode === 'archive' && !/^(docs$|api|guide|tutorial)/.test(path)) {
this.locationService.replace('docs');
}
if (path === this.currentPath) {
// scroll only if on same page (most likely a change to the hash)
this.scrollService.scroll();
@ -138,7 +133,15 @@ export class AppComponent implements OnInit {
}
});
this.navigationService.currentNodes.subscribe(currentNodes => this.currentNodes = currentNodes);
this.navigationService.currentNodes.subscribe(currentNodes => {
this.currentNodes = currentNodes;
// Redirect to docs if we are in archive mode and are not hitting a docs page
// (i.e. we have arrived at a marketing page)
if (this.deployment.mode === 'archive' && !currentNodes[sideNavView]) {
this.locationService.replace('docs');
}
});
// Compute the version picker list from the current version and the versions in the navigation map
combineLatest(

View File

@ -206,7 +206,7 @@ export class DocViewerComponent implements OnDestroy {
// setting each style.
switchMap(() => raf$), tap(() => elem.style[prop] = from),
switchMap(() => raf$), tap(() => elem.style.transition = `all ${duration}ms ease-in-out`),
switchMap(() => raf$), tap(() => (elem.style as any)[prop] = to),
switchMap(() => raf$), tap(() => elem.style[prop] = to),
switchMap(() => timer(getActualDuration(elem))), switchMap(() => this.void$),
);
};

View File

@ -1,106 +0,0 @@
'use strict';
/* eslint-env worker */
/* global importScripts, lunr */
var SEARCH_TERMS_URL = '/generated/docs/app/search-data.json';
// NOTE: This needs to be kept in sync with `ngsw-config.json`.
importScripts('/generated/lunr.min.js');
var index;
var pages /* : SearchInfo */ = {};
// interface SearchInfo {
// [key: string]: PageInfo;
// }
// interface PageInfo {
// path: string;
// type: string,
// titleWords: string;
// keyWords: string;
// }
self.onmessage = handleMessage;
// Create the lunr index - the docs should be an array of objects, each object containing
// the path and search terms for a page
function createIndex(addFn) {
lunr.QueryLexer.termSeparator = lunr.tokenizer.separator = /\s+/;
return lunr(/** @this */function() {
this.ref('path');
this.field('titleWords', {boost: 10});
this.field('headingWords', {boost: 5});
this.field('members', {boost: 4});
this.field('keywords', {boost: 2});
addFn(this);
});
}
// The worker receives a message to load the index and to query the index
function handleMessage(message) {
var type = message.data.type;
var id = message.data.id;
var payload = message.data.payload;
switch(type) {
case 'load-index':
makeRequest(SEARCH_TERMS_URL, function(searchInfo) {
index = createIndex(loadIndex(searchInfo));
self.postMessage({type: type, id: id, payload: true});
});
break;
case 'query-index':
self.postMessage({type: type, id: id, payload: {query: payload, results: queryIndex(payload)}});
break;
default:
self.postMessage({type: type, id: id, payload: {error: 'invalid message type'}})
}
}
// Use XHR to make a request to the server
function makeRequest(url, callback) {
// The JSON file that is loaded should be an array of PageInfo:
var searchDataRequest = new XMLHttpRequest();
searchDataRequest.onload = function() {
callback(JSON.parse(this.responseText));
};
searchDataRequest.open('GET', url);
searchDataRequest.send();
}
// Create the search index from the searchInfo which contains the information about each page to be indexed
function loadIndex(searchInfo /*: SearchInfo */) {
return function(index) {
// Store the pages data to be used in mapping query results back to pages
// Add search terms from each page to the search index
searchInfo.forEach(function(page /*: PageInfo */) {
index.add(page);
pages[page.path] = page;
});
};
}
// Query the index and return the processed results
function queryIndex(query) {
try {
if (query.length) {
var results = index.search(query);
if (results.length === 0) {
// Add a relaxed search in the title for the first word in the query
// E.g. if the search is "ngCont guide" then we search for "ngCont guide titleWords:ngCont*"
var titleQuery = 'titleWords:*' + query.split(' ', 1)[0] + '*';
results = index.search(query + ' ' + titleQuery);
}
// Map the hits into info about each page to be returned as results
return results.map(function(hit) { return pages[hit.ref]; });
}
} catch(e) {
// If the search query cannot be parsed the index throws an error
// Log it and recover
console.log(e);
}
return [];
}

View File

@ -0,0 +1,104 @@
import { WebWorkerMessage } from '../shared/web-worker-message';
import * as lunr from 'lunr';
const SEARCH_TERMS_URL = '/generated/docs/app/search-data.json';
let index: lunr.Index;
const pages: SearchInfo = {};
interface SearchInfo {
[key: string]: PageInfo;
}
interface PageInfo {
path: string;
type: string;
titleWords: string;
keyWords: string;
}
addEventListener('message', handleMessage);
// Create the lunr index - the docs should be an array of objects, each object containing
// the path and search terms for a page
function createIndex(loadIndex: IndexLoader): lunr.Index {
// The lunr typings are missing QueryLexer so we have to add them here manually.
const queryLexer = (lunr as any as { QueryLexer: { termSeparator: RegExp } }).QueryLexer;
queryLexer.termSeparator = lunr.tokenizer.separator = /\s+/;
return lunr(/** @this */function () {
this.ref('path');
this.field('titleWords', { boost: 10 });
this.field('headingWords', { boost: 5 });
this.field('members', { boost: 4 });
this.field('keywords', { boost: 2 });
loadIndex(this);
});
}
// The worker receives a message to load the index and to query the index
function handleMessage(message: { data: WebWorkerMessage }): void {
const type = message.data.type;
const id = message.data.id;
const payload = message.data.payload;
switch (type) {
case 'load-index':
makeRequest(SEARCH_TERMS_URL, function (searchInfo: PageInfo[]) {
index = createIndex(loadIndex(searchInfo));
postMessage({ type: type, id: id, payload: true });
});
break;
case 'query-index':
postMessage({ type: type, id: id, payload: { query: payload, results: queryIndex(payload) } });
break;
default:
postMessage({ type: type, id: id, payload: { error: 'invalid message type' } })
}
}
// Use XHR to make a request to the server
function makeRequest(url: string, callback: (response: any) => void): void {
// The JSON file that is loaded should be an array of PageInfo:
const searchDataRequest = new XMLHttpRequest();
searchDataRequest.onload = function () {
callback(JSON.parse(this.responseText));
};
searchDataRequest.open('GET', url);
searchDataRequest.send();
}
// Create the search index from the searchInfo which contains the information about each page to be indexed
function loadIndex(pagesData: PageInfo[]): IndexLoader {
return (indexBuilder: lunr.Builder) => {
// Store the pages data to be used in mapping query results back to pages
// Add search terms from each page to the search index
pagesData.forEach(page => {
indexBuilder.add(page);
pages[page.path] = page;
});
};
}
// Query the index and return the processed results
function queryIndex(query: string): PageInfo[] {
try {
if (query.length) {
let results = index.search(query);
if (results.length === 0) {
// Add a relaxed search in the title for the first word in the query
// E.g. if the search is "ngCont guide" then we search for "ngCont guide titleWords:ngCont*"
const titleQuery = 'titleWords:*' + query.split(' ', 1)[0] + '*';
results = index.search(query + ' ' + titleQuery);
}
// Map the hits into info about each page to be returned as results
return results.map(function (hit) { return pages[hit.ref]; });
}
} catch (e) {
// If the search query cannot be parsed the index throws an error
// Log it and recover
console.log(e);
}
return [];
}
type IndexLoader = (indexBuilder: lunr.Builder) => void;

View File

@ -25,11 +25,11 @@ describe('SearchService', () => {
describe('initWorker', () => {
it('should create the worker and load the index after the specified delay', fakeAsync(() => {
service.initWorker('some/url', 100);
service.initWorker(100);
expect(WebWorkerClient.create).not.toHaveBeenCalled();
expect(mockWorker.sendMessage).not.toHaveBeenCalled();
tick(100);
expect(WebWorkerClient.create).toHaveBeenCalledWith('some/url', jasmine.any(NgZone));
expect(WebWorkerClient.create).toHaveBeenCalledWith(jasmine.any(Worker), jasmine.any(NgZone));
expect(mockWorker.sendMessage).toHaveBeenCalledWith('load-index');
}));
});
@ -37,7 +37,7 @@ describe('SearchService', () => {
describe('search', () => {
beforeEach(() => {
// We must initialize the service before calling connectSearches
service.initWorker('some/url', 1000);
service.initWorker(1000);
// Simulate the index being ready so that searches get sent to the worker
(service as any).ready = of(true);
});

View File

@ -16,10 +16,9 @@ export class SearchService {
* initial rendering of the web page. Triggering a search will override this delay and cause the index to be
* loaded immediately.
*
* @param workerUrl the url of the WebWorker script that runs the searches
* @param initDelay the number of milliseconds to wait before we load the WebWorker and generate the search index
*/
initWorker(workerUrl: string, initDelay: number) {
initWorker(initDelay: number) {
// Wait for the initDelay or the first search
const ready = this.ready = race<any>(
timer(initDelay),
@ -28,7 +27,8 @@ export class SearchService {
.pipe(
concatMap(() => {
// Create the worker and load the index
this.worker = WebWorkerClient.create(workerUrl, this.zone);
const worker = new Worker('./search-worker', { type: 'module' });
this.worker = WebWorkerClient.create(worker, this.zone);
return this.worker.sendMessage<boolean>('load-index');
}),
publishReplay(1),

View File

@ -0,0 +1,5 @@
export interface WebWorkerMessage {
type: string;
payload: any;
id?: number;
}

View File

@ -1,17 +1,12 @@
import {NgZone} from '@angular/core';
import {Observable} from 'rxjs';
export interface WebWorkerMessage {
type: string;
payload: any;
id?: number;
}
import {WebWorkerMessage} from './web-worker-message';
export class WebWorkerClient {
private nextId = 0;
static create(workerUrl: string, zone: NgZone) {
return new WebWorkerClient(new Worker(workerUrl), zone);
static create(worker: Worker, zone: NgZone) {
return new WebWorkerClient(worker, zone);
}
private constructor(private worker: Worker, private zone: NgZone) {

View File

@ -55,21 +55,22 @@ table {
td {
letter-spacing: 0.30px;
tr td:first-child {
@media (max-width: 480px) {
background-color: $lightgray;
tr td:first-child {
@media (max-width: 480px) {
background-color: $lightgray;
}
}
}
}
th {
background: rgba($lightgray, 0.2);
border-right: 1px solid $lightgray;
font-weight: 600;
max-width: 100px;
}
}
tbody > tr {
&:last-child td {
border: none;
@ -111,4 +112,4 @@ table {
}
}
}
}
}

View File

@ -1,19 +1,23 @@
{
"extends": "../tsconfig.json",
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"baseUrl": "",
"types": [],
"lib": [
"es2018",
"dom"
],
"importHelpers": true
},
"exclude": [
"testing/**/*",
"test.ts",
"test-specs.ts",
"**/*.spec.ts"
"**/*.spec.ts",
"**/*-worker.ts"
],
"angularCompilerOptions": {
"disableTypeScriptVersionCheck": true
}
}
}

11
aio/src/tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"module": "es2015",
"lib": [
"es2018",
"dom",
"webworker"
],
}
}

View File

@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/worker",
"lib": [
"es2018",
"webworker"
],
"types": [
"lunr"
],
},
"include": ["**/*-worker.ts"]
}

View File

@ -145,7 +145,7 @@
/docs/js/latest/api/upgrade/index/UpgradeAdapter-class.html /api/upgrade/UpgradeAdapter
/docs/js/latest/api/upgrade/static/UpgradeModule-class /api/upgrade/static/UpgradeModule
/docs/js/latest/api/upgrade/static/UpgradeModule-class.html /api/upgrade/static/UpgradeModule
/docs/js/latest/cookbook/ts-to-js.html https://github.com/angular/angular/blob/master/aio/content/guide/change-log.md#es6--described-in-typescript-to-javascript-2016-11-14
/docs/js/latest/cookbook/ts-to-js.html https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html
/docs/js/latest/glossary /guide/glossary
/docs/js/latest/guide/ /docs
/docs/js/latest/guide/lifecycle-hooks /guide/lifecycle-hooks
@ -170,7 +170,7 @@
/docs/ts/latest/api/http/testing/index/MockConnection-class.html /api/http/testing/MockConnection
/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://github.com/angular/angular/blob/master/aio/content/guide/change-log.md#es6--described-in-typescript-to-javascript-2016-11-14
/docs/ts/latest/cookbook/ts-to-js.html https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html
/guide/cli-quickstart /guide/quickstart
/guide/learning-angular /guide/quickstart
/guide/learning-angular.html /guide/quickstart

View File

@ -29,7 +29,7 @@ Currently you will find the next boilerplates:
* CLI - For CLI based examples. This is the default one, to be used in the majority of the examples.
* systemjs - Currently in deprecation, only used in a a few examples.
* systemjs - Currently in deprecation, only used in a few examples.
* i18n - Based on the CLI one, features a few scripts for i18n.
* universal - Based on the cli with a extra server for universal.

View File

@ -23,7 +23,7 @@
"@angular/router": "^7.0.0",
"angular-in-memory-web-api": "^0.6.0",
"core-js": "^2.5.4",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
},

View File

@ -26,7 +26,7 @@
"@angular/router": "^7.0.0",
"angular-in-memory-web-api": "^0.6.0",
"core-js": "^2.5.4",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
},

View File

@ -24,7 +24,7 @@
"@angular/service-worker": "^7.0.0",
"angular-in-memory-web-api": "^0.6.0",
"core-js": "^2.5.4",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
},

View File

@ -30,7 +30,7 @@
"@nguniversal/module-map-ngfactory-loader": "^7.0.0",
"angular-in-memory-web-api": "^0.6.0",
"core-js": "^2.5.4",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
},

View File

@ -36,7 +36,7 @@
"angular-in-memory-web-api": "github:brandonroberts/in-memory-web-api-bazel#50a34d8",
"core-js": "^2.5.4",
"express": "^4.14.1",
"rxjs": "^6.3.0",
"rxjs": "^6.5.1",
"systemjs": "0.19.39",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"

View File

@ -6663,7 +6663,7 @@ rx@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
rxjs@6.3.3, rxjs@^6.3.0:
rxjs@6.3.3:
version "6.3.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55"
dependencies:
@ -6675,6 +6675,13 @@ rxjs@^6.1.0:
dependencies:
tslib "^1.9.0"
rxjs@^6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.1.tgz#f7a005a9386361921b8524f38f54cbf80e5d08f4"
integrity sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==
dependencies:
tslib "^1.9.0"
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"

View File

@ -1,7 +1,7 @@
module.exports = function filterHiddenCommands() {
return {
$runAfter: ['files-read'],
$runBefore: ['processCliContainerDoc'],
$runBefore: ['processCliContainerDoc', 'createSitemap'],
$process(docs) {
return docs.filter(doc => doc.docType !== 'cli-command' || doc.hidden !== true);
}

View File

@ -18,7 +18,7 @@ describe('filterHiddenCommands processor', () => {
it('should run before the correct processor', () => {
const processor = processorFactory();
expect(processor.$runBefore).toEqual(['processCliContainerDoc']);
expect(processor.$runBefore).toEqual(['processCliContainerDoc', 'createSitemap']);
});
it('should remove CLI command docs that are hidden', () => {

File diff suppressed because it is too large Load Diff

View File

@ -1,141 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"demo": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/demo",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demo:build"
},
"configurations": {
"production": {
"browserTarget": "demo:build:production"
},
"ci": {
"progress": false
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "demo:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"demo-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "demo:serve"
},
"configurations": {
"production": {
"devServerTarget": "demo:serve:production"
},
"ci": {
"devServerTarget": "demo:serve:ci"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "demo"
}

View File

@ -1,14 +0,0 @@
{
"name": "bazel-schematics",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@angular/bazel": "file:../../dist/packages-dist/bazel",
"@angular/cli": "file:../../node_modules/@angular/cli",
"@bazel/bazel": "file:../../node_modules/@bazel/bazel"
},
"scripts": {
"test": "./test.sh"
}
}

View File

@ -1,47 +0,0 @@
#!/usr/bin/env bash
set -eux -o pipefail
function installLocalPackages() {
# Install Angular packages that are built locally from HEAD.
# This also gets around the bug whereby yarn caches local `file://` urls.
# See https://github.com/yarnpkg/yarn/issues/2165
readonly pwd=$(pwd)
readonly packages=(
animations common compiler core forms platform-browser
platform-browser-dynamic router bazel compiler-cli language-service upgrade
)
local local_packages=()
for package in "${packages[@]}"; do
local_packages+=("@angular/${package}@file:${pwd}/../../../dist/packages-dist/${package}")
done
yarn add "${local_packages[@]}"
}
function testBazel() {
# Set up
bazel version
ng version
rm -rf demo
# Create project
ng new demo --collection=@angular/bazel --defaults --skip-git --skip-install --style=scss
cd demo
installLocalPackages
yarn webdriver-manager update --gecko=false --standalone=false ${CI_CHROMEDRIVER_VERSION_ARG:---versions.chrome 2.45}
ng generate component widget --style=css
ng build
ng test
ng e2e
}
function testNonBazel() {
# Replace angular.json that uses Bazel builder with the default generated by CLI
cp ../angular.json.original ./angular.json
rm -rf dist src/main.dev.ts src/main.prod.ts
ng build --progress=false
ng test --progress=false --watch=false
ng e2e --configuration=ci --webdriver-update=false
}
testBazel
testNonBazel

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@ const integrationTests = fs.readdirSync(__dirname).filter(
const manualTestShards = [
// The first shard should only run the bazel integration tests because these take up
// a lot of time and shouldn't be split up automatically.
['bazel', 'bazel-schematics']
['bazel']
];
// Tests which haven't been assigned manually to a shard. These tests will be automatically

View File

@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "7.2.13",
"version": "7.2.16",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps",
@ -71,6 +71,7 @@
"domino": "2.1.0",
"fs-extra": "4.0.2",
"hammerjs": "2.0.8",
"is-builtin-module": "3.0.0",
"incremental-dom": "0.4.1",
"jasmine": "^3.1.0",
"jasmine-core": "^3.1.0",
@ -96,7 +97,7 @@
"tslib": "^1.9.0",
"typescript": "~3.2.2",
"xhr2": "0.1.4",
"yargs": "9.0.1",
"yargs": "13.1.0",
"zone.js": "^0.8.26"
},
"optionalDependencies": {
@ -135,7 +136,7 @@
"karma-browserstack-launcher": "^1.3.0",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^1.1.2",
"karma-sauce-launcher": "^2.0.2",
"karma-sauce-launcher": "2.0.1",
"karma-sourcemap-loader": "^0.3.7",
"madge": "0.5.0",
"mutation-observer": "^1.0.3",

View File

@ -1200,8 +1200,8 @@ export function useAnimation(
* query('.content', style({ opacity: 0 })),
*
* // animate the inner elements in, one by one
* query('h1', animate(1000, style({ opacity: 1 })),
* query('.content', animate(1000, style({ opacity: 1 })),
* query('h1', animate(1000, style({ opacity: 1 }))),
* query('.content', animate(1000, style({ opacity: 1 }))),
* ])
* ])
* ]

View File

@ -83,7 +83,7 @@ export interface HttpParamsOptions {
*/
fromString?: string;
/** Object map of the HTTP params. Mutally exclusive with `fromString`. */
/** Object map of the HTTP params. Mutually exclusive with `fromString`. */
fromObject?: {[param: string]: string | string[]};
/** Encoding codec used to parse and serialize the params. */
@ -227,7 +227,7 @@ export class HttpParams {
}
}
});
this.cloneFrom = null;
this.cloneFrom = this.updates = null;
}
}
}

View File

@ -53,6 +53,15 @@ import {HttpParams} from '@angular/common/http/src/params';
const mutated = body.delete('a', '2').delete('a', '4');
expect(mutated.getAll('a')).toEqual(['1', '3', '5']);
});
it('should not repeat mutations that have already been materialized', () => {
const body = new HttpParams({fromString: 'a=b'});
const mutated = body.append('a', 'c');
expect(mutated.toString()).toEqual('a=b&a=c');
const mutated2 = mutated.append('c', 'd');
expect(mutated.toString()).toEqual('a=b&a=c');
expect(mutated2.toString()).toEqual('a=b&a=c&c=d');
});
});
describe('read operations', () => {

View File

@ -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",

View File

@ -264,7 +264,7 @@ export type CanDeactivateFn<T> =
/**
* @description
*
* Interface that class can implement to be a data provider.
* Interface that classes can implement to be a data provider.
*
* ```
* class Backend {

View File

@ -143,18 +143,32 @@ export class RouterModule {
* Creates a module with all the router providers and directives. It also optionally sets up an
* application listener to perform an initial navigation.
*
* Options (see `ExtraOptions`):
* * `enableTracing` makes the router log all its internal events to the console.
* * `useHash` enables the location strategy that uses the URL fragment instead of the history
* Configuration Options:
*
* * `enableTracing` Toggles whether the router should log all navigation events to the console.
* * `useHash` Enables the location strategy that uses the URL fragment instead of the history
* API.
* * `initialNavigation` disables the initial navigation.
* * `errorHandler` provides a custom error handler.
* * `preloadingStrategy` configures a preloading strategy (see `PreloadAllModules`).
* * `onSameUrlNavigation` configures how the router handles navigation to the current URL. See
* `ExtraOptions` for more details.
* * `paramsInheritanceStrategy` defines how the router merges params, data and resolved data
* from parent to child routes.
*/
* * `initialNavigation` Disables the initial navigation.
* * `errorHandler` Defines a custom error handler for failed navigations.
* * `preloadingStrategy` Configures a preloading strategy. See `PreloadAllModules`.
* * `onSameUrlNavigation` Define what the router should do if it receives a navigation request to
* the current URL.
* * `scrollPositionRestoration` Configures if the scroll position needs to be restored when
* navigating back.
* * `anchorScrolling` Configures if the router should scroll to the element when the url has a
* fragment.
* * `scrollOffset` Configures the scroll offset the router will use when scrolling to an element.
* * `paramsInheritanceStrategy` Defines how the router merges params, data and resolved data from
* parent to child routes.
* * `malformedUriErrorHandler` Defines a custom malformed uri error handler function. This
* handler is invoked when encodedURI contains invalid character sequences.
* * `urlUpdateStrategy` Defines when the router updates the browser URL. The default behavior is
* to update after successful navigation.
* * `relativeLinkResolution` Enables the correct relative link resolution in components with
* empty paths.
*
* See `ExtraOptions` for more details about the above options.
*/
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders<RouterModule> {
return {
ngModule: RouterModule,

View File

@ -296,7 +296,9 @@ export function getAngularJSGlobal(): any {
export const bootstrap: typeof angular.bootstrap = (e, modules, config?) =>
angular.bootstrap(e, modules, config);
export const module: typeof angular.module = (prefix, dependencies?) =>
// Do not declare as `module` to avoid webpack bug
// (see https://github.com/angular/angular/issues/30050).
export const module_: typeof angular.module = (prefix, dependencies?) =>
angular.module(prefix, dependencies);
export const element: typeof angular.element = (e => angular.element(e)) as typeof angular.element;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, CompilerOptions, Injector, NgModule, NgModuleRef, NgZone, StaticProvider, Testability, Type, resolveForwardRef} from '@angular/core';
import {Compiler, CompilerOptions, Injector, NgModule, NgModuleRef, NgZone, StaticProvider, Testability, Type, isDevMode, resolveForwardRef} from '@angular/core';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import * as angular from '../../common/src/angular1';
@ -501,7 +501,7 @@ export class UpgradeAdapter {
let rootScopePrototype: any;
let rootScope: angular.IRootScopeService;
const upgradeAdapter = this;
const ng1Module = this.ng1Module = angular.module(this.idPrefix, modules);
const ng1Module = this.ng1Module = angular.module_(this.idPrefix, modules);
const platformRef = platformBrowserDynamic();
this.ngZone = new NgZone({enableLongStackTrace: Zone.hasOwnProperty('longStackTraceZoneSpec')});
@ -598,8 +598,20 @@ export class UpgradeAdapter {
})
.then(() => this.ng2BootstrapDeferred.resolve(ng1Injector), onError)
.then(() => {
let subscription =
this.ngZone.onMicrotaskEmpty.subscribe({next: () => rootScope.$digest()});
let subscription = this.ngZone.onMicrotaskEmpty.subscribe({
next: () => {
if (rootScope.$$phase) {
if (isDevMode()) {
console.warn(
'A digest was triggered while one was already in progress. This may mean that something is triggering digests outside the Angular zone.');
}
return rootScope.$evalAsync(() => {});
}
return rootScope.$digest();
}
});
rootScope.$on('$destroy', () => { subscription.unsubscribe(); });
});
})

View File

@ -34,7 +34,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should instantiate ng2 in ng1 template and project content', async(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component({
selector: 'ng2',
@ -60,7 +60,7 @@ withEachNg1Version(() => {
it('should instantiate ng1 in ng2 template and project content', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component({
selector: 'ng2',
@ -94,7 +94,7 @@ withEachNg1Version(() => {
spyOn(platformRef, 'bootstrapModule').and.callThrough();
spyOn(platformRef, 'bootstrapModuleFactory').and.callThrough();
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component({selector: 'ng2', template: `{{ 'NG2' }}(<ng-content></ng-content>)`})
class Ng2 {
}
@ -128,7 +128,7 @@ withEachNg1Version(() => {
let adapter: UpgradeAdapter;
beforeEach(() => {
angular.module('ng1', []);
angular.module_('ng1', []);
@Component({
selector: 'ng2',
@ -171,10 +171,49 @@ withEachNg1Version(() => {
}));
});
describe('scope/component change-detection', () => {
describe('change-detection', () => {
it('should not break if a $digest is already in progress', async(() => {
@Component({selector: 'my-app', template: ''})
class AppComponent {
}
@NgModule({declarations: [AppComponent], imports: [BrowserModule]})
class Ng2Module {
}
const ng1Module = angular.module_('ng1', []);
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const element = html('<my-app></my-app>');
adapter.bootstrap(element, [ng1Module.name]).ready((ref) => {
const $rootScope: any = ref.ng1RootScope;
const ngZone: NgZone = ref.ng2ModuleRef.injector.get<NgZone>(NgZone);
const digestSpy = spyOn($rootScope, '$digest').and.callThrough();
// Step 1: Ensure `$digest` is run on `onMicrotaskEmpty`.
ngZone.onMicrotaskEmpty.emit(null);
expect(digestSpy).toHaveBeenCalledTimes(1);
digestSpy.calls.reset();
// Step 2: Cause the issue.
$rootScope.$apply(() => ngZone.onMicrotaskEmpty.emit(null));
// With the fix, `$digest` will only be run once (for `$apply()`).
// Without the fix, `$digest()` would have been run an extra time (`onMicrotaskEmpty`).
expect(digestSpy).toHaveBeenCalledTimes(1);
digestSpy.calls.reset();
// Step 3: Ensure that `$digest()` is still executed on `onMicrotaskEmpty`.
ngZone.onMicrotaskEmpty.emit(null);
expect(digestSpy).toHaveBeenCalledTimes(1);
});
}));
it('should interleave scope and component expressions', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const log: string[] = [];
const l = (value: string) => {
log.push(value);
@ -217,7 +256,6 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-712: Rendering is being run on next "animation frame" rather than "Zone.microTaskEmpty" trigger')
.it('should propagate changes to a downgraded component inside the ngZone', async(() => {
@ -265,7 +303,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'myApp', adapter.downgradeNg2Component(AppComponent));
const element = html('<my-app></my-app>');
@ -288,7 +326,7 @@ withEachNg1Version(() => {
// }
// const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
// const ng1Module = angular.module('ng1', []).directive(
// const ng1Module = angular.module_('ng1', []).directive(
// 'myApp', adapter.downgradeNg2Component(AppComponent));
// const element = html('<my-app></my-app>');
@ -319,7 +357,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.directive('ng2', adapter.downgradeNg2Component(WorksComponent));
const element = html('<ng2></ng2>');
@ -331,7 +369,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-715: ngOnChanges being called a second time unexpectedly')
.it('should bind properties, events', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []).value(
const ng1Module = angular.module_('ng1', []).value(
$EXCEPTION_HANDLER, (err: any) => { throw err; });
ng1Module.run(($rootScope: any) => {
@ -456,7 +494,7 @@ withEachNg1Version(() => {
.it('should support two-way binding and event listener', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const listenerSpy = jasmine.createSpy('$rootScope.listener');
const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['value'] = 'world';
$rootScope['listener'] = listenerSpy;
});
@ -538,7 +576,7 @@ withEachNg1Version(() => {
class Ng2Module {
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'ng2', adapter.downgradeNg2Component(Ng2Component));
const element = html(`
@ -564,7 +602,7 @@ withEachNg1Version(() => {
it('should bind to ng-model', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.run(($rootScope: any /** TODO #9100 */) => { $rootScope.modelA = 'A'; });
@ -622,7 +660,7 @@ withEachNg1Version(() => {
it('should properly run cleanup when ng1 directive is destroyed', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const onDestroyed: EventEmitter<string> = new EventEmitter<string>();
ng1Module.directive('ng1', () => {
@ -678,7 +716,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1', () => ({template: '<ng2-inner></ng2-inner>'}))
.directive('ng2Inner', adapter.downgradeNg2Component(Ng2InnerComponent))
.directive('ng2Outer', adapter.downgradeNg2Component(Ng2OuterComponent));
@ -698,7 +736,7 @@ withEachNg1Version(() => {
it('should fallback to the root ng2.injector when compiled outside the dom', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.directive('ng1', [
'$compile',
@ -734,7 +772,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should support multi-slot projection', async(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component({
selector: 'ng2',
@ -777,7 +815,7 @@ withEachNg1Version(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module);
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng2', adapter.downgradeNg2Component(Ng2Component))
.run(($rootScope: angular.IRootScopeService) => {
$rootScope['items'] = [
@ -801,7 +839,7 @@ withEachNg1Version(() => {
it('should allow attribute selectors for components in ng2', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => MyNg2Module));
const ng1Module = angular.module('myExample', []);
const ng1Module = angular.module_('myExample', []);
@Component({selector: '[works]', template: 'works!'})
class WorksComponent {
@ -852,7 +890,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -916,7 +954,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -980,7 +1018,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -1041,7 +1079,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -1074,7 +1112,7 @@ withEachNg1Version(() => {
it('should bind properties, events', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1132,7 +1170,7 @@ withEachNg1Version(() => {
it('should bind optional properties', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1177,7 +1215,7 @@ withEachNg1Version(() => {
it('should bind properties, events in controller when bindToController is not used',
async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1221,7 +1259,7 @@ withEachNg1Version(() => {
it('should bind properties, events in link function', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1265,7 +1303,7 @@ withEachNg1Version(() => {
it('should support templateUrl fetched from $httpBackend', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.value(
'$httpBackend', (method: string, url: string, post: any, cbFn: Function) => {
cbFn(200, `${method}:${url}`);
@ -1294,7 +1332,7 @@ withEachNg1Version(() => {
it('should support templateUrl as a function', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.value(
'$httpBackend', (method: string, url: string, post: any, cbFn: Function) => {
cbFn(200, `${method}:${url}`);
@ -1323,7 +1361,7 @@ withEachNg1Version(() => {
it('should support empty template', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => { return {template: ''}; };
ng1Module.directive('ng1', ng1);
@ -1349,7 +1387,7 @@ withEachNg1Version(() => {
it('should support template as a function', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => { return {template() { return ''; }}; };
ng1Module.directive('ng1', ng1);
@ -1375,7 +1413,7 @@ withEachNg1Version(() => {
it('should support templateUrl fetched from $templateCache', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
ng1Module.run(($templateCache: any) => $templateCache.put('url.html', 'WORKS'));
const ng1 = () => { return {templateUrl: 'url.html'}; };
@ -1402,7 +1440,7 @@ withEachNg1Version(() => {
it('should support controller with controllerAs', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1446,7 +1484,7 @@ withEachNg1Version(() => {
it('should support bindToController', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1480,7 +1518,7 @@ withEachNg1Version(() => {
it('should support bindToController with bindings', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = () => {
return {
@ -1514,7 +1552,7 @@ withEachNg1Version(() => {
it('should support single require in linking fn', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = ($rootScope: any) => {
return {
@ -1555,7 +1593,7 @@ withEachNg1Version(() => {
it('should support array require in linking fn', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const parent = () => { return {controller: class {parent = 'PARENT';}}; };
const ng1 = () => {
@ -1607,7 +1645,7 @@ withEachNg1Version(() => {
class Ng2Component {
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1651,7 +1689,7 @@ withEachNg1Version(() => {
class Ng2Component {
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1700,7 +1738,7 @@ withEachNg1Version(() => {
constructor(cd: ChangeDetectorRef) { changeDetector = cd; }
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1754,7 +1792,7 @@ withEachNg1Version(() => {
constructor(cd: ChangeDetectorRef) { changeDetector = cd; }
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1807,7 +1845,7 @@ withEachNg1Version(() => {
class Ng2Component {
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1851,7 +1889,7 @@ withEachNg1Version(() => {
class Ng2Component {
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -1904,7 +1942,7 @@ withEachNg1Version(() => {
constructor() { ng2Instance = this; }
}
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1A', () => ({
template: '',
scope: {valA: '<'},
@ -2007,7 +2045,7 @@ withEachNg1Version(() => {
// on
// the queue at the end of the test, causing it to fail.
// Mocking animations (via `ngAnimateMock`) avoids the issue.
angular.module('ng1', ['ngAnimateMock'])
angular.module_('ng1', ['ngAnimateMock'])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -2096,7 +2134,7 @@ withEachNg1Version(() => {
// on
// the queue at the end of the test, causing it to fail.
// Mocking animations (via `ngAnimateMock`) avoids the issue.
angular.module('ng1', ['ngAnimateMock'])
angular.module_('ng1', ['ngAnimateMock'])
.directive('ng1A', () => ({
template: '',
scope: {},
@ -2171,7 +2209,7 @@ withEachNg1Version(() => {
// on
// the queue at the end of the test, causing it to fail.
// Mocking animations (via `ngAnimateMock`) avoids the issue.
angular.module('ng1', ['ngAnimateMock'])
angular.module_('ng1', ['ngAnimateMock'])
.component('ng1', {
controller: function($scope: angular.IScope) {
$scope.$on('$destroy', scopeDestroyListener);
@ -2217,7 +2255,7 @@ withEachNg1Version(() => {
// on
// the queue at the end of the test, causing it to fail.
// Mocking animations (via `ngAnimateMock`) avoids the issue.
angular.module('ng1', ['ngAnimateMock'])
angular.module_('ng1', ['ngAnimateMock'])
.component('ng1', {
controller: class {
constructor(private $element: angular.IAugmentedJQuery) {} $onInit() {
@ -2285,7 +2323,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', adapter.downgradeNg2Component(Ng2ComponentA));
@ -2351,7 +2389,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', adapter.downgradeNg2Component(Ng2ComponentA));
@ -2405,7 +2443,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2443,7 +2481,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2483,7 +2521,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2523,7 +2561,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2562,7 +2600,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2615,7 +2653,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', adapter.downgradeNg2Component(Ng2ComponentA));
@ -2680,7 +2718,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2739,7 +2777,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2813,7 +2851,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2879,7 +2917,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2929,7 +2967,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.value($EXCEPTION_HANDLER, (error: Error) => errorMessage = error.message)
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2985,7 +3023,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -3024,7 +3062,7 @@ withEachNg1Version(() => {
it('should bind input properties (<) of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = {
bindings: {personProfile: '<'},
@ -3056,7 +3094,7 @@ withEachNg1Version(() => {
it('should support ng2 > ng1 > ng2', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const ng1 = {
template: 'ng1(<ng2b></ng2b>)',
@ -3099,7 +3137,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module);
const module = angular.module('myExample', []);
const module = angular.module_('myExample', []);
module.factory('someToken', adapter.downgradeNg2Provider(SomeToken));
adapter.bootstrap(html('<div>'), ['myExample']).ready((ref) => {
expect(ref.ng1Injector.get('someToken')).toBe('correct_value');
@ -3113,7 +3151,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module);
const module = angular.module('myExample', []);
const module = angular.module_('myExample', []);
module.value('testValue', 'secreteToken');
adapter.upgradeNg1Provider('testValue');
adapter.upgradeNg1Provider('testValue', {asToken: 'testToken'});
@ -3128,7 +3166,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should respect hierarchical dependency injection for ng2', async(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component(
{selector: 'ng2-parent', template: `ng2-parent(<ng-content></ng-content>)`})
@ -3162,7 +3200,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module);
angular.module('ng1', []);
angular.module_('ng1', []);
let bootstrapResumed: boolean = false;
const element = html('<div></div>');
@ -3185,7 +3223,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module);
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
let a1Injector: angular.IInjectorService|undefined;
ng1Module.run([
'$injector', function($injector: angular.IInjectorService) { a1Injector = $injector; }
@ -3208,7 +3246,7 @@ withEachNg1Version(() => {
}
const adapter: UpgradeAdapter = new UpgradeAdapter(MyNg2Module);
angular.module('ng1', []);
angular.module_('ng1', []);
const element = html('<div></div>');
adapter.bootstrap(element, ['ng1']).ready((ref) => {
const ng2Testability: Testability = ref.ng2Injector.get(Testability);
@ -3232,7 +3270,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should verify UpgradeAdapter example', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const module = angular.module('myExample', []);
const module = angular.module_('myExample', []);
const ng1 = () => {
return {
@ -3276,7 +3314,7 @@ withEachNg1Version(() => {
let $rootScope: angular.IRootScopeService;
beforeEach(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
@Component({
selector: 'ng2',
@ -3321,4 +3359,4 @@ function $apply(adapter: UpgradeAdapterRef, exp: angular.Ng1Expression) {
function $digest(adapter: UpgradeAdapterRef) {
const $rootScope = adapter.ng1Injector.get($ROOT_SCOPE) as angular.IRootScopeService;
$rootScope.$digest();
}
}

View File

@ -143,7 +143,7 @@ export function downgradeModule<T>(
let injector: Injector;
// Create an ng1 module to bootstrap.
angular.module(lazyModuleName, [])
angular.module_(lazyModuleName, [])
.constant(UPGRADE_APP_TYPE_KEY, UpgradeAppType.Lite)
.factory(INJECTOR_KEY, [lazyInjectorKey, identity])
.factory(

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, NgModule, NgZone, Testability} from '@angular/core';
import {Injector, NgModule, NgZone, Testability, isDevMode} from '@angular/core';
import * as angular from '../../src/common/src/angular1';
import {$$TESTABILITY, $DELEGATE, $INJECTOR, $INTERVAL, $PROVIDE, INJECTOR_KEY, LAZY_MODULE_REF, UPGRADE_APP_TYPE_KEY, UPGRADE_MODULE_NAME} from '../../src/common/src/constants';
@ -171,7 +171,7 @@ export class UpgradeModule {
// Create an ng1 module to bootstrap
const initModule =
angular
.module(INIT_MODULE_NAME, [])
.module_(INIT_MODULE_NAME, [])
.constant(UPGRADE_APP_TYPE_KEY, UpgradeAppType.Static)
@ -255,14 +255,24 @@ export class UpgradeModule {
// stabilizing
setTimeout(() => {
const $rootScope = $injector.get('$rootScope');
const subscription =
this.ngZone.onMicrotaskEmpty.subscribe(() => $rootScope.$digest());
const subscription = this.ngZone.onMicrotaskEmpty.subscribe(() => {
if ($rootScope.$$phase) {
if (isDevMode()) {
console.warn(
'A digest was triggered while one was already in progress. This may mean that something is triggering digests outside the Angular zone.');
}
return $rootScope.$evalAsync();
}
return $rootScope.$digest();
});
$rootScope.$on('$destroy', () => { subscription.unsubscribe(); });
}, 0);
}
]);
const upgradeModule = angular.module(UPGRADE_MODULE_NAME, [INIT_MODULE_NAME].concat(modules));
const upgradeModule = angular.module_(UPGRADE_MODULE_NAME, [INIT_MODULE_NAME].concat(modules));
// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
const windowAngular = (window as any)['angular'];

View File

@ -19,10 +19,65 @@ import {html, withEachNg1Version} from '../../../src/common/test/helpers/common_
import {bootstrap} from './static_test_helpers';
withEachNg1Version(() => {
describe('scope/component change-detection', () => {
describe('change-detection', () => {
beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform());
it('should not break if a $digest is already in progress', async(() => {
const element = html('<my-app></my-app>');
@Component({selector: 'my-app', template: ''})
class AppComponent {
}
@NgModule({
declarations: [AppComponent],
entryComponents: [AppComponent],
imports: [BrowserModule, UpgradeModule]
})
class Ng2Module {
ngDoBootstrap() {}
}
const ng1Module = angular.module_('ng1', []).directive(
'myApp', downgradeComponent({component: AppComponent}));
bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => {
const $rootScope = upgrade.$injector.get('$rootScope') as angular.IRootScopeService;
const ngZone: NgZone = upgrade.ngZone;
// Wrap in a setTimeout to ensure all boostrap operations have completed.
setTimeout(
// Run inside the Angular zone, so that operations such as emitting
// `onMicrotaskEmpty` do not trigger entering/existing the zone (and thus another
// `$digest`). This also closer simulates what would happen in a real app.
() => ngZone.run(() => {
const digestSpy = spyOn($rootScope, '$digest').and.callThrough();
// Step 1: Ensure `$digest` is run on `onMicrotaskEmpty`.
ngZone.onMicrotaskEmpty.emit(null);
expect(digestSpy).toHaveBeenCalledTimes(1);
digestSpy.calls.reset();
// Step 2: Cause the issue.
$rootScope.$apply(() => ngZone.onMicrotaskEmpty.emit(null));
// With the fix, `$digest` will only be run once (for `$apply()`).
// Without the fix, `$digest()` would have been run an extra time
// (`onMicrotaskEmpty`).
expect(digestSpy).toHaveBeenCalledTimes(1);
digestSpy.calls.reset();
// Step 3: Ensure that `$digest()` is still executed on `onMicrotaskEmpty`.
ngZone.onMicrotaskEmpty.emit(null);
expect(digestSpy).toHaveBeenCalledTimes(1);
}),
0);
});
}));
it('should interleave scope and component expressions', async(() => {
const log: string[] = [];
const l = (value: string) => {
@ -61,7 +116,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1a', () => ({template: '{{ l(\'ng1a\') }}'}))
.directive('ng1b', () => ({template: '{{ l(\'ng1b\') }}'}))
.directive('ng2', downgradeComponent({component: Ng2Component}))
@ -125,7 +180,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'myApp', downgradeComponent({component: AppComponent}));
bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => {
@ -145,7 +200,7 @@ withEachNg1Version(() => {
// }
// const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
// const ng1Module = angular.module('ng1', []).directive(
// const ng1Module = angular.module_('ng1', []).directive(
// 'myApp', adapter.downgradeNg2Component(AppComponent));
// const element = html('<my-app></my-app>');

View File

@ -45,7 +45,7 @@ withEachNg1Version(() => {
// the ng1 app module that will consume the downgraded component
const ng1Module = angular
.module('ng1', [])
.module_('ng1', [])
// create an ng1 facade of the ng2 component
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(($rootScope: angular.IRootScopeService) => {
@ -79,7 +79,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(($rootScope: angular.IRootScopeService) => {
$rootScope['items'] = [
@ -128,7 +128,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1', () => ({
transclude: true,
template: '{{ prop }}(<ng-transclude></ng-transclude>)'
@ -167,7 +167,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'ng2', downgradeComponent({component: Ng2Component}));
// The ng-if on one of the projected children is here to make sure

View File

@ -25,7 +25,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-715: ngOnChanges being called a second time unexpectedly')
.it('should bind properties, events', async(() => {
const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['name'] = 'world';
$rootScope['dataA'] = 'A';
$rootScope['dataB'] = 'B';
@ -150,7 +150,7 @@ withEachNg1Version(() => {
}));
it('should bind properties to onpush components', async(() => {
const ng1Module = angular.module('ng1', []).run(
const ng1Module = angular.module_('ng1', []).run(
($rootScope: angular.IScope) => { $rootScope['dataB'] = 'B'; });
@Component({
@ -193,7 +193,7 @@ withEachNg1Version(() => {
fixmeIvy('FW-715: ngOnChanges being called a second time unexpectedly')
.it('should support two-way binding and event listener', async(() => {
const listenerSpy = jasmine.createSpy('$rootScope.listener');
const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['value'] = 'world';
$rootScope['listener'] = listenerSpy;
});
@ -263,7 +263,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(($rootScope: angular.IRootScopeService) => {
$rootScope.value1 = 0;
@ -327,7 +327,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest: false}))
.run(($rootScope: angular.IRootScopeService) => {
@ -389,7 +389,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive(
'ng2A', downgradeComponent({component: Ng2Component, propagateDigest: true}))
.directive(
@ -444,7 +444,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'ng2', downgradeComponent({component: Ng2Component}));
const element = html(`
@ -467,7 +467,7 @@ withEachNg1Version(() => {
}));
it('should bind to ng-model', async(() => {
const ng1Module = angular.module('ng1', []).run(
const ng1Module = angular.module_('ng1', []).run(
($rootScope: angular.IScope) => { $rootScope['modelA'] = 'A'; });
let ng2Instance: Ng2;
@ -539,7 +539,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive(
'ng1',
() => { return {template: '<div ng-if="!destroyIt"><ng2></ng2></div>'}; })
@ -592,7 +592,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('ng1', () => ({template: '<ng2-inner></ng2-inner>'}))
.directive('ng2Inner', downgradeComponent({component: Ng2InnerComponent}))
.directive('ng2Outer', downgradeComponent({component: Ng2OuterComponent}));
@ -627,7 +627,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive(
'ng1',
[
@ -672,7 +672,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'worksComponent', downgradeComponent({component: WorksComponent}));
const element = html('<works-component></works-component>');
@ -700,7 +700,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'rootComponent', downgradeComponent({component: RootComponent}));
const element = html('<root-component></root-component>');
@ -731,7 +731,7 @@ withEachNg1Version(() => {
}
const ng1Module =
angular.module('ng1', [])
angular.module_('ng1', [])
.directive('parent', downgradeComponent({component: ParentComponent}))
.directive('child', downgradeComponent({component: ChildComponent}));
@ -773,7 +773,7 @@ withEachNg1Version(() => {
class LazyLoadedModule {
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'ng2', downgradeComponent({component: Ng2Component}));
const element = html('<ng2></ng2>');
@ -808,7 +808,7 @@ withEachNg1Version(() => {
}
const ng1Module = angular.module('ng1', []).directive(
const ng1Module = angular.module_('ng1', []).directive(
'ng2', downgradeComponent({component: Ng2Component, downgradedModule: 'foo'}));
const element = html('<ng2></ng2>');

View File

@ -63,7 +63,7 @@ withEachNg1Version(() => {
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB])
const ng1Module = angular.module_('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest,
@ -131,7 +131,7 @@ withEachNg1Version(() => {
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module =
angular.module('ng1', [downModA, downModB])
angular.module_('ng1', [downModA, downModB])
.directive('ng1A', () => ({template: 'ng1A(<ng2-b ng-if="showB"></ng2-b>)'}))
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
@ -205,7 +205,7 @@ withEachNg1Version(() => {
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB])
const ng1Module = angular.module_('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest,
@ -299,7 +299,7 @@ withEachNg1Version(() => {
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB])
const ng1Module = angular.module_('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest,
@ -391,7 +391,7 @@ withEachNg1Version(() => {
const downMod = downgradeModule(bootstrapFn);
const ng1Module =
angular.module('ng1', [downMod])
angular.module_('ng1', [downMod])
.directive(
'ng2A', downgradeComponent({component: Ng2ComponentA, propagateDigest}))
.directive(
@ -501,7 +501,7 @@ withEachNg1Version(() => {
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB])
const ng1Module = angular.module_('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest,
@ -568,7 +568,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2AComponent, propagateDigest}))
.run(($rootScope: angular.IRootScopeService) => $rootScope.value = 0);
@ -631,7 +631,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}))
.value('ng1Value', 'foo');
@ -676,7 +676,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -711,7 +711,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -752,7 +752,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}))
.run(($rootScope: angular.IRootScopeService) => {
@ -822,7 +822,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'test', downgradeComponent({component: TestComponent, propagateDigest}))
.directive(
@ -871,7 +871,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -924,7 +924,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'test', downgradeComponent({component: TestComponent, propagateDigest}))
.directive(
@ -996,7 +996,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}))
.run(($rootScope: angular.IRootScopeService) => {
@ -1140,7 +1140,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -1197,7 +1197,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -1252,7 +1252,7 @@ withEachNg1Version(() => {
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
angular.module_('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
@ -1317,7 +1317,7 @@ withEachNg1Version(() => {
afterEach(() => setTempInjectorRef(null !));
it('should throw if no downgraded module is included', async(() => {
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({
component: Ng2CompA,
@ -1349,7 +1349,7 @@ withEachNg1Version(() => {
}));
it('should throw if the corresponding downgraded module is not included', async(() => {
const ng1Module = angular.module('ng1', [downModA])
const ng1Module = angular.module_('ng1', [downModA])
.value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({
component: Ng2CompA,
@ -1375,7 +1375,7 @@ withEachNg1Version(() => {
it('should throw if `downgradedModule` is not specified and there are multiple downgraded modules',
async(() => {
const ng1Module = angular.module('ng1', [downModA, downModB])
const ng1Module = angular.module_('ng1', [downModA, downModB])
.value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({
component: Ng2CompA,

View File

@ -66,7 +66,7 @@ withEachNg1Version(() => {
// This module represents the AngularJS pieces of the application
const ng1Module =
angular
.module('myExample', [])
.module_('myExample', [])
// This is an AngularJS component that will be upgraded
.directive(
'ng1',

View File

@ -40,8 +40,8 @@ withEachNg1Version(() => {
}
// create the ng1 module that will import an ng2 service
const ng1Module =
angular.module('ng1Module', []).factory('ng2Service', downgradeInjectable(Ng2Service));
const ng1Module = angular.module_('ng1Module', [])
.factory('ng2Service', downgradeInjectable(Ng2Service));
bootstrap(platformBrowserDynamic(), Ng2Module, html('<div>'), ng1Module)
.then((upgrade) => {
@ -71,7 +71,8 @@ withEachNg1Version(() => {
}
// create the ng1 module that will import an ng2 service
const ng1Module = angular.module('ng1Module', []).value('ng1Service', 'ng1 service value');
const ng1Module =
angular.module_('ng1Module', []).value('ng1Service', 'ng1 service value');
bootstrap(platformBrowserDynamic(), Ng2Module, html('<div>'), ng1Module)
.then((upgrade) => {
@ -84,7 +85,7 @@ withEachNg1Version(() => {
async(() => {
let runBlockTriggered = false;
const ng1Module = angular.module('ng1Module', []).run([
const ng1Module = angular.module_('ng1Module', []).run([
INJECTOR_KEY,
function(injector: Injector) {
runBlockTriggered = true;
@ -124,7 +125,7 @@ withEachNg1Version(() => {
ngDoBootstrap() {}
}
const ng1Module = angular.module('ng1Module', []);
const ng1Module = angular.module_('ng1Module', []);
bootstrap(platformBrowserDynamic(), Ng2Module, html('<div>'), ng1Module)
.then(upgrade => expect(wrappedBootstrapCalled).toBe(true))

View File

@ -31,7 +31,7 @@ withEachNg1Version(() => {
it('should handle deferred bootstrap', fakeAsync(() => {
let applicationRunning = false;
let stayedInTheZone: boolean = undefined !;
const ng1Module = angular.module('ng1', []).run(() => {
const ng1Module = angular.module_('ng1', []).run(() => {
applicationRunning = true;
stayedInTheZone = NgZone.isInAngularZone();
});
@ -50,7 +50,7 @@ withEachNg1Version(() => {
}));
it('should propagate return value of resumeBootstrap', fakeAsync(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
let a1Injector: angular.IInjectorService|undefined;
ng1Module.run([
'$injector', function($injector: angular.IInjectorService) { a1Injector = $injector; }
@ -69,7 +69,7 @@ withEachNg1Version(() => {
}));
it('should wait for ng2 testability', fakeAsync(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const element = html('<div></div>');
bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => {
@ -95,7 +95,7 @@ withEachNg1Version(() => {
}));
it('should not wait for $interval', fakeAsync(() => {
const ng1Module = angular.module('ng1', []);
const ng1Module = angular.module_('ng1', []);
const element = html('<div></div>');
bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => {

View File

@ -45,7 +45,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -85,7 +85,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -132,7 +132,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -173,7 +173,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(
@ -217,7 +217,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(
@ -268,7 +268,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.run(
@ -313,7 +313,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.value(
@ -364,7 +364,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.value(
@ -434,7 +434,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.component('ng1C', ng1ComponentC)
@ -506,7 +506,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -583,7 +583,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -664,7 +664,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -737,7 +737,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -834,7 +834,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -917,7 +917,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1007,7 +1007,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1075,7 +1075,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.component('ng1A', ng1ComponentA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2X', downgradeComponent({component: Ng2ComponentX}));
@ -1124,7 +1124,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1171,7 +1171,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1219,7 +1219,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1267,7 +1267,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1314,7 +1314,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1379,7 +1379,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1452,7 +1452,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1506,7 +1506,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1554,7 +1554,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.controller('Ng1Controller', class { text = 'GREAT'; })
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1608,7 +1608,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1664,7 +1664,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1716,7 +1716,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -1783,7 +1783,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const mockExceptionHandler = jasmine.createSpy($EXCEPTION_HANDLER);
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.component('ng1C', ng1ComponentC)
@ -1854,7 +1854,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const mockExceptionHandler = jasmine.createSpy($EXCEPTION_HANDLER);
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}))
.value($EXCEPTION_HANDLER, mockExceptionHandler);
@ -1929,7 +1929,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.component('ng1C', ng1ComponentC)
@ -1995,7 +1995,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2052,7 +2052,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2110,7 +2110,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.component('ng1C', ng1ComponentC)
@ -2175,7 +2175,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}));
@ -2236,7 +2236,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2302,7 +2302,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2377,7 +2377,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2450,7 +2450,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2509,7 +2509,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.value($EXCEPTION_HANDLER, (error: Error) => errorMessage = error.message)
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2574,7 +2574,7 @@ withEachNg1Version(() => {
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2670,7 +2670,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}))
@ -2823,7 +2823,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -2953,7 +2953,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3023,7 +3023,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3090,7 +3090,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3160,7 +3160,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3222,7 +3222,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3304,7 +3304,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3383,7 +3383,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3484,7 +3484,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3562,7 +3562,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3619,7 +3619,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}));
@ -3683,7 +3683,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}));
@ -3750,7 +3750,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}));
@ -3819,7 +3819,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}));
@ -3873,7 +3873,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1Module', [])
const ng1Module = angular.module_('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', downgradeComponent({component: Ng2Component}));
@ -3937,7 +3937,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.component('ng1X', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}))
.directive('ng2B', downgradeComponent({component: Ng2ComponentB}));
@ -4045,7 +4045,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.component('ng1X', ng1Component)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}))
.directive('ng2B', downgradeComponent({component: Ng2ComponentB}));
@ -4190,7 +4190,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module = angular.module('ng1', [])
const ng1Module = angular.module_('ng1', [])
.component('ng1A', ng1ComponentA)
.component('ng1B', ng1ComponentB)
.directive('ng2A', downgradeComponent({component: Ng2ComponentA}))

237
yarn.lock
View File

@ -708,6 +708,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"
@ -1593,6 +1598,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"
@ -1883,7 +1893,7 @@ cliui@^2.1.0:
right-align "^0.1.1"
wordwrap "0.0.2"
cliui@^3.0.3, cliui@^3.2.0:
cliui@^3.0.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
@ -2565,7 +2575,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==
@ -2722,7 +2732,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=
@ -3006,6 +3016,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"
@ -3329,6 +3344,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"
@ -3675,6 +3703,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"
@ -4143,6 +4178,11 @@ get-caller-file@^1.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=
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-pkg-repo@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d"
@ -4164,7 +4204,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==
@ -5158,6 +5198,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"
@ -5214,6 +5259,13 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-builtin-module@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.0.0.tgz#137d3d2425023a19a660fb9dd6ddfabe52c03466"
integrity sha512-/93sDihsAD652hrMEbJGbMAVBf1qc96kyThHQ0CAOONHaE3aROLpTjDe4WQ5aoC5ITHFxEq1z8XqSU7km+8amw==
dependencies:
builtin-modules "^3.0.0"
is-builtin-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
@ -5956,7 +6008,16 @@ karma-requirejs@1.1.0:
resolved "https://registry.yarnpkg.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz#fddae2cb87d7ebc16fb0222893564d7fee578798"
integrity sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=
karma-sauce-launcher@2.0.2, karma-sauce-launcher@^2.0.2:
karma-sauce-launcher@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/karma-sauce-launcher/-/karma-sauce-launcher-2.0.1.tgz#1d370ce7244b9cc804529ea373e848ad2f3da64a"
integrity sha512-hwMxGZNO6mJvvtm84ghY1SyPbb79P7dUX+RI4XVSfvPyjMSnOfgFbiUnm6MY2+P+sC+I78eMl4lA+p6BeZ/+9Q==
dependencies:
sauce-connect-launcher "^1.2.4"
saucelabs "^1.5.0"
selenium-webdriver "^4.0.0-alpha.1"
karma-sauce-launcher@2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/karma-sauce-launcher/-/karma-sauce-launcher-2.0.2.tgz#dbf98e70d86bf287b03a537cf637eb7aefa975c3"
integrity sha512-jLUFaJhHMcKpxFWUesyWYihzM5FvQiJsDwGcCtKeOy2lsWhkVw0V0Byqb1d+wU6myU1mribBtsIcub23HS4kWA==
@ -6109,6 +6170,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"
lie@~3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
@ -6146,16 +6214,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"
@ -6193,6 +6251,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"
@ -6589,6 +6655,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"
@ -6651,6 +6724,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"
@ -6853,6 +6935,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"
@ -7594,6 +7681,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"
@ -7622,6 +7718,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"
@ -7632,6 +7733,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.1.0"
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
p-limit@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
@ -7639,6 +7745,13 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
p-limit@^2.0.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
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"
@ -7646,6 +7759,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"
@ -7658,6 +7778,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"
@ -7873,13 +7998,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"
@ -8332,14 +8450,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"
@ -8357,15 +8467,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"
@ -8688,6 +8789,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"
@ -9730,6 +9836,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"
@ -9768,6 +9883,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"
@ -11064,12 +11186,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.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
dependencies:
camelcase "^4.1.0"
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^9.0.2:
version "9.0.2"
@ -11096,24 +11219,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@^3.10.0:
version "3.32.0"