Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
362b3e4d03 | |||
2952ea57a5 | |||
3541e590f4 | |||
8ef0ae3561 | |||
c3ff66c1ba | |||
a1d9848456 | |||
a3482f7076 | |||
006af0b985 | |||
9dc4815e39 | |||
4263d9ea0d | |||
30253a7df3 | |||
16b83e8e2f | |||
e0c10632ea | |||
686b62129c | |||
dd2587d9e5 | |||
2742649a52 | |||
eb0461d2d4 | |||
e24393c35b | |||
8237e958a6 | |||
9ba898d588 | |||
cd1b0c1b1f | |||
06072e0062 | |||
288e0ef7b6 | |||
88ad5052bf | |||
7e6644a25a | |||
d533d15001 | |||
d0abf1bc54 | |||
56ac18ea8c |
@ -7,158 +7,162 @@
|
||||
# To validate changes, use an online parser, eg.
|
||||
# http://yaml-online-parser.appspot.com/
|
||||
|
||||
# Note that the browser docker image comes with Chrome and Firefox preinstalled. This is just
|
||||
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
||||
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
||||
# docker image with browsers pre-installed.
|
||||
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
|
||||
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
|
||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the
|
||||
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
||||
# version that is compatible with the Chrome version in the image.
|
||||
var_1: &default_docker_image circleci/node:10.16@sha256:75c05084fff4afa3683a03c5a04a4a3ad95c536ff2439d8fe14e7e1f5c58b09a
|
||||
var_2: &browsers_docker_image circleci/node:10.16-browsers@sha256:d2a96fe1cbef51257ee626b5f645e64dade3e886f00ba9cb7e8ea65b4efe8db1
|
||||
# CircleCI configuration version
|
||||
# Version 2.1 allows for extra config reuse features
|
||||
# https://circleci.com/docs/2.0/reusing-config/#getting-started-with-config-reuse
|
||||
version: 2.1
|
||||
|
||||
# We don't want to include the current branch name in the cache key because that would prevent
|
||||
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||
# The cache key should only consist of dynamic values that change whenever something in the
|
||||
# cache changes. For example:
|
||||
# 1) yarn lock file changes --> cached "node_modules" are different.
|
||||
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
||||
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
||||
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
|
||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||
var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
|
||||
# Initializes the CI environment by setting up common environment variables.
|
||||
var_4: &init_environment
|
||||
run:
|
||||
name: Initializing environment (setting up variables, overwriting Yarn)
|
||||
# Overwrite the yarn installed in the docker container with our own version.
|
||||
command: |
|
||||
./.circleci/env.sh
|
||||
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.17.3/bin/yarn.js)
|
||||
sudo chmod a+x $ourYarn
|
||||
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
||||
echo "Yarn version: $(yarn --version)"
|
||||
|
||||
# Add GitHub to known hosts.
|
||||
mkdir -p ~/.ssh
|
||||
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
||||
|
||||
# use git+ssh instead of https
|
||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||
git config --global gc.auto 0 || true
|
||||
|
||||
|
||||
var_5: &setup_bazel_remote_execution
|
||||
run:
|
||||
name: "Setup bazel RBE remote execution"
|
||||
command: |
|
||||
# We need ensure that the same default digest is used for encoding and decoding
|
||||
# with openssl. Openssl versions might have different default digests which can
|
||||
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||
openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||
./.circleci/setup-rbe.sh .bazelrc.user
|
||||
|
||||
# Settings common to each job
|
||||
var_6: &job_defaults
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: *default_docker_image
|
||||
|
||||
# After checkout, rebase on top of target branch.
|
||||
var_7: &post_checkout
|
||||
run:
|
||||
name: Rebase PR on target branch
|
||||
command: >
|
||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||
# User is required for rebase.
|
||||
git config user.name "angular-ci"
|
||||
git config user.email "angular-ci"
|
||||
# Rebase PR on top of target branch.
|
||||
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
||||
else
|
||||
echo "This build is not over a PR, nothing to do."
|
||||
fi
|
||||
|
||||
var_8: &yarn_install
|
||||
run:
|
||||
name: Running Yarn install
|
||||
command: |
|
||||
# Yarn's requests sometimes take more than 10mins to complete.
|
||||
# Print something to stdout, to prevent CircleCI from failing due to not output.
|
||||
while true; do sleep 60; echo "[`date`] Keeping alive..."; done &
|
||||
KEEP_ALIVE_PID=$!
|
||||
yarn install --frozen-lockfile --non-interactive
|
||||
kill $KEEP_ALIVE_PID
|
||||
|
||||
var_9: &setup_circleci_bazel_config
|
||||
run:
|
||||
name: Setting up CircleCI bazel configuration
|
||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
var_10: &restore_cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- *cache_key
|
||||
# This fallback should be the cache_key without variables.
|
||||
- v3-angular-node-10.16-
|
||||
|
||||
# Branch filter that can be specified for jobs that should only run on publish branches
|
||||
# (e.g. master or the patch branch)
|
||||
var_11: &publish_branches_filter
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
# e.g. 7.0.x, 7.1.x, etc.
|
||||
- /\d+\.\d+\.x/
|
||||
|
||||
# Workspace initially persisted by the `install` job, and then enhanced by `test_aio` and
|
||||
# `build-npm-packages`.
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||
var_12: &attach_workspace
|
||||
attach_workspace:
|
||||
at: ~/
|
||||
|
||||
var_13: ¬ify_caretaker_on_fail
|
||||
run:
|
||||
when: on_fail
|
||||
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: |
|
||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_CARETAKER_WEBHOOK_URL
|
||||
|
||||
var_14: ¬ify_dev_infra_on_fail
|
||||
run:
|
||||
when: on_fail
|
||||
name: Notify dev-infra about failure
|
||||
# `$SLACK_DEV_INFRA_CI_FAILURES_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: |
|
||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" $SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
var_4: &cache_key_fallback v3-angular-node-10.16-
|
||||
|
||||
# Cache key for the Material unit tests job. **Note** when updating the SHA in the cache keys,
|
||||
# also update the SHA for the "MATERIAL_REPO_COMMIT" environment variable.
|
||||
var_15: &material_unit_tests_cache_key v4-angular-material-18b9ef3f5529f0fa8f034944681486447af7b879
|
||||
var_16: &material_unit_tests_cache_key_short v4-angular-material
|
||||
var_5: &material_unit_tests_cache_key v4-angular-material-18b9ef3f5529f0fa8f034944681486447af7b879
|
||||
var_6: &material_unit_tests_cache_key_fallback v4-angular-material-
|
||||
|
||||
version: 2
|
||||
|
||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||
# `build-ivy-npm-packages`.
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||
var_7: &workspace_location ~/
|
||||
|
||||
# Executor Definitions
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-executors
|
||||
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
|
||||
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
|
||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
# **NOTE 3**: If you change the version of the `*-browsers` docker image, make sure the
|
||||
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
||||
# version that is compatible with the Chrome version in the image.
|
||||
executors:
|
||||
default-executor:
|
||||
parameters:
|
||||
resource_class:
|
||||
type: string
|
||||
default: medium
|
||||
docker:
|
||||
- image: circleci/node:10.16@sha256:75c05084fff4afa3683a03c5a04a4a3ad95c536ff2439d8fe14e7e1f5c58b09a
|
||||
resource_class: << parameters.resource_class >>
|
||||
working_directory: ~/ng
|
||||
|
||||
browsers-executor:
|
||||
parameters:
|
||||
resource_class:
|
||||
type: string
|
||||
default: medium
|
||||
docker:
|
||||
# The browser docker image comes with Chrome and Firefox preinstalled. This is just
|
||||
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
||||
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
||||
# docker image with browsers pre-installed.
|
||||
- image: circleci/node:10.16-browsers@sha256:d2a96fe1cbef51257ee626b5f645e64dade3e886f00ba9cb7e8ea65b4efe8db1
|
||||
resource_class: << parameters.resource_class >>
|
||||
working_directory: ~/ng
|
||||
|
||||
# Command Definitions
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands
|
||||
commands:
|
||||
custom_attach_workspace:
|
||||
description: Attach workspace at a predefined location
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: *workspace_location
|
||||
|
||||
# Initializes the CI environment by setting up common environment variables.
|
||||
init_environment:
|
||||
description: Initializing environment (setting up variables, overwriting Yarn)
|
||||
steps:
|
||||
- run: ./.circleci/env.sh
|
||||
- run:
|
||||
# Overwrite the yarn installed in the docker container with our own version.
|
||||
name: Overwrite yarn with our own version
|
||||
command: |
|
||||
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.17.3/bin/yarn.js)
|
||||
sudo chmod a+x $ourYarn
|
||||
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
||||
- run: echo "Yarn version $(yarn --version)"
|
||||
- run:
|
||||
# Configure git as the CircleCI `checkout` command does.
|
||||
# This is needed because we only checkout on the setup job.
|
||||
# Add GitHub to known hosts
|
||||
name: Configure git
|
||||
command: |
|
||||
mkdir -p ~/.ssh
|
||||
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||
git config --global gc.auto 0 || true
|
||||
|
||||
setup_circleci_bazel_config:
|
||||
description: Set up CircleCI bazel configuration
|
||||
steps:
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
setup_bazel_rbe:
|
||||
description: Setup bazel RBE remote execution
|
||||
steps:
|
||||
# We need ensure that the same default digest is used for encoding and decoding
|
||||
# with openssl. Openssl versions might have different default digests which can
|
||||
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
||||
- run: openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||
- run: echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||
- run: ./.circleci/setup-rbe.sh .bazelrc.user
|
||||
|
||||
notify_webhook_on_fail:
|
||||
description: Notify a webhook about failure
|
||||
parameters:
|
||||
# `webhook_url_env_var` are secret env vars defined in CircleCI project settings.
|
||||
# The URLs come from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
webhook_url_env_var:
|
||||
type: env_var_name
|
||||
steps:
|
||||
- run:
|
||||
when: on_fail
|
||||
command: |
|
||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" ${<< parameters.webhook_url_env_var >>}
|
||||
|
||||
# Job definitions
|
||||
# Jobs can include parameters that are passed in the workflow job invocation.
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs
|
||||
jobs:
|
||||
setup:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout
|
||||
- *post_checkout
|
||||
- run:
|
||||
name: Rebase PR on target branch
|
||||
# After checkout, rebase on top of target branch.
|
||||
command: >
|
||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||
# User is required for rebase.
|
||||
git config user.name "angular-ci"
|
||||
git config user.email "angular-ci"
|
||||
# Rebase PR on top of target branch.
|
||||
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
||||
else
|
||||
echo "This build is not over a PR, nothing to do."
|
||||
fi
|
||||
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
||||
- *restore_cache
|
||||
- *init_environment
|
||||
- *yarn_install
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *cache_key
|
||||
- *cache_key_fallback
|
||||
- init_environment
|
||||
- run:
|
||||
name: Running Yarn install
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
# Yarn's requests sometimes take more than 10mins to complete.
|
||||
no_output_timeout: 45m
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Make the bazel directories and add a file to them if they don't exist already so that
|
||||
# persist_to_workspace does not fail.
|
||||
@ -168,19 +172,18 @@ jobs:
|
||||
touch ~/bazel_repository_cache/MARKER
|
||||
fi
|
||||
# Persist any changes at this point to be reused by further jobs.
|
||||
# **NOTE 1 **: Folders persisted here should be kept in sync with `var_13: &attach_workspace`.
|
||||
# **NOTE 2 **: To add new content to the workspace, always persist on the same root.
|
||||
# **NOTE**: To add new content to the workspace, always persist on the same root.
|
||||
- persist_to_workspace:
|
||||
root: ~/
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- ./ng
|
||||
- ./bazel_repository_cache
|
||||
|
||||
lint:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
|
||||
- run: 'yarn bazel:format -mode=check ||
|
||||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
||||
@ -192,25 +195,29 @@ jobs:
|
||||
- run: node tools/verify-codeownership
|
||||
|
||||
test:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- setup_circleci_bazel_config
|
||||
# Setup remote execution and run RBE-compatible tests.
|
||||
- *setup_bazel_remote_execution
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||
- setup_bazel_rbe
|
||||
- run:
|
||||
command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||
no_output_timeout: 20m
|
||||
|
||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||
test_ivy_aot:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- setup_circleci_bazel_config
|
||||
- setup_bazel_rbe
|
||||
|
||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||
# not be able to easily find the output bin directory when uploading artifacts for size
|
||||
@ -242,16 +249,17 @@ jobs:
|
||||
#
|
||||
# NOTE: This is currently limited to master builds only. See the `default_workflow` configuration.
|
||||
test_saucelabs_bazel:
|
||||
<<: *job_defaults
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- setup_circleci_bazel_config
|
||||
- setup_bazel_rbe
|
||||
- run:
|
||||
name: Run Bazel tests in saucelabs
|
||||
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
||||
@ -266,16 +274,16 @@ jobs:
|
||||
--username $SAUCE_USERNAME \
|
||||
--key $(echo $SAUCE_ACCESS_KEY | rev) \
|
||||
yarn bazel test //:test_web_all
|
||||
- *notify_dev_infra_on_fail
|
||||
no_output_timeout: 20m
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
test_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Build aio
|
||||
- run: yarn --cwd aio build --progress=false
|
||||
# Lint the code
|
||||
@ -294,27 +302,27 @@ jobs:
|
||||
- run: yarn --cwd aio redirects-test
|
||||
|
||||
deploy_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
||||
- image: *browsers_docker_image
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Deploy angular.io to production (if necessary)
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run: yarn --cwd aio deploy-production
|
||||
|
||||
test_aio_local:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
parameters:
|
||||
ivy:
|
||||
type: boolean
|
||||
default: false
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Build aio (with local Angular packages)
|
||||
- run: yarn --cwd aio build-local-ci
|
||||
- run: yarn --cwd aio build-local<<# parameters.ivy >>-with-ivy<</ parameters.ivy >>-ci
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
@ -322,32 +330,13 @@ jobs:
|
||||
# Run PWA-score tests
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size aio-local
|
||||
|
||||
test_aio_local_ivy:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
# Build aio with Ivy (using local Angular packages)
|
||||
- run: yarn --cwd aio build-with-ivy-ci
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
# Run PWA-score tests
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
- run: yarn --cwd aio payload-size aio-local-ivy
|
||||
- run: yarn --cwd aio payload-size aio-local<<# parameters.ivy >>-ivy<</ parameters.ivy >>
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Install
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd aio extract-cli-command-docs
|
||||
@ -356,56 +345,42 @@ jobs:
|
||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||
|
||||
test_docs_examples:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
parameters:
|
||||
ivy:
|
||||
type: boolean
|
||||
default: false
|
||||
executor:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
parallelism: 4
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||
|
||||
test_docs_examples_ivy:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
resource_class: xlarge
|
||||
# We increase the parallelism here to five while the "test_docs_examples" job runs with
|
||||
# a parallelism of four. This is necessary because this job also need to run NGCC which
|
||||
# takes up more time and we don't want these jobs to impact the overall CI turnaround.
|
||||
name: browsers-executor
|
||||
resource_class: xlarge
|
||||
parallelism: 5
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# 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, we should keep
|
||||
# the packages installer unchanged.
|
||||
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||
- when:
|
||||
condition: << parameters.ivy >>
|
||||
steps:
|
||||
# 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, we should keep
|
||||
# the packages installer unchanged.
|
||||
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
|
||||
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.ivy >>--ivy<</ parameters.ivy >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
environment:
|
||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||
- store_artifacts:
|
||||
path: *aio_preview_artifact_path
|
||||
@ -416,13 +391,11 @@ jobs:
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
test_aio_preview:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||
- image: *browsers_docker_image
|
||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run:
|
||||
name: Wait for preview and run tests
|
||||
@ -438,19 +411,20 @@ jobs:
|
||||
|
||||
# Build the view engine npm packages. No new jobs should depend on this.
|
||||
build-npm-packages:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- setup_circleci_bazel_config
|
||||
- setup_bazel_rbe
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
- persist_to_workspace:
|
||||
root: ~/
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- ng/dist/packages-dist
|
||||
|
||||
@ -464,19 +438,20 @@ jobs:
|
||||
|
||||
# Build the ivy npm packages.
|
||||
build-ivy-npm-packages:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- *setup_circleci_bazel_config
|
||||
- *setup_bazel_remote_execution
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- setup_circleci_bazel_config
|
||||
- setup_bazel_rbe
|
||||
|
||||
- run: scripts/build-ivy-npm-packages.sh
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
- persist_to_workspace:
|
||||
root: ~/
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- ng/dist/packages-dist-ivy-aot
|
||||
|
||||
@ -487,18 +462,17 @@ jobs:
|
||||
# need to re-run manually should be alleviated.
|
||||
# See comments inside the integration/run_tests.sh script.
|
||||
integration_test:
|
||||
<<: *job_defaults
|
||||
parallelism: 4
|
||||
docker:
|
||||
executor:
|
||||
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
||||
- image: *browsers_docker_image
|
||||
# Note: we run Bazel in one of the integration tests, and it can consume >2G
|
||||
# of memory. Together with the system under test, this can exhaust the RAM
|
||||
# on a 4G worker so we use a larger machine here too.
|
||||
resource_class: xlarge
|
||||
name: browsers-executor
|
||||
# Note: we run Bazel in one of the integration tests, and it can consume >2G
|
||||
# of memory. Together with the system under test, this can exhaust the RAM
|
||||
# on a 4G worker so we use a larger machine here too.
|
||||
resource_class: xlarge
|
||||
parallelism: 4
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
||||
# amount of container nodes for this job is controlled by the "parallelism" option.
|
||||
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||
@ -506,7 +480,7 @@ jobs:
|
||||
# This job updates the content of repos like github.com/angular/core-builds
|
||||
# for every green build on angular/angular.
|
||||
publish_snapshot:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
# See below - ideally this job should not trigger for non-upstream builds.
|
||||
# But since it does, we have to check this condition.
|
||||
@ -520,8 +494,8 @@ jobs:
|
||||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
||||
circleci step halt
|
||||
fi
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# CircleCI has a config setting to force SSH for all github connections
|
||||
# This is not compatible with our mechanism of using a Personal Access Token
|
||||
# Clear the global setting
|
||||
@ -535,14 +509,12 @@ jobs:
|
||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||
|
||||
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
|
||||
# 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.
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run:
|
||||
name: Check out `aio/` from the stable branch
|
||||
@ -552,33 +524,36 @@ jobs:
|
||||
- run:
|
||||
name: Run tests against https://angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- *notify_caretaker_on_fail
|
||||
- *notify_dev_infra_on_fail
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
aio_monitoring_next:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||
# which does not load the browser through the Bazel webtesting rules.
|
||||
- image: *browsers_docker_image
|
||||
# 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.
|
||||
executor: browsers-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run:
|
||||
name: Run tests against https://next.angular.io/
|
||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||
- *notify_caretaker_on_fail
|
||||
- *notify_dev_infra_on_fail
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||
- notify_webhook_on_fail:
|
||||
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||
|
||||
legacy-unit-tests-saucelabs:
|
||||
<<: *job_defaults
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
executor:
|
||||
name: default-executor
|
||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: |
|
||||
@ -597,10 +572,10 @@ jobs:
|
||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||
|
||||
legacy-misc-tests:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: yarn gulp check-cycle
|
||||
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
||||
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
||||
@ -609,23 +584,22 @@ jobs:
|
||||
# Job to run unit tests from angular/material2. Needs a browser since all
|
||||
# component unit tests assume they're running in the browser environment.
|
||||
material-unit-tests:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: *browsers_docker_image
|
||||
executor:
|
||||
name: browsers-executor
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Although RBE is configured below for the Material repo, also setup RBE in the Angular repo
|
||||
# to provision Angular's GCP token into the environment variables.
|
||||
- *setup_bazel_remote_execution
|
||||
- setup_bazel_rbe
|
||||
# Restore the cache before cloning the repository because the clone script re-uses
|
||||
# the restored repository if present. This reduces the amount of times the components
|
||||
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *material_unit_tests_cache_key
|
||||
- *material_unit_tests_cache_key_short
|
||||
- *material_unit_tests_cache_key_fallback
|
||||
- run:
|
||||
name: "Fetching Material repository"
|
||||
command: ./scripts/ci/clone_angular_material_repo.sh
|
||||
@ -648,10 +622,10 @@ jobs:
|
||||
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
||||
|
||||
test_zonejs:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *init_environment
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Install
|
||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
||||
# Run zone.js tools tests
|
||||
@ -710,7 +684,9 @@ workflows:
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_aio_local_ivy:
|
||||
- test_aio_local:
|
||||
name: test_aio_local_ivy
|
||||
ivy: true
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_aio_tools:
|
||||
@ -719,7 +695,9 @@ workflows:
|
||||
- test_docs_examples:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_docs_examples_ivy:
|
||||
- test_docs_examples:
|
||||
name: test_docs_examples_ivy
|
||||
ivy: true
|
||||
requires:
|
||||
- build-ivy-npm-packages
|
||||
- aio_preview:
|
||||
|
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@ -841,9 +841,7 @@ testing/** @angular/fw-test
|
||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/deprecations.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/migration-renderer.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/migration-undecorated-classes.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/migration-dynamic-flag.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
|
@ -1,3 +1,10 @@
|
||||
<a name="8.2.10"></a>
|
||||
## [8.2.10](https://github.com/angular/angular/compare/8.2.9...8.2.10) (2019-10-09)
|
||||
|
||||
This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="8.2.9"></a>
|
||||
## [8.2.9](https://github.com/angular/angular/compare/8.2.8...8.2.9) (2019-10-02)
|
||||
|
||||
|
@ -201,7 +201,7 @@ Must be one of the following:
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
### Scope
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||
|
||||
The following is the list of supported scopes:
|
||||
|
||||
|
@ -18,7 +18,7 @@ Here are the most important tasks you might need to use:
|
||||
|
||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||
* `yarn build-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
|
||||
* `yarn build-local-with-ivy` - same as `build-local`, but in addition also turns on `ivy` mode in aio.
|
||||
(Note: To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
|
||||
|
||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||
|
@ -206,6 +206,7 @@ function heroModuleSetup() {
|
||||
nameInput.value = 'quick BROWN fOx';
|
||||
|
||||
// dispatch a DOM event so that Angular learns of input value change.
|
||||
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
||||
nameInput.dispatchEvent(newEvent('input'));
|
||||
|
||||
// Tell Angular to update the display binding through the title pipe
|
||||
|
@ -28,7 +28,7 @@ export class KeyUpComponent_v1 {
|
||||
// #docregion key-up-component-1-class
|
||||
|
||||
onKey(event: KeyboardEvent) { // with type info
|
||||
this.values += (<HTMLInputElement>event.target).value + ' | ';
|
||||
this.values += (event.target as HTMLInputElement).value + ' | ';
|
||||
}
|
||||
// #docregion key-up-component-1-class-no-type
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ export class AppComponent {
|
||||
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
|
||||
The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
|
||||
|
||||
The compiler can only create instances certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
||||
The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
|
||||
* New instances
|
||||
|
||||
The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
|
||||
|
@ -142,7 +142,7 @@ Begin by adding `HostListener` to the list of imported symbols.
|
||||
|
||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
|
||||
|
||||
Then add two eventhandlers that respond when the mouse enters or leaves,
|
||||
Then add two event handlers that respond when the mouse enters or leaves,
|
||||
each adorned by the `HostListener` decorator.
|
||||
|
||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
|
||||
|
@ -321,7 +321,7 @@ In a typical Angular project, the polyfill is not used in production builds, so
|
||||
{@a static-query-resolution}
|
||||
### `@ViewChild()` / `@ContentChild()` static resolution as the default
|
||||
|
||||
See the [dedicated migration guide for static queries](guide/static-query-migration).
|
||||
See our [dedicated migration guide for static queries](guide/static-query-migration).
|
||||
|
||||
{@a contentchild-input-together}
|
||||
### `@ContentChild()` / `@Input()` used together
|
||||
@ -389,23 +389,6 @@ As of Angular version 8, all `platform-webworker` APIs are deprecated.
|
||||
This includes both packages: `@angular/platform-webworker` and
|
||||
`@angular/platform-webworker-dynamic`.
|
||||
|
||||
|
||||
## Angular version 9 schematics
|
||||
|
||||
{@a renderer-to-renderer2}
|
||||
### Migrating from `Renderer` to `Renderer2`
|
||||
|
||||
See the [dedicated migration guide for Renderer](guide/migration-renderer).
|
||||
|
||||
{@a undecorated-classes}
|
||||
### Migrating undecorated classes
|
||||
See the [dedicated migration guide for undecorated classes](guide/migration-undecorated-classes).
|
||||
|
||||
{@a flag-migration}
|
||||
### Dynamic queries flag migration
|
||||
|
||||
See the [dedicated migration guide for dynamic queries](guide/migration-dynamic-flag).
|
||||
|
||||
{@a removed}
|
||||
## Removed APIs
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
|
||||
# Dynamic queries flag migration
|
||||
|
||||
## What does this migration do?
|
||||
|
||||
In Angular version 8, a schematic added `static` flags to all `@ViewChild()`
|
||||
and `@ContentChild()` queries.
|
||||
This was the first step towards changing the default behavior.
|
||||
With version 9, the default value
|
||||
changes to `static: false` and the flag becomes optional.
|
||||
|
||||
This schematic scans classes in the compilation and for each
|
||||
class, checks if the members have a `@ViewChild()` or
|
||||
`@ContentChild()` query with the `static` flag set to
|
||||
`false`. If so, the schematic removes the flag, as it
|
||||
now matches the default.
|
||||
|
||||
**Before:**
|
||||
```ts
|
||||
@ViewChild('foo', {static: false}) foo: ElementRef;
|
||||
|
||||
@ViewChild('bar', {static: true}) bar: ElementRef;
|
||||
```
|
||||
|
||||
|
||||
**After:**
|
||||
```ts
|
||||
@ViewChild('foo') foo: ElementRef;
|
||||
|
||||
// this query doesn't change because the static value is true
|
||||
@ViewChild('bar', {static: true}) bar: ElementRef;
|
||||
```
|
||||
|
||||
Note that the flag is not supported in `@ViewChildren()`
|
||||
or `@ContentChildren()` queries, so the schematic
|
||||
will not check these properties.
|
||||
|
||||
|
||||
## Why is this migration necessary?
|
||||
|
||||
This schematic performs a code cleanup to remove `static`
|
||||
flags that match the default, as they are no longer
|
||||
necessary. Functionally, the code change should be a noop.
|
||||
|
||||
Before version 9, Angular figured out the static or
|
||||
dynamic nature of a query automatically, based
|
||||
on how the template was written. Looking at templates
|
||||
in this way, however, caused buggy and surprising behavior
|
||||
(see more about that in the [Static Query Migration Guide](guide/static-query-migration#what-does-this-flag-mean)).
|
||||
As of version 9, Angular uses dynamic queries
|
||||
(`static: false`) by default, which simplifies
|
||||
queries. Developers can still explicitly set a
|
||||
query to `static: true` if necessary.
|
||||
|
||||
|
||||
<div class=" alert is-helpful">
|
||||
|
||||
### What is the difference between static and dynamic queries?
|
||||
|
||||
The `static` option for `@ViewChild()` and `@ContentChild()`
|
||||
queries determines when
|
||||
the query results become available.
|
||||
|
||||
With static queries (`static: true`), the query resolves
|
||||
once the view has been created, but before change detection runs.
|
||||
The result, though, will never be updated to reflect
|
||||
changes to your view, such as
|
||||
changes to `ngIf` and `ngFor` blocks.
|
||||
|
||||
With dynamic queries (`static: false`), the query resolves
|
||||
after either `ngAfterViewInit()` or
|
||||
`ngAfterContentInit()` for `@ViewChild()` and `@ContentChild()`
|
||||
respectively. The result will
|
||||
be updated for changes to your view, such as changes to
|
||||
`ngIf` and `ngFor` blocks.
|
||||
|
||||
For more information, see the following entries in the
|
||||
[Static Query Migration Guide](https://angular.io/guide/static-query-migration):
|
||||
|
||||
* [How do I choose which `static` flag value to use: `true` or `false`?](https://angular.io/guide/static-query-migration#how-do-i-choose-which-static-flag-value-to-use-true-or-false)
|
||||
|
||||
* [Is there a case where I should use `{static: true}`?](https://angular.io/guide/static-query-migration#is-there-a-case-where-i-should-use-static-true)
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## What does this mean for libraries?
|
||||
|
||||
In order to support applications that are still running
|
||||
with version 8, the safest option for libraries is to
|
||||
retain the `static` flag to keep the resolution
|
||||
timing consistent.
|
||||
|
||||
- *Libraries on version 9 with applications running version 8: *
|
||||
|
||||
The schematic won't run on libraries. As long as libraries retain their `static` flags from version 8, they should work with apps on 8.
|
||||
|
||||
- *Libraries on version 8 with applications running version 9: *
|
||||
|
||||
Libraries will have explicit flags defined. The behavior
|
||||
with explicit flags has not changed.
|
||||
|
||||
|
||||
### What about applications using non-migrated libraries?
|
||||
|
||||
Because this is a code cleanup that is a noop,
|
||||
non-migrated libraries will work the same either way.
|
@ -1,96 +0,0 @@
|
||||
# `Renderer` to `Renderer2` migration
|
||||
|
||||
## Migration Overview
|
||||
|
||||
The `Renderer` class has been marked as deprecated since Angular version 4. This section provides guidance on migrating from this deprecated API to the newer `Renderer2` API and what it means for your app.
|
||||
|
||||
## Why should I migrate to Renderer2?
|
||||
|
||||
The deprecated `Renderer` class has been removed in version 9 of Angular, so it's necessary to migrate to a supported API. Using `Renderer2` is the recommended strategy because it supports a similar set of functionality to `Renderer`. The API surface is quite large (with 19 methods), but the schematic should simplify this process for your applications.
|
||||
|
||||
## Is there action required on my end?
|
||||
|
||||
No. The schematic should handle most cases with the exception of `Renderer.animate()` and `Renderer.setDebugInfo()`, which already aren’t supported.
|
||||
|
||||
## What are the `__ngRendererX` methods? Why are they necessary?
|
||||
|
||||
Some methods either don't have exact equivalents in `Renderer2`, or they correspond to more than one expression. For example, both renderers have a `createElement()` method, but they're not equal because a call such as `renderer.createElement(parentNode, namespaceAndName)` in the `Renderer` corresponds to the following block of code in `Renderer2`:
|
||||
|
||||
```ts
|
||||
const [namespace, name] = splitNamespace(namespaceAndName);
|
||||
const el = renderer.createElement(name, namespace);
|
||||
if (parentNode) {
|
||||
renderer.appendChild(parentNode, el);
|
||||
}
|
||||
return el;
|
||||
```
|
||||
|
||||
Migration has to guarantee that the return values of functions and types of variables stay the same. To handle the majority of cases safely, the schematic declares helper functions at the bottom of the user's file. These helpers encapsulate your own logic and keep the replacements inside your code down to a single function call. Here's an example of how the `createElement()` migration looks:
|
||||
|
||||
|
||||
**Before:**
|
||||
|
||||
```ts
|
||||
public createAndAppendElement() {
|
||||
const el = this.renderer.createElement('span');
|
||||
el.textContent = 'hello world';
|
||||
return el;
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
<code-example>
|
||||
|
||||
public createAndAppendElement() {
|
||||
const el = __ngRendererCreateElement(this.renderer, this.element, 'span');
|
||||
el.textContent = 'hello world';
|
||||
return el;
|
||||
}
|
||||
// Generated code at the bottom of the file
|
||||
__ngRendererCreateElement(renderer: any, parentNode: any, nameAndNamespace: any) {
|
||||
const [namespace, name] = __ngRendererSplitNamespace(namespaceAndName);
|
||||
const el = renderer.createElement(name, namespace);
|
||||
if (parentNode) {
|
||||
renderer.appendChild(parentNode, el);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
__ngRendererSplitNamespace(nameAndNamespace: any) {
|
||||
// returns the split name and namespace
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
When implementing these helper functions, the schematic ensures that they're only declared once per file and that their names are unique enough that there's a small chance of colliding with pre-existing functions in your code. The schematic also keeps their parameter types as `any` so that it doesn't have to insert extra logic that ensures that their values have the correct type.
|
||||
|
||||
### I’m a library author. Should I run this migration?
|
||||
|
||||
**Library authors should definitely use this migration to move away from the `Renderer`. Otherwise, the libraries won't work with applications built with version 9.**
|
||||
|
||||
|
||||
### Full list of method migrations
|
||||
|
||||
The following table shows all methods that the migration maps from `Renderer` to `Renderer2`.
|
||||
|
||||
|Renderer|Renderer2|
|
||||
|---|---|
|
||||
|`listen(renderElement, name, callback)`|`listen(renderElement, name, callback)`|
|
||||
|`setElementProperty(renderElement, propertyName, propertyValue)`|`setProperty(renderElement, propertyName, propertyValue)`|
|
||||
|`setText(renderNode, text)`|`setValue(renderNode, text)`|
|
||||
|`listenGlobal(target, name, callback)`|`listen(target, name, callback)`|
|
||||
|`selectRootElement(selectorOrNode, debugInfo?)`|`selectRootElement(selectorOrNode)`|
|
||||
|`createElement(parentElement, name, debugInfo?)`|`appendChild(parentElement, createElement(name))`|
|
||||
|`setElementStyle(el, style, value?)`|`value == null ? removeStyle(el, style) : setStyle(el, style, value)`
|
||||
|`setElementAttribute(el, name, value?)`|`attributeValue == null ? removeAttribute(el, name) : setAttribute(el, name, value)`
|
||||
|`createText(parentElement, value, debugInfo?)`|`appendChild(parentElement, createText(value))`|
|
||||
|`createTemplateAnchor(parentElement)`|`appendChild(parentElement, createComment(''))`|
|
||||
|`setElementClass(renderElement, className, isAdd)`|`isAdd ? addClass(renderElement, className) : removeClass(renderElement, className)`|
|
||||
|`projectNodes(parentElement, nodes)`|`for (let i = 0; i < nodes.length; i<ins></ins>) { appendChild(parentElement, nodes<i>); }`|
|
||||
|`attachViewAfter(node, viewRootNodes)`|`const parentElement = parentNode(node); const nextSibling = nextSibling(node); for (let i = 0; i < viewRootNodes.length; i<ins></ins>) { insertBefore(parentElement, viewRootNodes<i>, nextSibling);}`|
|
||||
|`detachView(viewRootNodes)`|`for (let i = 0; i < viewRootNodes.length; i<ins></ins>) {const node = viewRootNodes<i>; const parentElement = parentNode(node); removeChild(parentElement, node);}`|
|
||||
|`destroyView(hostElement, viewAllNodes)`|`for (let i = 0; i < viewAllNodes.length; i<ins></ins>) { destroyNode(viewAllNodes<i>); }`|
|
||||
|`setBindingDebugInfo()`|This function is a noop in `Renderer2`.|
|
||||
|`createViewRoot(hostElement)`|Should be replaced with a reference to `hostElement`|
|
||||
|`invokeElementMethod(renderElement, methodName, args?)`|`(renderElement as any)<methodName>.apply(renderElement, args);`|
|
||||
|`animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?)`|Throws an error (same behavior as `Renderer.animate()`)|
|
@ -1,138 +0,0 @@
|
||||
# Undecorated classes migration (DI)
|
||||
|
||||
This section discusses an Angular version 9 schematic that migrates
|
||||
two inheritance patterns that need to be updated to work with Ivy.
|
||||
|
||||
## What does this migration do?
|
||||
|
||||
This migration adds an empty `@Directive()` decorator to undecorated
|
||||
base classes that are extended by either directives or components.
|
||||
|
||||
Before:
|
||||
```ts
|
||||
export class BaseMenu {
|
||||
constructor(private vcr: ViewContainerRef) {}
|
||||
}
|
||||
|
||||
@Directive({selector: '[settingsMenu]'})
|
||||
export class SettingsMenu extends BaseMenu {}
|
||||
```
|
||||
|
||||
After:
|
||||
```ts
|
||||
@Directive()
|
||||
export class BaseMenu {
|
||||
constructor(private vcr: ViewContainerRef) {}
|
||||
}
|
||||
|
||||
@Directive({selector: '[settingsMenu]'})
|
||||
export class SettingsMenu extends BaseMenu {}
|
||||
```
|
||||
|
||||
The schematic also copies any inherited directive or component metadata to the derived class.
|
||||
|
||||
Before:
|
||||
```ts
|
||||
@Component({
|
||||
selector: 'base-menu',
|
||||
template: '<div></div>'
|
||||
})
|
||||
class BaseMenu {}
|
||||
|
||||
export class SettingsMenu extends BaseMenu {}
|
||||
```
|
||||
|
||||
After:
|
||||
```ts
|
||||
@Component({
|
||||
selector: 'base-menu',
|
||||
template: '<div></div>'
|
||||
})
|
||||
class BaseMenu {}
|
||||
|
||||
@Component({
|
||||
selector: 'settings-menu',
|
||||
template: '<div></div>'
|
||||
})
|
||||
export class SettingsMenu extends BaseMenu {}
|
||||
```
|
||||
|
||||
## Why is this migration necessary?
|
||||
|
||||
When a class has a `@Directive()` or `@Component()` decorator,
|
||||
the Angular compiler generates extra code to inject dependencies into
|
||||
the constructor. When using inheritance, Ivy needs both the parent class
|
||||
and the child class to apply a decorator to generate the correct code.
|
||||
|
||||
You can think of this change as two cases: a parent class is missing a
|
||||
decorator or a child class is missing a decorator. In both scenarios,
|
||||
Angular's run-time needs additional information from the compiler.
|
||||
This additional information comes from adding decorators.
|
||||
|
||||
|
||||
### Decorator missing from parent class
|
||||
|
||||
When the decorator is missing from the parent class,
|
||||
the subclass will inherit a constructor from a class for
|
||||
which the compiler did not generate special constructor
|
||||
info (because it was not decorated as a directive).
|
||||
When Angular then tries to create the subclass,
|
||||
it doesn't have the correct info
|
||||
to create it.
|
||||
|
||||
In View Engine, the compiler has global knowledge, so it
|
||||
can look up the missing data. However, the Ivy compiler
|
||||
only processes each directive in isolation. This means that
|
||||
compilation can be faster, but the compiler can't
|
||||
automatically infer the same
|
||||
information as before. Adding the `@Directive()` explicitly
|
||||
provides this information.
|
||||
|
||||
In the future, add `@Directive()` to base classes that
|
||||
do not already have decorators and are extended by directives.
|
||||
|
||||
### Decorator missing from child class
|
||||
|
||||
When the child class is missing the decorator, the
|
||||
child class inherits from the
|
||||
parent class yet has no decorators of its own.
|
||||
Without a decorator, the compiler has no way of knowing
|
||||
that the class is a `@Directive` or `@Component`, so
|
||||
it doesn't generate the proper instructions for the directive.
|
||||
|
||||
|
||||
## What does it mean to have a `@Directive()` decorator with no metadata inside of it?
|
||||
|
||||
The presence of the `@Directive` decorator causes Angular to generate
|
||||
extra code for the affected class. If that decorator includes no
|
||||
properties (metadata),
|
||||
the directive won't be matched to elements or instantiated
|
||||
directly, but other classes that _extend_ the
|
||||
directive class will inherit this generated code. You can think of
|
||||
this as an "abstract" directive.
|
||||
|
||||
Adding an abstract directive to an `NgModule` will cause an error.
|
||||
A directive must have a `selector` property defined in order to match some element in a template.
|
||||
|
||||
## When do I need a `@Directive()` decorator without a selector?
|
||||
|
||||
If you're using dependency injection, or any Angular-specific
|
||||
feature, such as `@HostBinding()`, `@ViewChild()`, or `@Input()`, you need a
|
||||
`@Directive()` or `@Component()` decorator.
|
||||
The decorator lets the compiler know to generate the correct
|
||||
instructions to create that class and any classes that extend it.
|
||||
If you don't want to use that base class as a directive directly, leave
|
||||
the selector blank. If you do want it to be usable independently,
|
||||
fill in the metadata as usual.
|
||||
|
||||
Classes that don't use Angular features don't need an Angular decorator.
|
||||
|
||||
## I'm a library author. Should I add the `@Directive()` decorator to base classes?
|
||||
|
||||
|
||||
As support for selectorless decorators is introduced in
|
||||
Angular version 9, if you want to support Angular version 8 and earlier, you
|
||||
shouldn't add a selectorless `@Directive()` decorator.
|
||||
You can either add `@Directive()` with a selector or
|
||||
add an explicit constructor to affected subclasses.
|
||||
|
@ -674,6 +674,13 @@
|
||||
"rev": true,
|
||||
"title": "MDB Angular Boilerplate",
|
||||
"url": "https://github.com/mdbootstrap/Angular-Bootstrap-Boilerplate"
|
||||
},
|
||||
"dotnettricks": {
|
||||
"desc": "Online videos and training for Angular.",
|
||||
"logo": "",
|
||||
"rev": true,
|
||||
"title": "DotNetTricks",
|
||||
"url": "https://www.dotnettricks.com/courses/angular"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -90,8 +90,16 @@ The product details component handles the display of each product. The Angular R
|
||||
<code-example path="getting-started/src/app/product-details/product-details.component.1.ts" region="get-product">
|
||||
</code-example>
|
||||
|
||||
Angular calls `ngOnInit()` shortly after creating a component.
|
||||
|
||||
The route parameters correspond to the path variables defined in the route. The `productId` is provided from
|
||||
the URL that was matched to the route. You use the `productId` to display the details for each unique product.
|
||||
the URL that was matched to the route. You use the `productId` to display the details for each unique product.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more information on `ngOnInit()`, see [Lifecycle hooks](guide/lifecycle-hooks).
|
||||
|
||||
</div>
|
||||
|
||||
1. Update the template to display product details information inside an `*ngIf`.
|
||||
|
||||
|
@ -19,10 +19,10 @@
|
||||
"build-local": "yarn ~~build",
|
||||
"prebuild-local-ci": "yarn setup-local --no-build-packages",
|
||||
"build-local-ci": "yarn ~~build --progress=false",
|
||||
"prebuild-with-ivy": "yarn setup-local && node scripts/switch-to-ivy",
|
||||
"build-with-ivy": "yarn ~~build",
|
||||
"prebuild-with-ivy-ci": "yarn setup-local --no-build-packages && node scripts/switch-to-ivy",
|
||||
"build-with-ivy-ci": "yarn ~~build --progress=false",
|
||||
"prebuild-local-with-ivy": "yarn setup-local && node scripts/switch-to-ivy",
|
||||
"build-local-with-ivy": "yarn ~~build",
|
||||
"prebuild-local-with-ivy-ci": "yarn setup-local --no-build-packages && node scripts/switch-to-ivy",
|
||||
"build-local-with-ivy-ci": "yarn ~~build --progress=false",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js e21aeeecd",
|
||||
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
||||
"test": "yarn check-env && ng test",
|
||||
@ -115,7 +115,7 @@
|
||||
"chalk": "^2.1.0",
|
||||
"chrome-launcher": "^0.10.7",
|
||||
"cjson": "^0.5.0",
|
||||
"codelyzer": "^5.0.0",
|
||||
"codelyzer": "^5.1.1",
|
||||
"cross-spawn": "^5.1.0",
|
||||
"css-selector-parser": "^1.3.0",
|
||||
"dgeni": "^0.4.11",
|
||||
|
@ -7,10 +7,11 @@ import { LocationService } from 'app/shared/location.service';
|
||||
selector: `aio-contributor-list`,
|
||||
template: `
|
||||
<div class="flex-center group-buttons">
|
||||
<a *ngFor="let name of groupNames"
|
||||
[class.selected]="name == selectedGroup.name"
|
||||
class="button mat-button filter-button"
|
||||
(click)="selectGroup(name)">{{name}}</a>
|
||||
<a *ngFor="let name of groupNames"
|
||||
[class.selected]="name == selectedGroup.name"
|
||||
class="button mat-button filter-button"
|
||||
(click)="selectGroup(name)"
|
||||
(keyup.enter)="selectGroup(name)">{{name}}</a>
|
||||
</div>
|
||||
<section *ngIf="selectedGroup" class="grid-fluid">
|
||||
<div class="contributor-group">
|
||||
|
@ -8,7 +8,7 @@ import { CONTENT_URL_PREFIX } from 'app/documents/document.service';
|
||||
template: `
|
||||
<div [ngClass]="{ 'flipped': person.isFlipped }" class="contributor-card">
|
||||
|
||||
<div class="card-front" (click)="flipCard(person)">
|
||||
<div class="card-front" (click)="flipCard(person)" (keyup.enter)="flipCard(person)">
|
||||
<h3>{{person.name}}</h3>
|
||||
|
||||
<div class="contributor-image" [style.background-image]="'url('+pictureBase+(person.picture || noPicture)+')'">
|
||||
@ -28,7 +28,7 @@ import { CONTENT_URL_PREFIX } from 'app/documents/document.service';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-back" *ngIf="person.isFlipped" (click)="flipCard(person)">
|
||||
<div class="card-back" *ngIf="person.isFlipped" (click)="flipCard(person)" (keyup.enter)="flipCard(person)">
|
||||
<h3>{{person.name}}</h3>
|
||||
<p class="contributor-bio">{{person.bio}}</p>
|
||||
</div>
|
||||
|
@ -4,6 +4,7 @@ import { PlatformLocation } from '@angular/common';
|
||||
import { Category } from './resource.model';
|
||||
import { ResourceService } from './resource.service';
|
||||
|
||||
/* tslint:disable:template-accessibility-elements-content */
|
||||
@Component({
|
||||
selector: 'aio-resource-list',
|
||||
templateUrl: 'resource-list.component.html'
|
||||
|
@ -1,4 +1,4 @@
|
||||
<span class="content" (click)="contentClick()">
|
||||
<span class="content" (click)="contentClick()" (keyup.enter)="contentClick()">
|
||||
<ng-content></ng-content>
|
||||
</span>
|
||||
|
||||
|
@ -21,16 +21,6 @@
|
||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||
/**
|
||||
* DO NOT REMOVE
|
||||
* By default, Reflect polyfills are auto-included by the CLI and
|
||||
* are required for JIT compilation. StackBlitz examples are
|
||||
* compiled using JIT.
|
||||
*/
|
||||
import 'core-js/es6/reflect';
|
||||
import 'core-js/es7/reflect';
|
||||
|
||||
/**
|
||||
* Web Animations `@angular/platform-browser/animations`
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
@ -65,8 +55,7 @@ import 'core-js/es7/reflect';
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
import 'zone.js/dist/zone-patch-canvas';
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
|
@ -33,7 +33,7 @@
|
||||
"@nguniversal/express-engine": "^8.0.0-rc.1",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^8.0.0-rc.1",
|
||||
"angular": "1.7.8",
|
||||
"angular-in-memory-web-api": "github:brandonroberts/in-memory-web-api-bazel#50a34d8",
|
||||
"angular-in-memory-web-api": "^0.9.0",
|
||||
"angular-route": "1.7.8",
|
||||
"core-js": "^2.5.4",
|
||||
"express": "^4.14.1",
|
||||
@ -69,7 +69,7 @@
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"lite-server": "^2.2.2",
|
||||
"lodash": "^4.16.2",
|
||||
"protractor": "~5.4.0",
|
||||
|
@ -795,11 +795,10 @@ amdefine@>=0.0.4:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
|
||||
"angular-in-memory-web-api@github:brandonroberts/in-memory-web-api-bazel#50a34d8":
|
||||
version "0.8.0"
|
||||
resolved "https://codeload.github.com/brandonroberts/in-memory-web-api-bazel/tar.gz/50a34d84b627ec88816242dec77603d6dcb9c880"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
angular-in-memory-web-api@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/angular-in-memory-web-api/-/angular-in-memory-web-api-0.9.0.tgz#6c98d9494fadc6b98f54e68376a1998ccfff04bc"
|
||||
integrity sha512-//PiJ5qb1+Yf/N7270ioQqR2laf4/Irjavg+M+WEn8y4At9LUoYgbQ5HVwvM5xUTlVlL0XkbJRLxREcGGNdIEw==
|
||||
|
||||
angular-route@1.7.8:
|
||||
version "1.7.8"
|
||||
@ -4430,15 +4429,10 @@ karma-coverage-istanbul-reporter@~2.0.1:
|
||||
istanbul-api "^2.0.5"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
karma-jasmine-html-reporter@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz#48a8e5ef18807617ee2b5e33c1194c35b439524c"
|
||||
dependencies:
|
||||
karma-jasmine "^1.0.2"
|
||||
|
||||
karma-jasmine@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.0.tgz#22e4c06bf9a182e5294d1f705e3733811b810acf"
|
||||
karma-jasmine-html-reporter@^1.4.2:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz#16d100fd701271192d27fd28ddc90b710ad36fff"
|
||||
integrity sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw==
|
||||
|
||||
karma-jasmine@~2.0.1:
|
||||
version "2.0.1"
|
||||
|
@ -29,6 +29,7 @@ module.exports =
|
||||
.processor(require('./processors/processClassLikeMembers'))
|
||||
.processor(require('./processors/markBarredODocsAsPrivate'))
|
||||
.processor(require('./processors/filterPrivateDocs'))
|
||||
.processor(require('./processors/filterMembers'))
|
||||
.processor(require('./processors/computeSearchTitle'))
|
||||
.processor(require('./processors/simplifyMemberAnchors'))
|
||||
.processor(require('./processors/computeStability'))
|
||||
@ -176,6 +177,12 @@ module.exports =
|
||||
filterContainedDocs.docTypes = API_CONTAINED_DOC_TYPES;
|
||||
})
|
||||
|
||||
.config(function(filterMembers) {
|
||||
filterMembers.notAllowedPatterns.push(
|
||||
/^ng[A-Z].*Def$/
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
.config(function(computePathsProcessor, EXPORT_DOC_TYPES, generateApiListDoc) {
|
||||
|
||||
|
21
aio/tools/transforms/angular-api-package/processors/filterMembers.js
vendored
Normal file
21
aio/tools/transforms/angular-api-package/processors/filterMembers.js
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Filter out members (i.e. static and instance properties and methods) that match specific
|
||||
* patterns. Patterns can be added (as `RegExp`s) to the `notAllowedPatterns` array.
|
||||
*
|
||||
* (By default, no members are excluded.)
|
||||
*/
|
||||
module.exports = function filterMembers() {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
notAllowedPatterns: [],
|
||||
$process(docs) {
|
||||
const isAllowed = ({name}) => !this.notAllowedPatterns.some(re => re.test(name));
|
||||
|
||||
docs.forEach(doc => {
|
||||
if (doc.statics) doc.statics = doc.statics.filter(isAllowed);
|
||||
if (doc.members) doc.members = doc.members.filter(isAllowed);
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
@ -0,0 +1,102 @@
|
||||
const processorFactory = require('./filterMembers');
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('filterMembers processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('filterMembers');
|
||||
expect(processor.$process).toBeDefined();
|
||||
expect(processor.$runAfter).toEqual(['processing-docs']);
|
||||
expect(processor.$runBefore).toEqual(['docs-processed']);
|
||||
});
|
||||
|
||||
it('should remove members that match one of the not allowed patterns', () => {
|
||||
const processor = processorFactory();
|
||||
processor.notAllowedPatterns = [/^foo/, /bar$/];
|
||||
const docs = [
|
||||
// Doc without members.
|
||||
{ },
|
||||
|
||||
// Doc with static members only.
|
||||
{
|
||||
statics: [
|
||||
{ name: 'fooStatic' }, // Will be removed.
|
||||
{ name: 'FOOStatic' },
|
||||
{ name: 'barStatic' },
|
||||
{ name: 'statiCbar' }, // Will be removed.
|
||||
],
|
||||
},
|
||||
|
||||
// Doc with instance members only.
|
||||
{
|
||||
members: [
|
||||
{ name: 'fooInstance' }, // Will be removed.
|
||||
{ name: 'FOOInstance' },
|
||||
{ name: 'barInstance' },
|
||||
{ name: 'instancEbar' }, // Will be removed.
|
||||
],
|
||||
},
|
||||
|
||||
// Doc with both static and instance members.
|
||||
{
|
||||
statics: [
|
||||
{ name: 'fooStatic' }, // Will be removed.
|
||||
{ name: 'FOOStatic' },
|
||||
{ name: 'barStatic' },
|
||||
{ name: 'statiCbar' }, // Will be removed.
|
||||
],
|
||||
members: [
|
||||
{ name: 'fooInstance' }, // Will be removed.
|
||||
{ name: 'FOOInstance' },
|
||||
{ name: 'barInstance' },
|
||||
{ name: 'instancEbar' }, // Will be removed.
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
processor.$process(docs);
|
||||
|
||||
expect(docs).toEqual([
|
||||
{ },
|
||||
{
|
||||
statics: [ { name: 'FOOStatic' }, { name: 'barStatic' } ],
|
||||
},
|
||||
{
|
||||
members: [ { name: 'FOOInstance' }, { name: 'barInstance' } ],
|
||||
},
|
||||
{
|
||||
statics: [ { name: 'FOOStatic' }, { name: 'barStatic' } ],
|
||||
members: [ { name: 'FOOInstance' }, { name: 'barInstance' } ],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should remove no members by default', () => {
|
||||
const processor = processorFactory();
|
||||
const expectedDocs = [
|
||||
{
|
||||
statics: [
|
||||
{ name: '' },
|
||||
{ name: 'foo' },
|
||||
{ name: '__bar' },
|
||||
{ name: 'ngBazDef' },
|
||||
],
|
||||
members: [
|
||||
{ name: '' },
|
||||
{ name: 'foo' },
|
||||
{ name: '__bar' },
|
||||
{ name: 'ngBazDef' },
|
||||
],
|
||||
},
|
||||
];
|
||||
const actualDocs = JSON.parse(JSON.stringify(expectedDocs));
|
||||
|
||||
processor.$process(actualDocs);
|
||||
|
||||
expect(processor.notAllowedPatterns).toEqual([]);
|
||||
expect(actualDocs).toEqual(expectedDocs);
|
||||
});
|
||||
});
|
@ -96,6 +96,16 @@
|
||||
"ban-keywords",
|
||||
"check-format",
|
||||
"require-const-for-all-caps"
|
||||
]
|
||||
],
|
||||
"template-accessibility-alt-text": true,
|
||||
"template-accessibility-elements-content": true,
|
||||
"template-accessibility-label-for": true,
|
||||
"template-accessibility-tabindex-no-positive": true,
|
||||
"template-accessibility-table-scope": true,
|
||||
"template-accessibility-valid-aria": true,
|
||||
"template-click-events-have-key-events": true,
|
||||
"template-mouse-events-have-key-events": true,
|
||||
"template-no-autofocus": true,
|
||||
"template-no-distracting-elements": true
|
||||
}
|
||||
}
|
||||
|
@ -938,10 +938,10 @@ anymatch@^3.0.1:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
app-root-path@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
|
||||
integrity sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=
|
||||
app-root-path@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a"
|
||||
integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==
|
||||
|
||||
append-transform@^1.0.0:
|
||||
version "1.0.0"
|
||||
@ -2179,12 +2179,12 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codelyzer@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.0.0.tgz#e4032efb23a7c5d4bcfe7321fc1789490c679837"
|
||||
integrity sha512-Bif70XYt8NFf/Q9GPTxmC86OsBRfQZq1dBjdruJ5kZhJ8/jKhJL6MvCLKnYtSOG6Rhiv/44DU0cHk6GYthjy8Q==
|
||||
codelyzer@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.1.1.tgz#a599fa8c2a5847f553a792b934e493d1506a4a62"
|
||||
integrity sha512-t8ZLSZBUjVFOJVk4jASLgmTdKWK/0ZsQCnPXy6PXw1LWOOormQOVnyy4OYoiZ6rAWTrz60Obx+zA2t8xY53QzQ==
|
||||
dependencies:
|
||||
app-root-path "^2.1.0"
|
||||
app-root-path "^2.2.1"
|
||||
aria-query "^3.0.0"
|
||||
axobject-query "^2.0.2"
|
||||
css-selector-tokenizer "^0.7.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "8.2.9",
|
||||
"version": "8.2.10",
|
||||
"private": true,
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
"homepage": "https://github.com/angular/angular",
|
||||
|
@ -372,7 +372,8 @@ def ngc_compile_action(
|
||||
node_opts,
|
||||
locale = None,
|
||||
i18n_args = [],
|
||||
dts_bundles_out = None):
|
||||
dts_bundles_out = None,
|
||||
compile_mode = "prodmode"):
|
||||
"""Helper function to create the ngc action.
|
||||
|
||||
This is exposed for google3 to wire up i18n replay rules, and is not intended
|
||||
@ -397,13 +398,13 @@ def ngc_compile_action(
|
||||
is_legacy_ngc = _is_legacy_ngc(ctx)
|
||||
|
||||
mnemonic = "AngularTemplateCompile"
|
||||
progress_message = "Compiling Angular templates (%s) %s" % (_compiler_name(ctx), label)
|
||||
progress_message = "Compiling Angular templates (%s - %s) %s" % (_compiler_name(ctx), compile_mode, label)
|
||||
|
||||
if locale:
|
||||
mnemonic = "AngularI18NMerging"
|
||||
supports_workers = "0"
|
||||
progress_message = ("Recompiling Angular templates (ngc) %s for locale %s" %
|
||||
(label, locale))
|
||||
progress_message = ("Recompiling Angular templates (ngc - %s) %s for locale %s" %
|
||||
(compile_mode, label, locale))
|
||||
else:
|
||||
supports_workers = str(int(ctx.attr._supports_workers))
|
||||
|
||||
@ -463,7 +464,7 @@ def ngc_compile_action(
|
||||
dts_entry_points.append(_R3_SYMBOLS_DTS_FILE)
|
||||
|
||||
ctx.actions.run(
|
||||
progress_message = "Bundling DTS %s" % str(ctx.label),
|
||||
progress_message = "Bundling DTS (%s) %s" % (compile_mode, str(ctx.label)),
|
||||
mnemonic = "APIExtractor",
|
||||
executable = ctx.executable.api_extractor,
|
||||
inputs = filter_inputs,
|
||||
@ -495,7 +496,15 @@ def _filter_ts_inputs(all_inputs):
|
||||
if f.path.endswith(".js") or f.path.endswith(".ts") or f.path.endswith(".json")
|
||||
]
|
||||
|
||||
def _compile_action(ctx, inputs, outputs, dts_bundles_out, messages_out, tsconfig_file, node_opts):
|
||||
def _compile_action(
|
||||
ctx,
|
||||
inputs,
|
||||
outputs,
|
||||
dts_bundles_out,
|
||||
messages_out,
|
||||
tsconfig_file,
|
||||
node_opts,
|
||||
compile_mode):
|
||||
# Give the Angular compiler all the user-listed assets
|
||||
file_inputs = list(ctx.files.assets)
|
||||
|
||||
@ -533,16 +542,16 @@ def _compile_action(ctx, inputs, outputs, dts_bundles_out, messages_out, tsconfi
|
||||
],
|
||||
)
|
||||
|
||||
return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, tsconfig_file, node_opts, None, [], dts_bundles_out)
|
||||
return ngc_compile_action(ctx, ctx.label, action_inputs, outputs, messages_out, tsconfig_file, node_opts, None, [], dts_bundles_out, compile_mode)
|
||||
|
||||
def _prodmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
|
||||
outs = _expected_outs(ctx)
|
||||
return _compile_action(ctx, inputs, outputs + outs.closure_js, None, outs.i18n_messages, tsconfig_file, node_opts)
|
||||
return _compile_action(ctx, inputs, outputs + outs.closure_js, None, outs.i18n_messages, tsconfig_file, node_opts, "prodmode")
|
||||
|
||||
def _devmode_compile_action(ctx, inputs, outputs, tsconfig_file, node_opts):
|
||||
outs = _expected_outs(ctx)
|
||||
compile_action_outputs = outputs + outs.devmode_js + outs.declarations + outs.summaries + outs.metadata
|
||||
_compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundles, None, tsconfig_file, node_opts)
|
||||
_compile_action(ctx, inputs, compile_action_outputs, outs.dts_bundles, None, tsconfig_file, node_opts, "devmode")
|
||||
|
||||
def _ts_expected_outs(ctx, label, srcs_files = []):
|
||||
# rules_typescript expects a function with two or more arguments, but our
|
||||
|
79
packages/common/upgrade/test/params.spec.ts
Normal file
79
packages/common/upgrade/test/params.spec.ts
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AngularJSUrlCodec} from '../src/params';
|
||||
|
||||
describe('AngularJSUrlCodec', () => {
|
||||
const codec = new AngularJSUrlCodec();
|
||||
|
||||
describe('parse', () => {
|
||||
it('should parse a complex URL', () => {
|
||||
const result = codec.parse('http://server.com:1234/foo?bar=true#heading');
|
||||
expect(result.href).toBe('http://server.com:1234/foo?bar=true#heading');
|
||||
expect(result.protocol).toBe('http');
|
||||
expect(result.host).toBe('server.com:1234');
|
||||
expect(result.search).toBe('bar=true');
|
||||
expect(result.hash).toBe('heading');
|
||||
expect(result.hostname).toBe('server.com');
|
||||
expect(result.port).toBe('1234');
|
||||
expect(result.pathname).toBe('/foo');
|
||||
});
|
||||
|
||||
it('should parse a URL without search', () => {
|
||||
const result = codec.parse('http://server.com:1234/foo#heading');
|
||||
expect(result.href).toBe('http://server.com:1234/foo#heading');
|
||||
expect(result.search).toBe('');
|
||||
expect(result.hash).toBe('heading');
|
||||
expect(result.pathname).toBe('/foo');
|
||||
});
|
||||
|
||||
it('should parse a URL without hash', () => {
|
||||
const result = codec.parse('http://server.com:1234/foo?bar=true');
|
||||
expect(result.href).toBe('http://server.com:1234/foo?bar=true');
|
||||
expect(result.search).toBe('bar=true');
|
||||
expect(result.hash).toBe('');
|
||||
expect(result.pathname).toBe('/foo');
|
||||
});
|
||||
|
||||
it('should parse a basic URL', () => {
|
||||
const result = codec.parse('http://server.com');
|
||||
expect(result.href).toBe('http://server.com/');
|
||||
expect(result.protocol).toBe('http');
|
||||
expect(result.host).toBe('server.com');
|
||||
expect(result.search).toBe('');
|
||||
expect(result.hash).toBe('');
|
||||
expect(result.hostname).toBe('server.com');
|
||||
expect(result.port).toBe('');
|
||||
expect(result.pathname).toBe('/');
|
||||
});
|
||||
|
||||
it('should apply a base', () => {
|
||||
const withoutSlash = codec.parse('foo/bar', 'http://abc.xyz');
|
||||
expect(withoutSlash.href).toBe('http://abc.xyz/foo/bar');
|
||||
const withSlash = codec.parse('/foo/bar', 'http://abc.xyz/');
|
||||
expect(withSlash.href).toBe('http://abc.xyz/foo/bar');
|
||||
});
|
||||
|
||||
it('should ignore an empty base', () => {
|
||||
const result = codec.parse('http://abc.xyz', '');
|
||||
expect(result.href).toBe('http://abc.xyz/');
|
||||
});
|
||||
|
||||
it('should throw an error for an invalid URL', () => {
|
||||
expect(() => {
|
||||
codec.parse('/foo/bar');
|
||||
}).toThrowError('Invalid URL (/foo/bar) with base (undefined)');
|
||||
});
|
||||
|
||||
it('should throw an error for an invalid base', () => {
|
||||
expect(() => {
|
||||
codec.parse('http://foo.bar', 'abc');
|
||||
}).toThrowError('Invalid URL (http://foo.bar) with base (abc)');
|
||||
});
|
||||
});
|
||||
});
|
@ -62,12 +62,8 @@ import {Subject, Subscription} from 'rxjs';
|
||||
* @publicApi
|
||||
*/
|
||||
export class EventEmitter<T extends any> extends Subject<T> {
|
||||
// TODO: mark this as internal once all the facades are gone
|
||||
// we can't mark it as internal now because EventEmitter exported via @angular/core would not
|
||||
// contain this property making it incompatible with all the code that uses EventEmitter via
|
||||
// facades, which are local to the code and do not have this property stripped.
|
||||
/**
|
||||
* Internal
|
||||
* @internal
|
||||
*/
|
||||
__isAsync: boolean; // tslint:disable-line
|
||||
|
||||
|
@ -57,8 +57,38 @@ export const NG_VALIDATORS = new InjectionToken<Array<Validator|Function>>('NgVa
|
||||
export const NG_ASYNC_VALIDATORS =
|
||||
new InjectionToken<Array<Validator|Function>>('NgAsyncValidators');
|
||||
|
||||
/**
|
||||
* A regular expression that matches valid e-mail addresses.
|
||||
*
|
||||
* At a high level, this regexp matches e-mail addresses of the format `local-part@tld`, where:
|
||||
* - `local-part` consists of one or more of the allowed characters (alphanumeric and some
|
||||
* punctuation symbols).
|
||||
* - `local-part` cannot begin or end with a period (`.`).
|
||||
* - `local-part` cannot be longer than 64 characters.
|
||||
* - `tld` consists of one or more `labels` separated by periods (`.`). For example `localhost` or
|
||||
* `foo.com`.
|
||||
* - A `label` consists of one or more of the allowed characters (alphanumeric, dashes (`-`) and
|
||||
* periods (`.`)).
|
||||
* - A `label` cannot begin or end with a dash (`-`) or a period (`.`).
|
||||
* - A `label` cannot be longer than 63 characters.
|
||||
* - The whole address cannot be longer than 254 characters.
|
||||
*
|
||||
* ## Implementation background
|
||||
*
|
||||
* This regexp was ported over from AngularJS (see there for git history):
|
||||
* https://github.com/angular/angular.js/blob/c133ef836/src/ng/directive/input.js#L27
|
||||
* It is based on the
|
||||
* [WHATWG version](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with
|
||||
* some enhancements to incorporate more RFC rules (such as rules related to domain names and the
|
||||
* lengths of different parts of the address). The main differences from the WHATWG version are:
|
||||
* - Disallow `local-part` to begin or end with a period (`.`).
|
||||
* - Disallow `local-part` length to exceed 64 characters.
|
||||
* - Disallow total address length to exceed 254 characters.
|
||||
*
|
||||
* See [this commit](https://github.com/angular/angular.js/commit/f3f5cf72e) for more details.
|
||||
*/
|
||||
const EMAIL_REGEXP =
|
||||
/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
|
||||
/^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
|
||||
/**
|
||||
* @description
|
||||
@ -191,6 +221,20 @@ export class Validators {
|
||||
* @description
|
||||
* Validator that requires the control's value pass an email validation test.
|
||||
*
|
||||
* Tests the value using a [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
|
||||
* pattern suitable for common usecases. The pattern is based on the definition of a valid email
|
||||
* address in the [WHATWG HTML specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address)
|
||||
* with some enhancements to incorporate more RFC rules (such as rules related to domain names and
|
||||
* the lengths of different parts of the address).
|
||||
*
|
||||
* The differences from the WHATWG version include:
|
||||
* - Disallow `local-part` (the part before the `@` symbol) to begin or end with a period (`.`).
|
||||
* - Disallow `local-part` to be longer than 64 characters.
|
||||
* - Disallow the whole address to be longer than 254 characters.
|
||||
*
|
||||
* If this pattern does not satisfy your business needs, you can use `Validators.pattern()` to
|
||||
* validate the value against a different pattern.
|
||||
*
|
||||
* @usageNotes
|
||||
*
|
||||
* ### Validate that the field matches a valid email pattern
|
||||
|
70
scripts/local-dev/setup-rbe.sh
Executable file
70
scripts/local-dev/setup-rbe.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# A script for automatically configuring a user's local dev
|
||||
# environment to use Remote Build Execution.
|
||||
|
||||
# Determine the root directory of the Angular github repo.
|
||||
project_directory=$(git rev-parse --show-toplevel 2> /dev/null);
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "This command must be run from within the cloned \"angular/angular\" repository.";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Confirm gcloud installed and available as a command.
|
||||
if [ ! -x "$(command -v gcloud)" ]; then
|
||||
echo "gcloud command is not available. Please install gcloud before continuing.";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Confirm the parameter provided to the script is a directory
|
||||
if [[ ! -d $1 ]]; then
|
||||
echo -e "Invalid command syntax.
|
||||
|
||||
\e[1mUsage:\e[0m $0 <ServiceAccountKeyLocation>
|
||||
|
||||
\e[1mExample:\e[0m ./setup-rbe ~/my_key_storage_directory/
|
||||
|
||||
The directory provided will be used to store the GCP service account key
|
||||
for the angular-local-dev service account. This key will then be used to
|
||||
authenticate for usage of the Remote Build Execution system and Remote Caching.
|
||||
";
|
||||
exit 1;
|
||||
fi
|
||||
credentials_directory=$(readlink -f $1)
|
||||
if [[ ! -d $credentials_directory ]]; then
|
||||
echo "The specified directory does not exist. Please create the directory and rerun.";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Create the service account key in the provided directory.
|
||||
echo "Checking provided directory for a service account key.";
|
||||
json_key_filepath="$credentials_directory/angular-local-dev-key.json";
|
||||
if [[ -f $json_key_filepath ]]; then
|
||||
echo "Angular Local Dev key already exists, reusing this key.";
|
||||
else
|
||||
# Confirm the user is already logged into gcloud, if they aren't
|
||||
# attempt to login
|
||||
echo "Checking gcloud login state.";
|
||||
gcloud auth print-identity-token &> /dev/null;
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Not currently logged into gcloud. Starting gcloud login now.";
|
||||
gcloud auth login;
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "gcloud login failed. Aborting.";
|
||||
exit 2;
|
||||
fi
|
||||
fi
|
||||
gcloud iam service-accounts keys create $json_key_filepath \
|
||||
--iam-account angular-local-dev@internal-200822.iam.gserviceaccount.com \
|
||||
--quiet --project internal-200822;
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Downloading service account key failed. Aborting.";
|
||||
exit 2;
|
||||
fi
|
||||
fi
|
||||
|
||||
# The full path to the .bazelrc.user file
|
||||
bazelrc_user_filepath="$project_directory/.bazelrc.user";
|
||||
# Create the bazelrc.user file, echo the config flags into the file.
|
||||
touch $bazelrc_user_filepath;
|
||||
echo "build --config=remote-http-caching" >> $bazelrc_user_filepath;
|
||||
echo "build --google_credentials=$json_key_filepath" >> $bazelrc_user_filepath;
|
1
tools/public_api_guard/core/core.d.ts
vendored
1
tools/public_api_guard/core/core.d.ts
vendored
@ -326,7 +326,6 @@ export declare class ErrorHandler {
|
||||
}
|
||||
|
||||
export declare class EventEmitter<T extends any> extends Subject<T> {
|
||||
__isAsync: boolean;
|
||||
constructor(isAsync?: boolean);
|
||||
emit(value?: T): void;
|
||||
subscribe(generatorOrNext?: any, error?: any, complete?: any): Subscription;
|
||||
|
Reference in New Issue
Block a user