Compare commits
157 Commits
7.0.2
...
mhevery-pa
Author | SHA1 | Date | |
---|---|---|---|
dce1c7cf58 | |||
2c7386c961 | |||
d5cbcef0ea | |||
b0476f308b | |||
9dc52d9d04 | |||
297dc2bc02 | |||
0cc9842bf6 | |||
54ea10288e | |||
1880c9531f | |||
13a803d4f7 | |||
f6c2db818e | |||
67789f10ef | |||
b83f1300bd | |||
6e16a17015 | |||
d744dd70e0 | |||
4e91ead40b | |||
7f39f37003 | |||
bf9ab53f12 | |||
d99f661af7 | |||
5d58a31d86 | |||
07b89902d5 | |||
ce6948fc1b | |||
38d626a3fa | |||
9b8a244a15 | |||
1bbf28ad19 | |||
3b24e0edb6 | |||
b647608c96 | |||
31c462ae3f | |||
da39fd70d2 | |||
ee0b857172 | |||
e0d6782d26 | |||
2f9e957523 | |||
38dbae9ca0 | |||
5a3077f46c | |||
d0cc019c1a | |||
26e8032bd0 | |||
84af7b065d | |||
83dc3c0ee0 | |||
5952775a03 | |||
57531737e5 | |||
3fd50f07fd | |||
4237c34c78 | |||
361eaf1888 | |||
cca89ec36e | |||
e4c7f369f2 | |||
d573a14119 | |||
ff767dd153 | |||
34c6ce6b08 | |||
6737e91974 | |||
1006eab482 | |||
a9f2952882 | |||
100c7eff25 | |||
dc7349915d | |||
213c25fb08 | |||
615a515bba | |||
838a3f204f | |||
15c2467dbd | |||
74ea4e9b5d | |||
4481571999 | |||
2132c8f461 | |||
2b3cac5b31 | |||
8d5e3e6981 | |||
30f1dc002a | |||
5da3b00222 | |||
631998b2df | |||
30d6233e83 | |||
6468711e16 | |||
d698b0eadf | |||
1f3331f5e6 | |||
b6c9678f21 | |||
4c2ce4e8ba | |||
bb0f95b6fb | |||
853faf4c71 | |||
00c7db02d1 | |||
13143b850e | |||
c1724062f1 | |||
7570f7222f | |||
f1e3d5125d | |||
3511f08a81 | |||
982bc7f2aa | |||
3903e5ebe7 | |||
0918adf39d | |||
42c331bbf2 | |||
0bae97a726 | |||
c5949f85ef | |||
24521f549c | |||
4bd9f53e8f | |||
2a78dcbd5a | |||
2ea57cdcc3 | |||
31022cbecf | |||
ce8053103e | |||
0b885ecaf7 | |||
1700bd6f08 | |||
b89bc37170 | |||
39df4dbde7 | |||
716d887e51 | |||
5b4cf38166 | |||
4c0ad5238e | |||
9e8903ada1 | |||
aa55d88408 | |||
07fc4c2464 | |||
b9bd95b3b2 | |||
3f89aeb80a | |||
6c530d3a85 | |||
03bf0d6b41 | |||
d4cee514f6 | |||
331989cea3 | |||
bbf96db2f2 | |||
72c2578d14 | |||
1a666dea61 | |||
7634c1cb31 | |||
95914a0fbf | |||
9c50891d6e | |||
624433c51d | |||
09cc458bfc | |||
efe0c5f371 | |||
d9d226087c | |||
7bad1d356d | |||
0add00a743 | |||
d557f1d9de | |||
665627e254 | |||
a609bf50ed | |||
f8195e5e3d | |||
65b209359a | |||
3a65c9ad4e | |||
77e58c6179 | |||
23d625172a | |||
c3643615fc | |||
638aaecc7d | |||
5a79decba4 | |||
225162aa6c | |||
a43b80a4c9 | |||
beebf7fe14 | |||
0ef1f7ef0d | |||
fc6dad40ac | |||
ecd473bbce | |||
8a3fd58cad | |||
8024857d4c | |||
3fa876c5e7 | |||
516515d9e3 | |||
948f507ba0 | |||
81a8ee1ddb | |||
5e58da14f0 | |||
fa8e633be5 | |||
be337a2e52 | |||
4d164b6ca4 | |||
371ffef4ce | |||
fdfedceeec | |||
9e5d440a0b | |||
0f7d2ca7a8 | |||
81c9720acb | |||
ea2cfbbd2e | |||
2326b9c294 | |||
41de0e0d98 | |||
f6a2dbf4f5 | |||
b115374601 | |||
7d82053117 |
@ -13,7 +13,7 @@ a GitHub token that enables publishing snapshots.
|
||||
|
||||
To create the github_token file, we take this approach:
|
||||
- Find the angular-builds:token in http://valentine
|
||||
- Go inside the CircleCI default docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it circleci/node:10.12`
|
||||
- Go inside the ngcontainer docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it angular/ngcontainer`
|
||||
- echo "https://[token]:@github.com" > credentials
|
||||
- openssl aes-256-cbc -e -in credentials -out .circleci/github_token -k $KEY
|
||||
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
|
@ -7,20 +7,40 @@
|
||||
# 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**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
var_1: &default_docker_image circleci/node:10.12
|
||||
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
||||
var_3: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-node-10.12
|
||||
# Variables
|
||||
|
||||
## IMPORTANT
|
||||
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
||||
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
||||
var_1: &docker_image angular/ngcontainer:0.7.0
|
||||
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.7.0
|
||||
|
||||
# Define common ENV vars
|
||||
var_4: &define_env_vars
|
||||
var_3: &define_env_vars
|
||||
run:
|
||||
name: Define environment variables
|
||||
command: ./.circleci/env.sh
|
||||
command: |
|
||||
echo "export PROJECT_ROOT=$(pwd)" | tee -a $BASH_ENV
|
||||
echo "export CI_AIO_MIN_PWA_SCORE=95" | tee -a $BASH_ENV
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
echo "export CI_BRANCH=$CIRCLE_BRANCH" | tee -a $BASH_ENV
|
||||
echo "export CI_COMMIT=$CIRCLE_SHA1" | tee -a $BASH_ENV
|
||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available,
|
||||
# i.e. on push builds (a.k.a. non-PR builds). That is fine, since we only need it in push builds.
|
||||
echo "export CI_COMMIT_RANGE=$(sed -r 's|^.*/([0-9a-f]+\.\.\.[0-9a-f]+)$|\1|i' <<< ${CIRCLE_COMPARE_URL:-})" | tee -a $BASH_ENV
|
||||
echo "export CI_PULL_REQUEST=${CIRCLE_PR_NUMBER:-false}" | tee -a $BASH_ENV
|
||||
echo "export CI_REPO_NAME=$CIRCLE_PROJECT_REPONAME" | tee -a $BASH_ENV
|
||||
echo "export CI_REPO_OWNER=$CIRCLE_PROJECT_USERNAME" | tee -a $BASH_ENV
|
||||
# WARNING: Secrets (do not print).
|
||||
echo "export CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN=$AIO_DEPLOY_TOKEN" >> $BASH_ENV
|
||||
echo "export CI_SECRET_PAYLOAD_FIREBASE_TOKEN=$ANGULAR_PAYLOAD_TOKEN" >> $BASH_ENV
|
||||
|
||||
# See remote cache documentation in /docs/BAZEL.md
|
||||
var_4: &setup-bazel-remote-cache
|
||||
run:
|
||||
name: Start up bazel remote cache proxy
|
||||
command: ~/bazel-remote-proxy -backend circleci://
|
||||
background: true
|
||||
|
||||
var_5: &setup_bazel_remote_execution
|
||||
run:
|
||||
@ -28,73 +48,59 @@ var_5: &setup_bazel_remote_execution
|
||||
command: openssl aes-256-cbc -d -in .circleci/gcp_token -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials && echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV && sudo bash -c "cat .circleci/rbe-bazel.rc >> /etc/bazel.bazelrc"
|
||||
|
||||
# Settings common to each job
|
||||
var_6: &job_defaults
|
||||
anchor_1: &job_defaults
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: *default_docker_image
|
||||
|
||||
var_7: &start-xvfb
|
||||
run:
|
||||
name: Running X virtual framebuffer
|
||||
command: Xvfb :99 -screen 0 1280x1024x24
|
||||
background: true
|
||||
- image: *docker_image
|
||||
|
||||
# After checkout, rebase on top of master.
|
||||
# Similar to travis behavior, but not quite the same.
|
||||
# See https://discuss.circleci.com/t/1662
|
||||
var_8: &post_checkout
|
||||
anchor_2: &post_checkout
|
||||
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
||||
|
||||
var_9: &yarn_install
|
||||
run:
|
||||
name: Running Yarn install
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
|
||||
var_10: &setup_circleci_bazel_config
|
||||
run:
|
||||
name: Setting up CircleCI bazel configuration
|
||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
lint:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
# Check BUILD.bazel formatting before we have a node_modules directory
|
||||
# Then we don't need any exclude pattern to avoid checking those files
|
||||
- run: 'yarn buildifier -mode=check ||
|
||||
(echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
|
||||
# Run the skylark linter to check our Bazel rules
|
||||
- run: 'yarn skylint ||
|
||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)'
|
||||
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- run: ./node_modules/.bin/gulp lint
|
||||
|
||||
test:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
- run: bazel info release
|
||||
- run: bazel run @nodejs//:yarn
|
||||
# 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,-local
|
||||
- run: bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-local
|
||||
# Now run RBE incompatible tests locally.
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||
- run: bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||
|
||||
# CircleCI will allow us to go back and view/download these artifacts from past builds.
|
||||
# Also we can use a service like https://buildsize.org/ to automatically track binary size of these artifacts.
|
||||
@ -126,115 +132,90 @@ jobs:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
# don't run this job on the patch branch (to preserve resources)
|
||||
- run: circleci step halt
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- *setup_bazel_remote_execution
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
- run: yarn test-ivy-jit //...
|
||||
- run: bazel run @yarn//:yarn
|
||||
- *setup_bazel_remote_execution
|
||||
- run: bazel test //... --define=compile=jit --build_tag_filters=ivy-jit --test_tag_filters=ivy-jit
|
||||
|
||||
test_ivy_aot:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
# don't run this job on the patch branch (to preserve resources)
|
||||
- run: circleci step halt
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
- run: bazel run @yarn//:yarn
|
||||
- *setup_bazel_remote_execution
|
||||
- run: bazel test //... --define=compile=aot --build_tag_filters=ivy-aot --test_tag_filters=ivy-aot
|
||||
|
||||
- run: yarn test-ivy-aot //...
|
||||
|
||||
test_aio:
|
||||
test_and_deploy_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
# Build aio
|
||||
- run: yarn --cwd aio build --progress=false
|
||||
# Lint the code
|
||||
- run: yarn --cwd aio lint
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Run PWA-score tests
|
||||
command: xvfb-run --auto-servernum yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio payload-size
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio test --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio e2e
|
||||
# Run unit tests for Firebase redirects
|
||||
- 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
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
# Deploy angular.io to production (if necessary)
|
||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||
- run: yarn --cwd aio deploy-production
|
||||
- run: echo "export CI_STABLE_BRANCH=$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')" | tee -a $BASH_ENV
|
||||
- run: xvfb-run --auto-servernum 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
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
# Build aio (with local Angular packages)
|
||||
- run: yarn --cwd aio build-local --progress=false
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Run PWA-score tests
|
||||
command: xvfb-run --auto-servernum yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio test --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio e2e
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
# Install
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd aio extract-cli-command-docs
|
||||
@ -244,45 +225,37 @@ jobs:
|
||||
|
||||
test_docs_examples_0:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
# Install root
|
||||
- *yarn_install
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=0/2
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio example-e2e --setup --local --shard=0/2
|
||||
|
||||
test_docs_examples_1:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
# Install root
|
||||
- *yarn_install
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=1/2
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio example-e2e --setup --local --shard=1/2
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
@ -290,12 +263,12 @@ jobs:
|
||||
environment:
|
||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *yarn_install
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||
- store_artifacts:
|
||||
path: *aio_preview_artifact_path
|
||||
@ -306,20 +279,16 @@ 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
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- run: yarn install --cwd aio --frozen-lockfile --non-interactive
|
||||
- run:
|
||||
name: Wait for preview and run tests
|
||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
command: xvfb-run --auto-servernum node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
# This job exists only for backwards-compatibility with old scripts and tests
|
||||
# that rely on the pre-Bazel dist/packages-dist layout.
|
||||
@ -332,15 +301,12 @@ jobs:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- run: bazel run @nodejs//:yarn
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
@ -360,31 +326,23 @@ jobs:
|
||||
# See comments inside the integration/run_tests.sh script.
|
||||
integration_test:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# 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
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- run: ./integration/run_tests.sh
|
||||
- run: xvfb-run --auto-servernum ./integration/run_tests.sh
|
||||
|
||||
# This job updates the content of repos like github.com/angular/core-builds
|
||||
# for every green build on angular/angular.
|
||||
publish_snapshot:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *define_env_vars
|
||||
# See below - ideally this job should not trigger for non-upstream builds.
|
||||
# But since it does, we have to check this condition.
|
||||
@ -396,6 +354,8 @@ jobs:
|
||||
|| "$CI_REPO_OWNER" != "angular"
|
||||
|| "$CI_REPO_NAME" != "angular"
|
||||
]] && circleci step halt || true'
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
# CircleCI has a config setting to force SSH for all github connections
|
||||
@ -409,24 +369,15 @@ jobs:
|
||||
|
||||
aio_monitoring:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||
# which does not load the browser through the Bazel webtesting rules.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- run:
|
||||
name: Run tests against the deployed apps
|
||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Notify caretaker about failure
|
||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL'
|
||||
when: on_fail
|
||||
command: xvfb-run --auto-servernum ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@ -437,10 +388,7 @@ workflows:
|
||||
- test_ivy_jit
|
||||
- test_ivy_aot
|
||||
- build-packages-dist
|
||||
- test_aio
|
||||
- deploy_aio:
|
||||
requires:
|
||||
- test_aio
|
||||
- test_and_deploy_aio
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
|
@ -1,38 +0,0 @@
|
||||
####################################################################################################
|
||||
# Helpers for defining environment variables for CircleCI.
|
||||
#
|
||||
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
|
||||
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
|
||||
# the default `bash` shell).
|
||||
#
|
||||
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
|
||||
####################################################################################################
|
||||
|
||||
# Set and print an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
|
||||
# visible to anyone through the CI logs.
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 $2;
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
# Set (without printing) an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are secret, i.e. should not be visible to
|
||||
# everyone through the CI logs.
|
||||
#
|
||||
# Usage: `setSecretVar <name> <value>`
|
||||
function setSecretVar() {
|
||||
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
|
||||
# (Keep original shell options to restore at the end.)
|
||||
local -r originalShellOptions=$(set +o);
|
||||
set +x -eu -o pipefail;
|
||||
|
||||
echo "export $1=\"${2:-}\";" >> $BASH_ENV;
|
||||
|
||||
# Restore original shell options.
|
||||
eval "$originalShellOptions";
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
readonly envHelpersPath="`dirname $0`/env-helpers.inc.sh";
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar PROJECT_ROOT "$(pwd)";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available,
|
||||
# i.e. on push builds (a.k.a. non-PR builds). That is fine, since we only need it in push builds.
|
||||
setPublicVar CI_COMMIT_RANGE "$(sed -r 's|^.*/([0-9a-f]+\.\.\.[0-9a-f]+)$|\1|i' <<< ${CIRCLE_COMPARE_URL:-})";
|
||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SECRET environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
# Defined in https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
setSecretVar CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL "$SLACK_CARETAKER_WEBHOOK_URL";
|
||||
|
||||
|
||||
# Source `$BASH_ENV` to make the variables available immediately.
|
||||
source $BASH_ENV;
|
@ -8,6 +8,13 @@ exports_files([
|
||||
"protractor-perf.conf.js",
|
||||
])
|
||||
|
||||
# Developers should always run `bazel run :install`
|
||||
# This ensures that package.json in subdirectories get installed as well.
|
||||
alias(
|
||||
name = "install",
|
||||
actual = "@nodejs//:yarn",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "web_test_bootstrap_scripts",
|
||||
# do not sort
|
||||
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,12 +1,18 @@
|
||||
<a name="7.0.2"></a>
|
||||
## [7.0.2](https://github.com/angular/angular/compare/7.0.1...7.0.2) (2018-10-31)
|
||||
<a name="7.1.0-beta.0"></a>
|
||||
# [7.1.0-beta.0](https://github.com/angular/angular/compare/7.0.0-rc.1...7.1.0-beta.0) (2018-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** generate relative paths only in summary file errors ([#26759](https://github.com/angular/angular/issues/26759)) ([c01f340](https://github.com/angular/angular/commit/c01f340))
|
||||
* **core:** Remove static dependency from [@angular](https://github.com/angular)/core to [@angular](https://github.com/angular)/compiler ([#26734](https://github.com/angular/angular/issues/26734)) ([#26879](https://github.com/angular/angular/issues/26879)) ([257ac83](https://github.com/angular/angular/commit/257ac83))
|
||||
* **core:** support computed base class in metadata inheritance ([#24014](https://github.com/angular/angular/issues/24014)) ([b3c6409](https://github.com/angular/angular/commit/b3c6409))
|
||||
* **core:** allow null value for renderer setElement(…) ([#17065](https://github.com/angular/angular/issues/17065)) ([ff15043](https://github.com/angular/angular/commit/ff15043)), closes [#13686](https://github.com/angular/angular/issues/13686)
|
||||
* **router:** fix regression where navigateByUrl promise didn't resolve on CanLoad failure ([#26455](https://github.com/angular/angular/issues/26455)) ([1c9b065](https://github.com/angular/angular/commit/1c9b065)), closes [#26284](https://github.com/angular/angular/issues/26284)
|
||||
* **service-worker:** clean up caches from old SW versions ([#26319](https://github.com/angular/angular/issues/26319)) ([2326b9c](https://github.com/angular/angular/commit/2326b9c))
|
||||
* **upgrade:** properly destroy upgraded component elements and descendants ([#26209](https://github.com/angular/angular/issues/26209)) ([071934e](https://github.com/angular/angular/commit/071934e)), closes [#26208](https://github.com/angular/angular/issues/26208)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **router:** add prioritizedGuardValue operator optimization and allowing UrlTree return from guard ([#26478](https://github.com/angular/angular/issues/26478)) ([fdfedce](https://github.com/angular/angular/commit/fdfedce))
|
||||
|
||||
|
||||
|
||||
@ -91,6 +97,7 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
||||
### Bug Fixes
|
||||
|
||||
* **platform-browser:** fix [#22155](https://github.com/angular/angular/issues/22155), destroy hammer manager when `HammerInstance.off()` is run ([#22156](https://github.com/angular/angular/issues/22156)) ([3b4d9dc](https://github.com/angular/angular/commit/3b4d9dc))
|
||||
* **upgrade:** properly destroy upgraded component elements and descendants ([#26209](https://github.com/angular/angular/issues/26209)) ([623adbb](https://github.com/angular/angular/commit/623adbb)), closes [#26208](https://github.com/angular/angular/issues/26208)
|
||||
|
||||
|
||||
|
||||
|
10
WORKSPACE
10
WORKSPACE
@ -6,16 +6,6 @@ load(
|
||||
"rules_angular_dev_dependencies",
|
||||
)
|
||||
|
||||
# Uncomment for local bazel rules development
|
||||
#local_repository(
|
||||
# name = "build_bazel_rules_nodejs",
|
||||
# path = "../rules_nodejs",
|
||||
#)
|
||||
#local_repository(
|
||||
# name = "build_bazel_rules_typescript",
|
||||
# path = "../rules_typescript",
|
||||
#)
|
||||
|
||||
# Angular Bazel users will call this function
|
||||
rules_angular_dependencies()
|
||||
# These are the dependencies only for us
|
||||
|
@ -49,6 +49,8 @@ You can edit the generated files directly, or add to and modify them using CLI c
|
||||
Use the [ng generate](cli/generate) command to add new files for additional components and services, and code for new pipes, directives, and so on.
|
||||
Commands such as [add](cli/add) and [generate](cli/generate), which create or operate on apps and libraries, must be executed from within a workspace or project folder.
|
||||
|
||||
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
||||
|
||||
* See more about the [Workspace file structure](guide/file-structure).
|
||||
|
||||
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
||||
|
@ -12,7 +12,7 @@ h2, h3 {
|
||||
body {
|
||||
margin: 2em;
|
||||
}
|
||||
body, input[type="text"], button {
|
||||
body, input[text], button {
|
||||
color: #888;
|
||||
font-family: Cambria, Georgia;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ export class HeroService {
|
||||
// #enddocregion getHeroes-1
|
||||
.pipe(
|
||||
// #enddocregion getHeroes-2
|
||||
tap(_ => this.log('fetched heroes')),
|
||||
tap(heroes => this.log('fetched heroes')),
|
||||
// #docregion getHeroes-2
|
||||
catchError(this.handleError('getHeroes', []))
|
||||
);
|
||||
|
@ -1,19 +1,19 @@
|
||||
# Deployment
|
||||
|
||||
When you are ready to deploy your Angular application to a remote server, you have various options for
|
||||
deployment.
|
||||
deployment.
|
||||
|
||||
{@a dev-deploy}
|
||||
{@a copy-files}
|
||||
|
||||
## Simplest deployment possible
|
||||
|
||||
For the simplest deployment, create a production build and copy the output directory to a web server.
|
||||
For the simplest deployment, build for development and copy the output directory to a web server.
|
||||
|
||||
1. Start with the production build:
|
||||
1. Start with the development build:
|
||||
|
||||
<code-example language="none" class="code-shell">
|
||||
ng build --prod
|
||||
ng build
|
||||
</code-example>
|
||||
|
||||
|
||||
@ -22,7 +22,8 @@ For the simplest deployment, create a production build and copy the output direc
|
||||
3. Configure the server to redirect requests for missing files to `index.html`.
|
||||
Learn more about server-side redirects [below](#fallback).
|
||||
|
||||
This is the simplest production-ready deployment of your application.
|
||||
This is _not_ a production deployment. It's not optimized, and it won't be fast for users.
|
||||
It might be good enough for sharing your progress and ideas internally with managers, teammates, and other stakeholders. For the next steps in deployment, see [Optimize for production](#optimize).
|
||||
|
||||
{@a deploy-to-github}
|
||||
|
||||
@ -30,7 +31,7 @@ This is the simplest production-ready deployment of your application.
|
||||
|
||||
Another simple way to deploy your Angular app is to use [GitHub Pages](https://help.github.com/articles/what-is-github-pages/).
|
||||
|
||||
1. You need to [create a GitHub account](https://github.com/join) if you don't have one, and then [create a repository](https://help.github.com/articles/create-a-repo/) for your project.
|
||||
1. You need to [create a GitHub account](https://github.com/join) if you don't have one, and then [create a repository](https://help.github.com/articles/create-a-repo/) for your project.
|
||||
Make a note of the user name and project name in GitHub.
|
||||
|
||||
1. Build your project using Github project name, with the Angular CLI command [`ng build`](cli/build) and the options shown here:
|
||||
@ -38,9 +39,9 @@ Make a note of the user name and project name in GitHub.
|
||||
ng build --prod --output-path docs --base-href <project_name>
|
||||
</code-example>
|
||||
|
||||
1. When the build is complete, make a copy of `docs/index.html` and name it `docs/404.html`.
|
||||
1. When the build is complete, make a copy of `docs/index.html` and name it `docs/404.html`.
|
||||
|
||||
1. Commit your changes and push.
|
||||
1. Commit your changes and push.
|
||||
|
||||
1. On the GitHub project page, configure it to [publish from the docs folder](https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#publishing-your-github-pages-site-from-a-docs-folder-on-your-master-branch).
|
||||
|
||||
@ -96,6 +97,51 @@ There is no single configuration that works for every server.
|
||||
The following sections describe configurations for some of the most popular servers.
|
||||
The list is by no means exhaustive, but should provide you with a good starting point.
|
||||
|
||||
#### Development servers
|
||||
|
||||
During development, the [`ng serve`](cli/serve) CLI command lets you run your app in a local browser.
|
||||
The CLI recompiles the application each time you save a file,
|
||||
and reloads the browser with the newly compiled application.
|
||||
|
||||
The app is hosted in local memory and served on `http://localhost:4200/`, using [webpack-dev-server](https://webpack.js.org/guides/development/#webpack-dev-server).
|
||||
|
||||
{@a serve-from-disk}
|
||||
|
||||
Later in development, you might want a closer approximation of how your app will behave when deployed.
|
||||
You can output your distribution folder (`dist`) to disk, but you need to install a different web server.
|
||||
Try installing [lite-server](https://github.com/johnpapa/lite-server); like `webpack-dev-server`, it can automatically reload your browser when you write new files.
|
||||
|
||||
To get the live-reload experience, you will need to run two terminals.
|
||||
The first runs the build in a watch mode and compiles the application to the `dist` folder.
|
||||
The second runs the web server against the `dist` folder.
|
||||
The combination of these two processes provides the same behavior as `ng serve`.
|
||||
|
||||
1. Start the build in terminal A:
|
||||
<code-example language="none" class="code-shell">
|
||||
ng build --watch
|
||||
</code-example>
|
||||
|
||||
1. Start the web server in terminal B:
|
||||
<code-example language="none" class="code-shell">
|
||||
lite-server --baseDir="dist"
|
||||
</code-example>
|
||||
The default browser opens to the appropriate URL.
|
||||
|
||||
* [Lite-Server](https://github.com/johnpapa/lite-server): the default dev server installed with the
|
||||
[Quickstart repo](https://github.com/angular/quickstart) is pre-configured to fallback to `index.html`.
|
||||
|
||||
* [Webpack-Dev-Server](https://github.com/webpack/webpack-dev-server): setup the
|
||||
`historyApiFallback` entry in the dev server options as follows:
|
||||
|
||||
<code-example>
|
||||
historyApiFallback: {
|
||||
disableDotRule: true,
|
||||
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
|
||||
}
|
||||
</code-example>
|
||||
|
||||
#### Production servers
|
||||
|
||||
* [Apache](https://httpd.apache.org/): add a
|
||||
[rewrite rule](http://httpd.apache.org/docs/current/mod/mod_rewrite.html) to the `.htaccess` file as shown
|
||||
(https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/):
|
||||
@ -184,9 +230,19 @@ Read about how to enable CORS for specific servers at
|
||||
|
||||
{@a optimize}
|
||||
|
||||
## Production optimizations
|
||||
## Optimize for production
|
||||
|
||||
The `--prod` _meta-flag_ engages the following build optimization features.
|
||||
Although deploying directly from the development environment works,
|
||||
you can generate an optimized build with additional CLI command line flags,
|
||||
starting with `--prod`.
|
||||
|
||||
### Build with _--prod_
|
||||
|
||||
<code-example language="none" class="code-shell">
|
||||
ng build --prod
|
||||
</code-example>
|
||||
|
||||
The `--prod` _meta-flag_ engages the following optimization features.
|
||||
|
||||
* [Ahead-of-Time (AOT) Compilation](guide/aot-compiler): pre-compiles Angular component templates.
|
||||
* [Production mode](#enable-prod-mode): deploys the production environment which enables _production mode_.
|
||||
@ -195,22 +251,25 @@ The `--prod` _meta-flag_ engages the following build optimization features.
|
||||
* Uglification: rewrites code to use short, cryptic variable and function names.
|
||||
* Dead code elimination: removes unreferenced modules and much unused code.
|
||||
|
||||
See [`ng build`](cli/build) for more about CLI build options and what they do.
|
||||
The remaining [copy deployment steps](#copy-files) are the same as before.
|
||||
|
||||
See [`ng build`](cli/build) for more about CLI build options and what they do.
|
||||
|
||||
{@a enable-prod-mode}
|
||||
|
||||
### Enable runtime production mode
|
||||
### Enable production mode
|
||||
|
||||
In addition to build optimizations, Angular also has a runtime production mode. Angular apps run in development mode by default, as you can see by the following message on the browser console:
|
||||
Angular apps run in development mode by default, as you can see by the following message on the browser
|
||||
console:
|
||||
|
||||
<code-example format="nocode">
|
||||
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
|
||||
</code-example>
|
||||
|
||||
Switching to _production mode_ makes it run faster by disabling development specific checks such as the dual change detection cycles.
|
||||
Switching to _production mode_ can make it run faster by disabling development specific checks such as the dual change detection cycles.
|
||||
|
||||
When you enable production builds via `--prod` command line flag, the runtime production mode is enabled as well.
|
||||
Building for production (or appending the `--environment=prod` flag) enables _production mode_
|
||||
Look at the CLI-generated `main.ts` to see how this works.
|
||||
|
||||
{@a lazy-loading}
|
||||
|
||||
@ -234,7 +293,7 @@ If you do that, the module will be loaded immediately.
|
||||
|
||||
The bundling configuration must take lazy loading into consideration.
|
||||
Because lazy-loaded modules aren't imported in JavaScript, bundlers exclude them by default.
|
||||
Bundlers don't know about the router configuration and can't create separate bundles for lazy-loaded modules.
|
||||
Bundlers don't know about the router configuration and can't create separate bundles for lazy-loaded modules.
|
||||
You would have to create these bundles manually.
|
||||
|
||||
The CLI runs the
|
||||
@ -329,7 +388,7 @@ for the missing files. Look at where it _tried_ to find those files and adjust t
|
||||
|
||||
## Building and serving for deployment
|
||||
|
||||
When you are designing and developing applications, you typically use `ng serve` to build your app for fast, local, iterative development.
|
||||
When you are designing and developing applications, you typically use `ng serve` to build your app for fast, local, iterative development.
|
||||
When you are ready to deploy, however, you must use the `ng build` command to build the app and deploy the build artifacts elsewhere.
|
||||
|
||||
Both `ng build` and `ng serve` clear the output folder before they build the project, but only the `ng build` command writes the generated build artifacts to the output folder.
|
||||
@ -342,12 +401,12 @@ To output to a different folder, change the `outputPath` in `angular.json`.
|
||||
</div>
|
||||
|
||||
The `ng serve` command builds, watches, and serves the application from local memory, using a local development server.
|
||||
When you have deployed your app to another server, however, you might still want to serve the app so that you can continue to see changes that you make in it.
|
||||
When you have deployed your app to another server, however, you might still want to serve the app so that you can continue to see changes that you make in it.
|
||||
You can do this by adding the `--watch` option to the `ng build` command.
|
||||
|
||||
```
|
||||
ng build --watch
|
||||
```
|
||||
Like the `ng serve` command, this regenerates output files when source files change.
|
||||
Like the `ng serve` command, this regenerates output files when source files change.
|
||||
|
||||
For complete details of the CLI commands, see the [CLI command reference](cli).
|
||||
|
@ -98,7 +98,7 @@ When the CLI generated the `CustomerDashboardComponent` for the feature module,
|
||||
</code-example>
|
||||
|
||||
|
||||
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the `declarations` array, add an `exports` array containing `CustomerDashboardComponent`:
|
||||
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the `declarations` array, add an `exports` array containing `CustomerDashboardModule`:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="component-exports" header="src/app/customer-dashboard/customer-dashboard.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
@ -672,7 +672,7 @@ format that Angular understands, such as `.xtb`.
|
||||
How you provide this information depends upon whether you compile with
|
||||
the JIT compiler or the AOT compiler.
|
||||
|
||||
* With [AOT](guide/i18n#merge-aot), you pass the information as configuration settings.
|
||||
* With [AOT](guide/i18n#merge-aot), you pass the information as a configuration
|
||||
* With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time.
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Workspace npm dependencies
|
||||
|
||||
The Angular Framework, Angular CLI, and components used by Angular applications are packaged as [npm packages](https://docs.npmjs.com/getting-started/what-is-npm "What is npm?") and distributed via the [npm registry](https://docs.npmjs.com/).
|
||||
The Angular Framework, Angular CLI, and components used by Angular applicatins are packaged as [npm packages](https://docs.npmjs.com/getting-started/what-is-npm "What is npm?") and distributed via the [npm registry](https://docs.npmjs.com/).
|
||||
|
||||
You can download and install these npm packages by using the [npm CLI client](https://docs.npmjs.com/cli/install), which is installed with and runs as a [Node.js®](https://nodejs.org "Nodejs.org") application. By default, the Angular CLI uses the npm client.
|
||||
|
||||
@ -138,4 +138,4 @@ Package name | Description
|
||||
For information about how the Angular CLI handles packages see the following guides:
|
||||
|
||||
* [Building and serving](guide/build) describes how packages come together to create a development build.
|
||||
* [Deployment](guide/deployment) describes how packages come together to create a production build.
|
||||
* [Deployment](guide/deployment) describes how packages come together to create a production build.
|
@ -1,135 +0,0 @@
|
||||
# Angular Workspace Configuration
|
||||
|
||||
A file named `angular.json` at the root level of an Angular [workspace](guide/glossary#workspace) provides workspace-wide and project-specific configuration defaults for build and development tools provided by the Angular CLI.
|
||||
Path values given in the configuration are relative to the root workspace folder.
|
||||
|
||||
## Overall JSON structure
|
||||
|
||||
At the top level of `angular.json`, a few properties configure the workspace, and a `projects` section contains the remaining per-project configuration options.
|
||||
|
||||
* `version`: The configuration-file version.
|
||||
* `newProjectRoot`: Path where new projects are created. Absolute or relative to the workspace folder.
|
||||
* `defaultProject`: Default project name to use in commands, where not provided as an argument. When you use `ng new` to create a new app in a new workspace, that app is the default project for the workspace until you change it here.
|
||||
* `projects` : Contains a subsection for each project (library, app, e2e test app) in the workspace, with the per-project configuration options.
|
||||
|
||||
The initial app that you create with `ng new app_name` is listed under "projects", along with its corresponding end-to-end test app:
|
||||
|
||||
<code-example format="." language="none" linenums="false">
|
||||
projects
|
||||
app_name
|
||||
...
|
||||
app_name-e2e
|
||||
...
|
||||
</code-example>
|
||||
|
||||
Each additional app that you create with `ng generate application` has a corresponding end-to-end test project, with its own configuration section.
|
||||
When you create a library project with `ng generate library`, the library project is also added to the `projects` section.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that the `projects` section of the configuration file does not correspond exactly to the workspace file structure.
|
||||
* The initial app created by `ng new` is at the top level of the workspace file structure, along with its e2e app.
|
||||
* Additional apps, e2e apps, and libraries go into a `projects` folder in the workspace.
|
||||
|
||||
For more information, see [Workspace and project file structure](guide/file-structure).
|
||||
|
||||
</div>
|
||||
|
||||
## Project configuration options
|
||||
|
||||
The following top-level configuration properties are available for each project, under `projects:<project_name>`.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"my-v7-app": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {}
|
||||
}
|
||||
</code-example>
|
||||
|
||||
| PROPERTY | DESCRIPTION |
|
||||
| :-------------- | :---------------------------- |
|
||||
| `root` | The root folder for this project's files, relative to the workspace folder. Empty for the initial app, which resides at the top level of the workspace. |
|
||||
| `sourceRoot` | The root folder for this project's source files. |
|
||||
| `projectType` | One of "application" or "library". An application can run independently in a browser, while a library cannot. Both an app and its e2e test app are of type "application".|
|
||||
| `prefix` | A string that Angular prepends to generated selectors. Can be customized to identify an app or feature area. |
|
||||
| `schematics` | An object containing schematics that customize CLI commands for this project. |
|
||||
| `architect` | An object containing configuration defaults for Architect builder targets for this project. |
|
||||
|
||||
## Project tool configuration options
|
||||
|
||||
Architect is the tool that the CLI uses to perform complex tasks such as compilation and test running, according to provided configurations. The `architect` section contains a set of Architect *targets*. Many of the targets correspond to the CLI commands that run them. Some additional predefined targets can be run using the `ng run` command, and you can define your own targets.
|
||||
|
||||
Each target object specifies the `builder` for that target, which is the npm package for the tool that Architect runs. In addition, each target has an `options` section that configure default options for the target, and a `configurations` section that names and specifies alternative configurations for the target. See the example in [Build target](#build-target) below.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"architect": {
|
||||
"build": { },
|
||||
"serve": { },
|
||||
"e2e" : { },
|
||||
"test": { },
|
||||
"lint": { },
|
||||
"extract-i18n": { },
|
||||
"server": { },
|
||||
"app-shell": { }
|
||||
}
|
||||
</code-example>
|
||||
|
||||
* The `architect/build` section configures defaults for options of the `ng build` command. See [Build target]{#build-target} below for more information.
|
||||
|
||||
* The `architect/serve` section overrides build defaults and supplies additional serve defaults for the `ng serve` command. In addition to the options available for the `ng build` command, it adds options related to serving the app.
|
||||
|
||||
* The `architect/e2e` section overrides build-option defaults for building end-to-end testing apps using the `ng e2e` command.
|
||||
|
||||
* The `architect/test` section overrides build-option defaults for test builds and supplies additional test-running defaults for the `ng test` command.
|
||||
|
||||
* The `architect/lint` section configures defaults for options of the `ng lint` command, which performs code analysis on project source files. The default linting tool for Angular is [TSLint](https://palantir.github.io/tslint/).
|
||||
|
||||
* The `architect/extract-i18n` section configures defaults for options of the `ng-xi18n` tool used by the `ng xi18n` command, which extracts marked message strings from source code and outputs translation files.
|
||||
|
||||
* The `architect/server` section configures defaults for creating a Universal app with server-side rendering, using the `ng run <project>:server` command.
|
||||
|
||||
* The `architect/app-shell` section configures defaults for creating an app shell for a progressive web app (PWA), using the `ng run <project>:app-shell` command.
|
||||
|
||||
In general, the options for which you can configure defaults correspond to the command options listed in the [CLI reference page](cli) for each command.
|
||||
Note that all options in the configuration file must use [camelCase](guide/glossary#case-conventions), rather than dash-case.
|
||||
|
||||
{@a build-target}
|
||||
|
||||
## Build target
|
||||
|
||||
The `architect/build` section configures defaults for options of the `ng build` command. It has the following top-level properties.
|
||||
|
||||
| PROPERTY | DESCRIPTION |
|
||||
| :-------------- | :---------------------------- |
|
||||
| `builder` | The npm package for the build tool used to create this target. The default is `@angular-devkit/build-angular:browser`, which uses the [webpack](https://webpack.js.org/) package bundler. |
|
||||
| `options` | This section contains defaults for build options, used when no named alternative configuration is specified. See [Default build options](#build-props) below. |
|
||||
| `configurations`| This section defines and names alternative configurations for different intended destinations. It contains a section for each named configuration, which sets the default options for that intended environment. See [Alternate build configurations](#build-configs) below. |
|
||||
|
||||
{@a build-configs}
|
||||
|
||||
### Alternate build configurations
|
||||
|
||||
By default, a `production` configuration is defined, and the `ng build` command has `--prod` option that builds using this configuration. The `production` configuration sets defaults that optimize the app in a number of ways, such bundling files, minimizing excess whitespace, removing comments and dead code, and rewriting code to use short, cryptic names ("minification").
|
||||
|
||||
You can define and name additional alternate configurations (such as `stage`, for instance) appropriate to your development process. Some examples of different build configurations are `stable`, `archive` and `next` used by AIO itself, and the individual locale-specific configurations required for building localized versions of an app. For details, see [Internationalization (i18n)](guide/i18n#merge-aot).
|
||||
|
||||
{@a build-props}
|
||||
|
||||
### Additional build and test options
|
||||
|
||||
The configurable options for a default or targeted build generally correspond to the options available for the [`ng build`](cli/build), [`ng serve`](cli/serve), and [`ng test`](cli/test) commands. For details of those options and their possible values, see the [CLI Reference](cli).
|
||||
|
||||
Some additional options (listed below) can only be set through the configuration file, either by direct editing or with the `ng config` command.
|
||||
|
||||
| OPTIONS PROPERTIES | DESCRIPTION |
|
||||
| :------------------------- | :---------------------------- |
|
||||
| `fileReplacements` | An object containing files and their compile-time replacements. |
|
||||
| `stylePreprocessorOptions` | An object containing option-value pairs to pass to style preprocessors. |
|
||||
| `assets` | An object containing paths to static assets to add to the global context of the project. The default paths point to the project's icon file and its `assets` folder. |
|
||||
| `styles` | An object containing style files to add to the global context of the project. Angular CLI supports CSS imports and all major CSS preprocessors: [sass/scss](http://sass-lang.com/), [less](http://lesscss.org/), and [stylus](http://stylus-lang.com/). |
|
||||
| `scripts` | An object containing JavaScript script files to add to the global context of the project. The scripts are loaded exactly as if you had added them in a `<script>` tag inside `index.html`. |
|
||||
| `budgets` | Default size-budget type and threshholds for all or parts of your app. You can configure the builder to report a warning or an error when the output reaches or exceeds a threshold size. See [Configure size budgets](guide/build#configure-size-budgets). (Not available in `test` section.) |
|
File diff suppressed because it is too large
Load Diff
@ -211,7 +211,7 @@
|
||||
"logo": "https://cloud.githubusercontent.com/assets/1016365/10639063/138338bc-7806-11e5-8057-d34c75f3cafc.png",
|
||||
"rev": true,
|
||||
"title": "Angular Universal",
|
||||
"url": "https://angular.io/guide/universal"
|
||||
"url": "https://github.com/angular/universal"
|
||||
},
|
||||
"c1": {
|
||||
"desc": "Lightweight development only Node.js® server",
|
||||
@ -273,13 +273,6 @@
|
||||
"rev": true,
|
||||
"title": "UI-jar - Test Driven Style Guide Development",
|
||||
"url": "https://github.com/ui-jar/ui-jar"
|
||||
},
|
||||
"protactor": {
|
||||
"desc": "The official end to end testing framework for Angular apps",
|
||||
"logo": "",
|
||||
"rev": true,
|
||||
"title": "Protractor",
|
||||
"url": "https://protractor.angular.io/"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -369,7 +362,7 @@
|
||||
"logo": "",
|
||||
"rev": true,
|
||||
"title": "Angular Material",
|
||||
"url": "https://material.angular.io/"
|
||||
"url": "https://github.com/angular/material2"
|
||||
},
|
||||
"mcc": {
|
||||
"desc": "Material components made by the community",
|
||||
@ -384,12 +377,6 @@
|
||||
"title": "Ant Design of Angular (ng-zorro-antd)",
|
||||
"url": "https://ng.ant.design/docs/introduce/en"
|
||||
},
|
||||
"ngzorromobile": {
|
||||
"desc": "A set of enterprise-class mobile UI components based on Ant Design Mobile and Angular",
|
||||
"rev": true,
|
||||
"title": "Ant Design Mobile of Angular (ng-zorro-antd-mobile)",
|
||||
"url": "http://ng.mobile.ant.design/#/docs/introduce/en"
|
||||
},
|
||||
"aggrid": {
|
||||
"desc": "A datagrid for Angular with enterprise style features such as sorting, filtering, custom rendering, editing, grouping, aggregation and pivoting.",
|
||||
"rev": true,
|
||||
|
@ -513,14 +513,8 @@
|
||||
{
|
||||
"url": "guide/file-structure",
|
||||
"title": "Project File Structure",
|
||||
"tooltip": "How your Angular workspace looks on your filesystem."
|
||||
"tooltip": "How your Angular workspace looks in your filesystem."
|
||||
},
|
||||
{
|
||||
"url": "guide/workspace-config",
|
||||
"title": "Workspace Configuration",
|
||||
"tooltip": "The \"angular.json\" file contains workspace and project configuration defaults for Angular CLI commands."
|
||||
},
|
||||
|
||||
{
|
||||
"url": "guide/npm-packages",
|
||||
"title": "npm Dependencies",
|
||||
|
@ -18,7 +18,7 @@
|
||||
"build-for": "yarn ~~build --configuration",
|
||||
"prebuild-local": "yarn setup-local",
|
||||
"build-local": "yarn ~~build --configuration=stable",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 4faa81e25",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js a2129510d7d57d1c02bec563872adf0204e11a2f",
|
||||
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
||||
"test": "yarn check-env && ng test",
|
||||
"pree2e": "yarn check-env && yarn update-webdriver",
|
||||
@ -30,8 +30,6 @@
|
||||
"setup-local": "yarn aio-use-local && yarn example-use-local",
|
||||
"postsetup-local": "yarn postsetup",
|
||||
"set-opensearch-url": "node --eval \"const sh = require('shelljs'); sh.set('-e'); sh.sed('-i', /PLACEHOLDER_URL/g, process.argv[1], 'dist/assets/opensearch.xml');\"",
|
||||
"presmoke-tests": "yarn update-webdriver",
|
||||
"smoke-tests": "protractor tests/deployment/e2e/protractor.conf.js --suite smoke --baseUrl",
|
||||
"test-pwa-score": "node scripts/test-pwa-score",
|
||||
"test-pwa-score-localhost": "run-p --race \"~~http-server dist -p 4200 --silent\" \"test-pwa-score http://localhost:4200 {1} {2}\" --",
|
||||
"example-e2e": "yarn example-check-local && node ./tools/examples/run-example-e2e",
|
||||
@ -115,7 +113,7 @@
|
||||
"entities": "^1.1.1",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-plugin-jasmine": "^2.2.0",
|
||||
"firebase-tools": "^5.1.1",
|
||||
"firebase-tools": "^3.2.1",
|
||||
"fs-extra": "^2.1.2",
|
||||
"globby": "^6.1.0",
|
||||
"hast-util-is-element": "^1.0.0",
|
||||
|
@ -13,7 +13,7 @@ readonly deployedUrl=https://pr${prNumber}-${prLastSha:0:7}.ngbuilds.io/
|
||||
cd $PROJECT_ROOT/aio
|
||||
|
||||
# Build and store the app
|
||||
yarn build --progress=false
|
||||
yarn build
|
||||
|
||||
# Set deployedUrl as parameter in the opensearch description
|
||||
# deployedUrl must end with /
|
||||
|
@ -93,7 +93,7 @@ fi
|
||||
cd "`dirname $0`/.."
|
||||
|
||||
# Build the app
|
||||
yarn build-for $deployEnv --progress=false
|
||||
yarn build-for $deployEnv
|
||||
|
||||
# Include any mode-specific files
|
||||
cp -rf src/extra-files/$deployEnv/. dist/
|
||||
@ -106,8 +106,8 @@ fi
|
||||
yarn payload-size
|
||||
|
||||
# Deploy to Firebase
|
||||
yarn firebase use "$projectId" --token "$firebaseToken"
|
||||
yarn firebase deploy --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
|
||||
firebase use "$projectId" --token "$firebaseToken"
|
||||
firebase deploy --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
|
||||
|
||||
# Run PWA-score tests
|
||||
yarn test-pwa-score "$deployedUrl" "$CI_AIO_MIN_PWA_SCORE"
|
||||
|
@ -45,9 +45,8 @@ get(previewabilityCheckUrl).
|
||||
const totalSecs = Math.round((previewCheckInterval * previewCheckAttempts) / 1000);
|
||||
throw new Error(`Preview still not available after ${totalSecs}s.`);
|
||||
}).
|
||||
// The preview is now available. Run the tests.
|
||||
then(() => yarnRun('smoke-tests', previewUrl)).
|
||||
then(() => yarnRun('test-pwa-score', previewUrl, minPwaScore));
|
||||
// The preview is now available. Run the PWA tests.
|
||||
then(() => runPwaTests());
|
||||
}).
|
||||
catch(onError);
|
||||
|
||||
@ -94,6 +93,15 @@ function reportNoPreview(reason) {
|
||||
console.log(`No (public) preview available. (Reason: ${reason})`);
|
||||
}
|
||||
|
||||
function runPwaTests() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawnOptions = {cwd: __dirname, stdio: 'inherit'};
|
||||
spawn('yarn', ['test-pwa-score', previewUrl, minPwaScore], spawnOptions).
|
||||
on('error', reject).
|
||||
on('exit', code => (code === 0 ? resolve : reject)());
|
||||
});
|
||||
}
|
||||
|
||||
function validateArgs(args) {
|
||||
if (args.length !== 3) {
|
||||
const relativeScriptPath = relative('.', __filename.replace(/\.js$/, ''));
|
||||
@ -111,12 +119,3 @@ function wait(delay) {
|
||||
console.log(`Waiting ${delay}ms...`);
|
||||
return new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
|
||||
function yarnRun(script, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawnOptions = {cwd: __dirname, stdio: 'inherit'};
|
||||
spawn('yarn', [script, ...args], spawnOptions).
|
||||
on('error', reject).
|
||||
on('exit', code => (code === 0 ? resolve : reject)());
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ set +x -eu -o pipefail
|
||||
|
||||
# Install dependencies.
|
||||
echo -e "\nInstalling dependencies in '$aioDir'...\n-----"
|
||||
yarn install --frozen-lockfile --non-interactive
|
||||
yarn install --frozen-lockfile
|
||||
yarn update-webdriver
|
||||
|
||||
# Run checks for all URLs.
|
||||
|
@ -3,11 +3,9 @@
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
suites: {
|
||||
full: './*.e2e-spec.ts',
|
||||
smoke: './smoke-tests.e2e-spec.ts',
|
||||
},
|
||||
suite: 'full',
|
||||
specs: [
|
||||
'./*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
// For Travis
|
||||
|
@ -59,9 +59,7 @@ describe(browser.baseUrl, () => {
|
||||
it('should serve `index.html` for unknown pages', async () => {
|
||||
const aioShell = element(by.css('aio-shell'));
|
||||
const heading = aioShell.element(by.css('h1'));
|
||||
|
||||
await page.goTo(unknownPagePath);
|
||||
await browser.wait(() => page.getDocViewerText(), 5000); // Wait for the document to be loaded.
|
||||
|
||||
expect(aioShell.isPresent()).toBe(true);
|
||||
expect(heading.getText()).toMatch(/page not found/i);
|
||||
|
@ -29,8 +29,6 @@ describe(browser.baseUrl, () => {
|
||||
Object.keys(textPerUrl).forEach(url => {
|
||||
it(`should show the page at '${url}'`, () => {
|
||||
page.goTo(url);
|
||||
browser.wait(() => page.getDocViewerText(), 5000); // Wait for the document to be loaded.
|
||||
|
||||
expect(page.getDocViewerText()).toContain(textPerUrl[url]);
|
||||
});
|
||||
});
|
||||
@ -41,7 +39,7 @@ describe(browser.baseUrl, () => {
|
||||
api: 'api list',
|
||||
'guide/architecture': 'architecture',
|
||||
'guide/http': 'httpclient',
|
||||
'guide/quickstart': 'getting started',
|
||||
'guide/quickstart': 'quickstart',
|
||||
'guide/security': 'security',
|
||||
tutorial: 'tutorial',
|
||||
};
|
||||
@ -49,8 +47,6 @@ describe(browser.baseUrl, () => {
|
||||
Object.keys(textPerUrl).forEach(url => {
|
||||
it(`should show the page at '${url}'`, () => {
|
||||
page.goTo(url);
|
||||
browser.wait(() => page.getDocViewerText(), 5000); // Wait for the document to be loaded.
|
||||
|
||||
expect(page.getDocViewerText()).toContain(textPerUrl[url]);
|
||||
});
|
||||
});
|
||||
@ -72,8 +68,6 @@ describe(browser.baseUrl, () => {
|
||||
Object.keys(textPerUrl).forEach(url => {
|
||||
it(`should show the page at '${url}'`, () => {
|
||||
page.goTo(url);
|
||||
browser.wait(() => page.getDocViewerText(), 5000); // Wait for the document to be loaded.
|
||||
|
||||
expect(page.getDocViewerText()).toContain(textPerUrl[url]);
|
||||
});
|
||||
});
|
||||
|
@ -12,15 +12,15 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^7.0.0",
|
||||
"@angular/common": "^7.0.0",
|
||||
"@angular/compiler": "^7.0.0",
|
||||
"@angular/core": "^7.0.0",
|
||||
"@angular/forms": "^7.0.0",
|
||||
"@angular/http": "^7.0.0",
|
||||
"@angular/platform-browser": "^7.0.0",
|
||||
"@angular/platform-browser-dynamic": "^7.0.0",
|
||||
"@angular/router": "^7.0.0",
|
||||
"@angular/animations": "~7.0.0-rc.0",
|
||||
"@angular/common": "~7.0.0-rc.0",
|
||||
"@angular/compiler": "~7.0.0-rc.0",
|
||||
"@angular/core": "~7.0.0-rc.0",
|
||||
"@angular/forms": "~7.0.0-rc.0",
|
||||
"@angular/http": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser-dynamic": "~7.0.0-rc.0",
|
||||
"@angular/router": "~7.0.0-rc.0",
|
||||
"angular-in-memory-web-api": "^0.6.0",
|
||||
"core-js": "^2.5.4",
|
||||
"rxjs": "^6.3.0",
|
||||
@ -28,10 +28,10 @@
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.0",
|
||||
"@angular-devkit/build-angular": "~0.9.0-rc.2",
|
||||
"@angular/cli": "~7.0.0-rc.2",
|
||||
"@angular/compiler-cli": "~7.0.0-rc.0",
|
||||
"@angular/language-service": "~7.0.0-rc.0",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
|
@ -15,15 +15,15 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^7.0.0",
|
||||
"@angular/common": "^7.0.0",
|
||||
"@angular/compiler": "^7.0.0",
|
||||
"@angular/core": "^7.0.0",
|
||||
"@angular/forms": "^7.0.0",
|
||||
"@angular/http": "^7.0.0",
|
||||
"@angular/platform-browser": "^7.0.0",
|
||||
"@angular/platform-browser-dynamic": "^7.0.0",
|
||||
"@angular/router": "^7.0.0",
|
||||
"@angular/animations": "~7.0.0-rc.0",
|
||||
"@angular/common": "~7.0.0-rc.0",
|
||||
"@angular/compiler": "~7.0.0-rc.0",
|
||||
"@angular/core": "~7.0.0-rc.0",
|
||||
"@angular/forms": "~7.0.0-rc.0",
|
||||
"@angular/http": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser-dynamic": "~7.0.0-rc.0",
|
||||
"@angular/router": "~7.0.0-rc.0",
|
||||
"angular-in-memory-web-api": "^0.6.0",
|
||||
"core-js": "^2.5.4",
|
||||
"rxjs": "^6.3.0",
|
||||
@ -31,10 +31,10 @@
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.0",
|
||||
"@angular-devkit/build-angular": "~0.9.0-rc.2",
|
||||
"@angular/cli": "~7.0.0-rc.2",
|
||||
"@angular/compiler-cli": "~7.0.0-rc.0",
|
||||
"@angular/language-service": "~7.0.0-rc.0",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
|
@ -16,18 +16,18 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^7.0.0",
|
||||
"@angular/common": "^7.0.0",
|
||||
"@angular/compiler": "^7.0.0",
|
||||
"@angular/core": "^7.0.0",
|
||||
"@angular/forms": "^7.0.0",
|
||||
"@angular/http": "^7.0.0",
|
||||
"@angular/platform-browser": "^7.0.0",
|
||||
"@angular/platform-browser-dynamic": "^7.0.0",
|
||||
"@angular/router": "^7.0.0",
|
||||
"@nguniversal/common": "^7.0.0",
|
||||
"@nguniversal/express-engine": "^7.0.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^7.0.0",
|
||||
"@angular/animations": "~7.0.0-rc.0",
|
||||
"@angular/common": "~7.0.0-rc.0",
|
||||
"@angular/compiler": "~7.0.0-rc.0",
|
||||
"@angular/core": "~7.0.0-rc.0",
|
||||
"@angular/forms": "~7.0.0-rc.0",
|
||||
"@angular/http": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser-dynamic": "~7.0.0-rc.0",
|
||||
"@angular/router": "~7.0.0-rc.0",
|
||||
"@nguniversal/common": "^6.1.0",
|
||||
"@nguniversal/express-engine": "^6.1.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^6.1.0",
|
||||
"angular-in-memory-web-api": "^0.6.0",
|
||||
"core-js": "^2.5.4",
|
||||
"rxjs": "^6.3.0",
|
||||
@ -35,11 +35,11 @@
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.0",
|
||||
"@angular/platform-server": "^7.0.0",
|
||||
"@angular-devkit/build-angular": "~0.9.0-rc.2",
|
||||
"@angular/cli": "~7.0.0-rc.2",
|
||||
"@angular/compiler-cli": "~7.0.0-rc.0",
|
||||
"@angular/language-service": "~7.0.0-rc.0",
|
||||
"@angular/platform-server": "~7.0.0-rc.0",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
|
@ -18,21 +18,21 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "^7.0.0",
|
||||
"@angular/common": "^7.0.0",
|
||||
"@angular/compiler": "^7.0.0",
|
||||
"@angular/core": "^7.0.0",
|
||||
"@angular/elements": "^7.0.0",
|
||||
"@angular/forms": "^7.0.0",
|
||||
"@angular/http": "^7.0.0",
|
||||
"@angular/platform-browser": "^7.0.0",
|
||||
"@angular/platform-browser-dynamic": "^7.0.0",
|
||||
"@angular/router": "^7.0.0",
|
||||
"@angular/service-worker": "^7.0.0",
|
||||
"@angular/upgrade": "^7.0.0",
|
||||
"@nguniversal/common": "^7.0.0",
|
||||
"@nguniversal/express-engine": "^7.0.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^7.0.0",
|
||||
"@angular/animations": "~7.0.0-rc.0",
|
||||
"@angular/common": "~7.0.0-rc.0",
|
||||
"@angular/compiler": "~7.0.0-rc.0",
|
||||
"@angular/core": "~7.0.0-rc.0",
|
||||
"@angular/elements": "~7.0.0-rc.0",
|
||||
"@angular/forms": "~7.0.0-rc.0",
|
||||
"@angular/http": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser": "~7.0.0-rc.0",
|
||||
"@angular/platform-browser-dynamic": "~7.0.0-rc.0",
|
||||
"@angular/router": "~7.0.0-rc.0",
|
||||
"@angular/service-worker": "~7.0.0-rc.0",
|
||||
"@angular/upgrade": "~7.0.0-rc.0",
|
||||
"@nguniversal/common": "^6.1.0",
|
||||
"@nguniversal/express-engine": "^6.1.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^6.1.0",
|
||||
"angular-in-memory-web-api": "^0.6.0",
|
||||
"core-js": "^2.5.4",
|
||||
"express": "^4.14.1",
|
||||
@ -42,11 +42,11 @@
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.0",
|
||||
"@angular/platform-server": "^7.0.0",
|
||||
"@angular-devkit/build-angular": "~0.9.0-rc.2",
|
||||
"@angular/cli": "^7.0.0-rc.2",
|
||||
"@angular/compiler-cli": "~7.0.0-rc.0",
|
||||
"@angular/language-service": "~7.0.0-rc.0",
|
||||
"@angular/platform-server": "~7.0.0-rc.0",
|
||||
"@types/angular": "^1.6.47",
|
||||
"@types/angular-animate": "^1.5.10",
|
||||
"@types/angular-mocks": "^1.6.0",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {
|
||||
return (ast) => {
|
||||
visit(ast, 'element', (node, ancestors) => {
|
||||
// Only interested in code elements that are not inside links
|
||||
if (autoLinkCodeImpl.codeElements.some(elementType =>
|
||||
is(node, elementType)) &&
|
||||
(!node.properties.className || node.properties.className.indexOf('no-auto-link') === -1) &&
|
||||
if (autoLinkCodeImpl.codeElements.some(elementType => is(node, elementType)) &&
|
||||
ancestors.every(ancestor => !is(ancestor, 'a'))) {
|
||||
visit(node, 'text', (node, ancestors) => {
|
||||
// Only interested in text nodes that are not inside links
|
||||
|
@ -109,11 +109,4 @@ describe('autoLinkCode post-processor', () => {
|
||||
processor.$process([doc]);
|
||||
expect(doc.renderedContent).toEqual('<code-example><a href="a/b/myclass" class="code-anchor">MyClass</a></code-example>');
|
||||
});
|
||||
|
||||
it('should ignore code blocks that are marked with a `no-auto-link` class', () => {
|
||||
aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });
|
||||
const doc = { docType: 'test-doc', renderedContent: '<code class="no-auto-link">MyClass</code>' };
|
||||
processor.$process([doc]);
|
||||
expect(doc.renderedContent).toEqual('<code class="no-auto-link">MyClass</code>');
|
||||
});
|
||||
});
|
||||
|
@ -47,6 +47,40 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
|
||||
var ignoreWordsMap = convertToMap(wordsToIgnore);
|
||||
|
||||
// If the heading contains a name starting with ng, e.g. "ngController", then add the
|
||||
// name without the ng to the text, e.g. "controller".
|
||||
function tokenize(text) {
|
||||
const rawTokens = text.split(/[\s\/]+/mg);
|
||||
const tokens = [];
|
||||
rawTokens.forEach(token => {
|
||||
// Strip off unwanted trivial characters
|
||||
token = token
|
||||
.trim()
|
||||
.replace(/^[_\-"'`({[<$*)}\]>.]+/, '')
|
||||
.replace(/[_\-"'`({[<$*)}\]>.]+$/, '');
|
||||
// Ignore tokens that contain weird characters
|
||||
if (/^[\w.\-]+$/.test(token)) {
|
||||
tokens.push(token.toLowerCase());
|
||||
const ngTokenMatch = /^[nN]g([A-Z]\w*)/.exec(token);
|
||||
if (ngTokenMatch) {
|
||||
tokens.push(ngTokenMatch[1].toLowerCase());
|
||||
}
|
||||
}
|
||||
});
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function extractWords(text, words, keywordMap) {
|
||||
var tokens = tokenize(text);
|
||||
tokens.forEach(function(token) {
|
||||
if (!keywordMap[token]) {
|
||||
words.push(token);
|
||||
keywordMap[token] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const filteredDocs = docs
|
||||
// We are not interested in some docTypes
|
||||
.filter(function(doc) { return !docTypesToIgnore[doc.docType]; })
|
||||
@ -70,9 +104,13 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
if (isString(value) && !propertiesToIgnore[key]) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
});
|
||||
|
||||
extractMemberWords(doc, members, membersMap);
|
||||
// Special case properties that contain content relating to "members"
|
||||
// of a doc that represents, say, a class or interface
|
||||
if (key === 'members' || key === 'statics') {
|
||||
value.forEach(function(member) { extractWords(member.name, members, membersMap); });
|
||||
}
|
||||
});
|
||||
|
||||
// Extract all the keywords from the headings
|
||||
if (doc.vFile && doc.vFile.headings) {
|
||||
@ -128,54 +166,4 @@ function convertToMap(collection) {
|
||||
const obj = {};
|
||||
collection.forEach(key => { obj[key] = true; });
|
||||
return obj;
|
||||
}
|
||||
|
||||
// If the heading contains a name starting with ng, e.g. "ngController", then add the
|
||||
// name without the ng to the text, e.g. "controller".
|
||||
function tokenize(text) {
|
||||
const rawTokens = text.split(/[\s\/]+/mg);
|
||||
const tokens = [];
|
||||
rawTokens.forEach(token => {
|
||||
// Strip off unwanted trivial characters
|
||||
token = token
|
||||
.trim()
|
||||
.replace(/^[_\-"'`({[<$*)}\]>.]+/, '')
|
||||
.replace(/[_\-"'`({[<$*)}\]>.]+$/, '');
|
||||
// Ignore tokens that contain weird characters
|
||||
if (/^[\w.\-]+$/.test(token)) {
|
||||
tokens.push(token.toLowerCase());
|
||||
const ngTokenMatch = /^[nN]g([A-Z]\w*)/.exec(token);
|
||||
if (ngTokenMatch) {
|
||||
tokens.push(ngTokenMatch[1].toLowerCase());
|
||||
}
|
||||
}
|
||||
});
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function extractWords(text, words, keywordMap) {
|
||||
var tokens = tokenize(text);
|
||||
tokens.forEach(function(token) {
|
||||
if (!keywordMap[token]) {
|
||||
words.push(token);
|
||||
keywordMap[token] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function extractMemberWords(doc, members, membersMap) {
|
||||
if (!doc) return;
|
||||
|
||||
if (doc.members) {
|
||||
doc.members.forEach(member => extractWords(member.name, members, membersMap));
|
||||
}
|
||||
if (doc.statics) {
|
||||
doc.statics.forEach(member => extractWords(member.name, members, membersMap));
|
||||
}
|
||||
if (doc.extendsClauses) {
|
||||
doc.extendsClauses.forEach(clause => extractMemberWords(clause.doc, members, membersMap));
|
||||
}
|
||||
if (doc.implementsClauses) {
|
||||
doc.implementsClauses.forEach(clause => extractMemberWords(clause.doc, members, membersMap));
|
||||
}
|
||||
}
|
@ -128,46 +128,6 @@ describe('generateKeywords processor', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should add inherited member doc properties to the search terms', () => {
|
||||
const processor = processorFactory(mockLogger, mockReadFilesProcessor);
|
||||
const parentClass = {
|
||||
docType: 'class',
|
||||
name: 'ParentClass',
|
||||
members: [
|
||||
{ name: 'parentMember1' },
|
||||
],
|
||||
statics: [
|
||||
{ name: 'parentMember2' },
|
||||
],
|
||||
};
|
||||
const parentInterface = {
|
||||
docType: 'interface',
|
||||
name: 'ParentInterface',
|
||||
members: [
|
||||
{ name: 'parentMember3' },
|
||||
]
|
||||
};
|
||||
|
||||
const childClass = {
|
||||
docType: 'class',
|
||||
name: 'Child',
|
||||
members: [
|
||||
{ name: 'childMember1' }
|
||||
],
|
||||
statics: [
|
||||
{ name: 'childMember2' }
|
||||
],
|
||||
extendsClauses: [{ doc: parentClass }],
|
||||
implementsClauses: [{ doc: parentInterface }]
|
||||
};
|
||||
const docs = [childClass, parentClass, parentInterface];
|
||||
processor.$process(docs);
|
||||
const keywordsDoc = docs[docs.length - 1];
|
||||
expect(keywordsDoc.data[0].members.split(' ').sort().join(' ')).toEqual(
|
||||
'childmember1 childmember2 parentmember1 parentmember2 parentmember3'
|
||||
);
|
||||
});
|
||||
|
||||
it('should process terms prefixed with "ng" to include the term stripped of "ng"', () => {
|
||||
const processor = processorFactory(mockLogger, mockReadFilesProcessor);
|
||||
const docs = [
|
||||
|
@ -12,14 +12,9 @@
|
||||
{$ doc.shortDescription | marked $}
|
||||
{$ doc.description | marked $}
|
||||
{$ cli.renderSyntax(doc) $}
|
||||
|
||||
{% if doc.longDescription.length %}
|
||||
<h2 class="no-anchor">Description</h2>
|
||||
{$ doc.longDescription | marked $}
|
||||
{% endif%}
|
||||
|
||||
{$ cli.renderArguments(doc.positionalOptions, 2) $}
|
||||
{$ cli.renderNamedOptions(doc.namedOptions, 2) $}
|
||||
{$ cli.renderSubcommands(doc) $}
|
||||
{$ doc.longDescription | marked $}
|
||||
</div>
|
||||
</article>
|
||||
|
@ -17,8 +17,8 @@
|
||||
<tbody>
|
||||
{% for command in doc.commands %}
|
||||
<tr>
|
||||
<td><a class="code-anchor" href="{$ command.path $}"><code class="no-auto-link">{$ command.name $}</code></a></td>
|
||||
<td>{% for alias in command.commandAliases %}<code class="no-auto-link">{$ alias $} </code>{% endfor %}</td>
|
||||
<td><a class="code-anchor" href="{$ command.path $}"><code>{$ command.name $}</code></a></td>
|
||||
<td>{% for alias in command.commandAliases %}<code>{$ alias $} </code>{% endfor %}</td>
|
||||
<td>{$ command.description | marked $}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% macro renderSyntax(container, prefix) -%}
|
||||
{% for name in container.names %}
|
||||
<code-example hideCopy="true" class="no-box api-heading no-auto-link">ng {%if prefix %}{$ prefix $} {% endif %}<span class="cli-name">{$ name $}</span>
|
||||
<code-example hideCopy="true" class="no-box api-heading">ng {%if prefix %}{$ prefix $} {% endif %}<span class="cli-name">{$ name $}</span>
|
||||
{%- for arg in container.positionalOptions %} <<var>{$ arg.name $}</var>>{% endfor %}
|
||||
{%- if container.namedOptions.length %} [<var>options</var>]{% endif -%}
|
||||
</code-example>
|
||||
@ -20,14 +20,14 @@
|
||||
<tbody>
|
||||
{% for option in arguments %}
|
||||
<tr class="cli-option">
|
||||
<td><code class="no-auto-link"><<var>{$ option.name $}</var>></code></td>
|
||||
<td><code><<var>{$ option.name $}</var>></code></td>
|
||||
<td>
|
||||
{$ option.description | marked $}
|
||||
{% if option.subcommands.length -%}
|
||||
<p>This option can take one of the following <a href="#{$ option.name $}-commands">sub-commands</a>:<p>
|
||||
<ul>
|
||||
{% for subcommand in option.subcommands %}
|
||||
<li><code class="no-auto-link"><a class="code-anchor" href="#{$ subcommand.name $}-command">{$ subcommand.name $}</a></code></li>
|
||||
<li><code><a class="code-anchor" href="#{$ subcommand.name $}-command">{$ subcommand.name $}</a></code></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{%- endif %}
|
||||
@ -53,11 +53,11 @@
|
||||
{% for option in options %}
|
||||
<tr class="cli-option">
|
||||
<td>
|
||||
<code class="cli-option-syntax no-auto-link">{$ renderOption(option.name, option.type, option.default, option.enum) $}</code>
|
||||
<code class="cli-option-syntax">{$ renderOption(option.name, option.type, option.default, option.enum) $}</code>
|
||||
</td>
|
||||
<td>
|
||||
{$ option.description | marked $}
|
||||
{% if option.default !== undefined %}<p><span class="cli-default">Default:</span> <code class="no-auto-link">{$ option.default $}</code></p>{% endif %}
|
||||
{% if option.default !== undefined %}<p><span class="cli-default">Default:</span> <code>{$ option.default $}</code></p>{% endif %}
|
||||
{% if option.aliases.length %}<p><span class="cli-aliases">Aliases:</span> {% for alias in option.aliases %}{$ renderOptionName(alias) $}{% if not loop.last %}, {% endif %}{% endfor %}</p>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
@ -92,7 +92,7 @@
|
||||
{% for command in container.positionalOptions %}{% if command.subcommands.length %}
|
||||
<h2><a id="{$ command.name $}-commands"></a>{$ command.name | title $} commands</h2>
|
||||
{% for subcommand in command.subcommands %}
|
||||
<h3><code class="no-auto-link"><a id="{$ subcommand.name $}-command"></a>{$ subcommand.name $}</code></h3>
|
||||
<h3><code><a id="{$ subcommand.name $}-command"></a>{$ subcommand.name $}</code></h3>
|
||||
{% for name in container.names %}
|
||||
{$ renderSyntax(subcommand, name) $}
|
||||
{% endfor %}
|
||||
|
1844
aio/yarn.lock
1844
aio/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -9,14 +9,21 @@ Bazel.
|
||||
|
||||
## Installation
|
||||
|
||||
In order to ensure that everyone builds Angular in a _consistent_ way, Bazel
|
||||
will be installed through NPM and therefore it's not necessary to install Bazel
|
||||
manually.
|
||||
Install Bazel from the distribution, see [install] instructions.
|
||||
On Mac, just `brew install bazel`.
|
||||
|
||||
The binaries for Bazel will be provided by the [`@bazel/bazel`](https://github.com/bazelbuild/rules_nodejs/tree/master/packages)
|
||||
NPM package and its platform-specific dependencies.
|
||||
Bazel will install a hermetic version of Node, npm, and Yarn when
|
||||
you run the first build.
|
||||
|
||||
You can access Bazel with the `yarn bazel` command
|
||||
[install]: https://bazel.build/versions/master/docs/install.html
|
||||
|
||||
### Installation of ibazel
|
||||
|
||||
Install interactive bazel runner / fs watcher via:
|
||||
|
||||
```
|
||||
yarn global add @bazel/ibazel
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -26,6 +33,12 @@ use to execute build steps, from `build_bazel_rules_typescript`.
|
||||
The sources on [GitHub] are published from Google's internal
|
||||
repository (google3).
|
||||
|
||||
That repository defines dependencies on specific versions of
|
||||
all the tools. You can run the tools Bazel installed, for
|
||||
example rather than `yarn install` (which depends on whatever
|
||||
version you have installed on your machine), you can
|
||||
`bazel run @nodejs//:yarn`.
|
||||
|
||||
Bazel accepts a lot of options. We check in some options in the
|
||||
`.bazelrc` file. See the [bazelrc doc]. For example, if you don't
|
||||
want Bazel to create several symlinks in your project directory
|
||||
@ -37,8 +50,8 @@ want Bazel to create several symlinks in your project directory
|
||||
|
||||
## Building Angular
|
||||
|
||||
- Build a package: `yarn bazel build packages/core`
|
||||
- Build all packages: `yarn bazel build packages/...`
|
||||
- Build a package: `bazel build packages/core`
|
||||
- Build all packages: `bazel build packages/...`
|
||||
|
||||
You can use [ibazel] to get a "watch mode" that continuously
|
||||
keeps the outputs up-to-date as you save sources. Note this is
|
||||
@ -48,9 +61,9 @@ new as of May 2017 and not very stable yet.
|
||||
|
||||
## Testing Angular
|
||||
|
||||
- Test package in node: `yarn bazel test packages/core/test:test`
|
||||
- Test package in karma: `yarn bazel test packages/core/test:test_web`
|
||||
- Test all packages: `yarn bazel test packages/...`
|
||||
- Test package in node: `bazel test packages/core/test:test`
|
||||
- Test package in karma: `bazel test packages/core/test:test_web`
|
||||
- Test all packages: `bazel test packages/...`
|
||||
|
||||
You can use [ibazel] to get a "watch mode" that continuously
|
||||
keeps the outputs up-to-date as you save sources.
|
||||
@ -59,20 +72,19 @@ keeps the outputs up-to-date as you save sources.
|
||||
|
||||
If you're experiencing problems with seemingly unrelated tests failing, it may be because you're not using the proper flags with your Bazel test runs in Angular.
|
||||
|
||||
See also: [`//.bazelrc`](https://github.com/angular/angular/blob/master/.bazelrc) where `--define=compile=legacy` is defined as default.
|
||||
See also: [`//.bazelrc`](https://github.com/angular/angular/blob/master/.bazelrc) where `--define=ivy=false` is defined as default.
|
||||
|
||||
- `--config=debug`: build and launch in debug mode (see [debugging](#debugging) instructions below)
|
||||
- `--test_arg=--node_options=--inspect=9228`: change the inspector port.
|
||||
- `--define=compile=<option>` Controls if ivy or legacy mode is enabled. This is done by generating the [`src/ivy_switch.ts`](https://github.com/angular/angular/blob/master/packages/core/src/ivy_switch.ts) file from [`ivy_switch_legacy.ts`](https://github.com/angular/angular/blob/master/packages/core/src/ivy_switch_legacy.ts) (default), [`ivy_switch_jit.ts`](https://github.com/angular/angular/blob/master/packages/core/src/ivy_switch_jit.ts), or [`ivy_switch_local.ts`](https://github.com/angular/angular/blob/master/packages/core/src/ivy_switch_local.ts).
|
||||
- `--define=compile=<option>` Controls if ivy or legacy mode is enabled. This switches which compiler is used (ngc, ngtsc, or a tsc pass-through mode).
|
||||
- `legacy`: (default behavior) compile against View Engine, e.g. `--define=compile=legacy`
|
||||
- `jit`: Compile in ivy JIT mode, e.g. `--define=compile=jit`
|
||||
- `aot`: Compile in ivy AOT move, e.g. `--define=compile=aot`
|
||||
- `--test_tag_filters=<tag>`: filter tests down to tags defined in the `tag` config of your rules in any given `BUILD.bazel`.
|
||||
- `no-ivy-aot`: Useful for excluding build and test targets that are not meant to be executed in Ivy AOT mode (`--define=compile=aot`).
|
||||
- `no-ivy-jit`: Useful for excluding build and test targets that are not meant to be executed in Ivy JIT mode (`--define=compile=jit`).
|
||||
- `ivy-only`: Useful for excluding all Ivy build and tests targets with `--define=compile=legacy`.
|
||||
- `fixme-ivy-aot`: Useful for including/excluding build and test targets that are currently broken in Ivy AOT mode (`--define=compile=aot`).
|
||||
- `fixme-ivy-jit`: Useful for including/excluding build and test targets that are currently broken in Ivy JIT mode (`--define=compile=jit`).
|
||||
- `local`: Compile in ivy AOT move, e.g. `--define=compile=local`
|
||||
- `--test_tag_filters=<tag>`: filter tests down to tags defined in the `tag` config
|
||||
of your rules in any given `BUILD.bazel`.
|
||||
- `ivy-jit`: This flag should be set for tests that should be excuted with ivy JIT, e.g. `--test_tag_filters=ivy-jit`. For this, you may have to include `--define=compile=jit`.
|
||||
- `ivy-local`: Only run tests that have to do with ivy AOT. For this, you may have to include `--define=compile=local`, e.g. `--test_tag_filters=ivy-local`..
|
||||
- `ivy-only`: Only run ivy related tests, e.g. `--test_tag_filters=ivy-only`.
|
||||
|
||||
|
||||
### Debugging a Node Test
|
||||
@ -80,7 +92,7 @@ See also: [`//.bazelrc`](https://github.com/angular/angular/blob/master/.bazelrc
|
||||
|
||||
- Open chrome at: [chrome://inspect](chrome://inspect)
|
||||
- Click on `Open dedicated DevTools for Node` to launch a debugger.
|
||||
- Run test: `yarn bazel test packages/core/test:test --config=debug`
|
||||
- Run test: `bazel test packages/core/test:test --config=debug`
|
||||
|
||||
The process should automatically connect to the debugger. For additional info and testing options, see the [nodejs_test documentation](https://bazelbuild.github.io/rules_nodejs/node/node.html#nodejs_test).
|
||||
|
||||
@ -117,7 +129,7 @@ First time setup:
|
||||
|
||||
**Setting breakpoints directly in your code files may not work in VSCode**. This is because the files you're actually debugging are built files that exist in a `./private/...` folder.
|
||||
The easiest way to debug a test for now is to add a `debugger` statement in the code
|
||||
and launch the bazel corresponding test (`yarn bazel test <target> --config=debug`).
|
||||
and launch the bazel corresponding test (`bazel test <target> --config=debug`).
|
||||
|
||||
Bazel will wait on a connection. Go to the debug view (by clicking on the sidebar or
|
||||
Apple+Shift+D on Mac) and click on the green play icon next to the configuration name
|
||||
@ -125,7 +137,7 @@ Apple+Shift+D on Mac) and click on the green play icon next to the configuration
|
||||
|
||||
### Debugging a Karma Test
|
||||
|
||||
- Run test: `yarn bazel run packages/core/test:test_web`
|
||||
- Run test: `bazel run packages/core/test:test_web`
|
||||
- Open chrome at: [http://localhost:9876/debug.html](http://localhost:9876/debug.html)
|
||||
- Open chrome inspector
|
||||
|
||||
@ -138,7 +150,7 @@ open $(bazel info output_base)/external
|
||||
|
||||
See subcommands that bazel executes (helpful for debugging):
|
||||
```sh
|
||||
yarn bazel build //packages/core:package -s
|
||||
bazel build //packages/core:package -s
|
||||
```
|
||||
|
||||
To debug nodejs_binary executable paths uncomment `find . -name rollup 1>&2` (~ line 96) in
|
||||
@ -155,7 +167,7 @@ In our repo, here is how it's configured:
|
||||
1) In `tools/bazel_stamp_vars.sh` we run the `git` commands to generate our versioning info.
|
||||
1) In `.bazelrc` we register this script as the value for the `workspace_status_command` flag. Bazel will run the script when it needs to stamp a binary.
|
||||
|
||||
Note that Bazel has a `--stamp` argument to `yarn bazel build`, but this has no effect since our stamping takes place in Skylark rules. See https://github.com/bazelbuild/bazel/issues/1054
|
||||
Note that Bazel has a `--stamp` argument to `bazel build`, but this has no effect since our stamping takes place in Skylark rules. See https://github.com/bazelbuild/bazel/issues/1054
|
||||
|
||||
## Remote cache
|
||||
|
||||
@ -193,7 +205,7 @@ See [bazelbuild/intellij#246](https://github.com/bazelbuild/intellij/issues/246)
|
||||
If you see the following error:
|
||||
|
||||
```
|
||||
$ yarn bazel build packages/...
|
||||
$ bazel build packages/...
|
||||
ERROR: /private/var/tmp/[...]/external/local_config_cc/BUILD:50:5: in apple_cc_toolchain rule @local_config_cc//:cc-compiler-darwin_x86_64: Xcode version must be specified to use an Apple CROSSTOOL
|
||||
ERROR: Analysis of target '//packages/core/test/render3:render3' failed; build aborted: Analysis of target '@local_config_cc//:cc-compiler-darwin_x86_64' failed; build aborted
|
||||
```
|
||||
@ -215,7 +227,7 @@ If VSCode is not the root cause, you might try:
|
||||
bazel clean --expunge
|
||||
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
||||
sudo xcodebuild -license
|
||||
yarn bazel build //packages/core # Run a build outside VSCode to pre-build the xcode; then safe to run VSCode
|
||||
bazel build //packages/core # Run a build outside VSCode to pre-build the xcode; then safe to run VSCode
|
||||
```
|
||||
|
||||
Source: https://stackoverflow.com/questions/45276830/xcode-version-must-be-specified-to-use-an-apple-crosstool
|
||||
|
@ -5,9 +5,6 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bazel/bazel": "file:../../node_modules/@bazel/bazel"
|
||||
},
|
||||
"scripts": {
|
||||
"//": "deps are listed in src/package.json which is used by yarn_install",
|
||||
"//": "this package.json file is only here so that `yarn test` can be called by /integration/run_tests.sh",
|
||||
|
@ -2,24 +2,3 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@bazel/bazel-darwin_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.18.0.tgz#bab437605a702279d42f59caa4741bb327eb7dbc"
|
||||
integrity sha512-um2OzgLL2Gd/W6joOpvrSTcqpnupliPNpwe/uE7sB0huBSJ/4Im0w2IlCTI6C7OfgMcbpUj4YxgUa9T6u6WY6w==
|
||||
|
||||
"@bazel/bazel-linux_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.18.0.tgz#0c02b2404ec95c180e17615cc7079ee07df48a69"
|
||||
integrity sha512-Rq8X8bL6SgQvbOHnfPhSgF6hp+f6Fbt2w6pRmBlFvV1J+CeUyrSrrRXfnnO1bjIuq05Ur3mV8ULA0qK6rtA5lQ==
|
||||
|
||||
"@bazel/bazel-win32_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.18.0.tgz#aa4575fb00066dcf59a6d464971774dea6a0bafd"
|
||||
integrity sha512-U2TbfK8B7dc3JqXSFwj2oXCQrxEaSzCCUkAHjAOIGOKzx/HLKIKs+NJj9IQkLLr7BsMU+Qqzo8aqo11E+Vs+aA==
|
||||
|
||||
"@bazel/bazel@file:../../node_modules/@bazel/bazel":
|
||||
version "0.18.0"
|
||||
optionalDependencies:
|
||||
"@bazel/bazel-darwin_x64" "0.18.0"
|
||||
"@bazel/bazel-linux_x64" "0.18.0"
|
||||
"@bazel/bazel-win32_x64" "0.18.0"
|
||||
|
@ -17,10 +17,10 @@ ivy-ngcc
|
||||
ls node_modules/@angular/common | grep __modified_by_ngcc_for_esm2015
|
||||
if [[ $? != 0 ]]; then exit 1; fi
|
||||
|
||||
# Did it replace the NGCC_PRE markers correctly?
|
||||
grep "= R3_COMPILE_COMPONENT__POST_NGCC__" node_modules/@angular/core/fesm2015/core.js
|
||||
# Did it replace the PRE_R3 markers correctly?
|
||||
grep "= SWITCH_COMPILE_COMPONENT__POST_R3__" node_modules/@angular/core/fesm2015/core.js
|
||||
if [[ $? != 0 ]]; then exit 1; fi
|
||||
grep "= R3_COMPILE_COMPONENT__POST_NGCC__" node_modules/@angular/core/fesm5/core.js
|
||||
grep "= SWITCH_COMPILE_COMPONENT__POST_R3__" node_modules/@angular/core/fesm5/core.js
|
||||
if [[ $? != 0 ]]; then exit 1; fi
|
||||
|
||||
# Did it compile @angular/core/ApplicationModule correctly?
|
||||
|
@ -56,15 +56,6 @@ describe('largetable benchmark perf', () => {
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for render3', done => {
|
||||
runTableBenchmark({
|
||||
id: `largeTable.render3.${worker.id}`,
|
||||
url: 'all/benchmarks/src/largetable/render3/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
worker: worker
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should run for iv', done => {
|
||||
runTableBenchmark({
|
||||
id: `largeTable.iv.${worker.id}`,
|
||||
|
@ -25,13 +25,6 @@ describe('largetable benchmark spec', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for render3', () => {
|
||||
testTableBenchmark({
|
||||
url: 'all/benchmarks/src/largetable/render3/index.html',
|
||||
ignoreBrowserSynchronization: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for iv', () => {
|
||||
testTableBenchmark({
|
||||
url: 'all/benchmarks/src/largetable/iv/index.html',
|
||||
|
@ -49,12 +49,6 @@ export const Benchmarks: Benchmark[] = [
|
||||
url: 'all/benchmarks/src/tree/ng2_switch/index.html',
|
||||
buttons: CreateDestroyButtons,
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng2.render3`,
|
||||
url: 'all/benchmarks/src/tree/render3/index.html',
|
||||
buttons: CreateDestroyDetectChangesButtons,
|
||||
ignoreBrowserSynchronization: true,
|
||||
},
|
||||
{
|
||||
id: `deepTree.ng2.render3_function`,
|
||||
url: 'all/benchmarks/src/tree/render3_function/index.html',
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import {$} from 'protractor';
|
||||
|
||||
import {openBrowser} from '../../../e2e_util/e2e_util';
|
||||
import {runBenchmark, verifyNoBrowserErrors} from '../../../e2e_util/perf_util';
|
||||
|
||||
interface Worker {
|
||||
@ -39,9 +40,23 @@ describe('largetable benchmark perf', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it('should render the table for render3', () => {
|
||||
openBrowser({
|
||||
url: '',
|
||||
ignoreBrowserSynchronization: true,
|
||||
params: [{name: 'cols', value: 5}, {name: 'rows', value: 5}],
|
||||
});
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('0/0');
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('A/A');
|
||||
$('#destroyDom').click();
|
||||
expect($('#root').getText() as any).toEqual('');
|
||||
});
|
||||
|
||||
[CreateOnlyWorker, CreateAndDestroyWorker, UpdateWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
it('should run for render3', done => {
|
||||
it('should run benchmark for render3', done => {
|
||||
runTableBenchmark({
|
||||
id: `largeTable.render3.${worker.id}`,
|
||||
url: 'index.html',
|
||||
|
@ -1,10 +1,10 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//tools:defaults.bzl", "ng_rollup_bundle", "ts_library")
|
||||
load("//tools:defaults.bzl", "ng_module", "ng_rollup_bundle")
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
|
||||
ts_library(
|
||||
ng_module(
|
||||
name = "largetable_lib",
|
||||
srcs = glob(
|
||||
[
|
||||
@ -12,18 +12,20 @@ ts_library(
|
||||
],
|
||||
exclude = ["protractor.on-prepare.ts"],
|
||||
),
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
"//modules/benchmarks/src:util_lib",
|
||||
"//modules/benchmarks/src/largetable:util_lib",
|
||||
"//packages:types",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
ng_rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "modules/benchmarks/src/largetable/render3/index.js",
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
":largetable_lib",
|
||||
],
|
||||
@ -44,6 +46,7 @@ ts_devserver(
|
||||
"index.html",
|
||||
":favicon",
|
||||
],
|
||||
tags = ["ivy-only"],
|
||||
)
|
||||
|
||||
protractor_web_test(
|
||||
@ -57,13 +60,9 @@ protractor_web_test(
|
||||
"@ngdeps//reflect-metadata",
|
||||
"@ngdeps//yargs",
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
on_prepare = ":protractor.on_prepare.js",
|
||||
server = ":devserver",
|
||||
tags = [
|
||||
"fixme-ivy-aot",
|
||||
"fixme-ivy-jit",
|
||||
"ivy-only",
|
||||
],
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
"//modules/benchmarks/src/largetable:perf_lib",
|
||||
],
|
||||
|
@ -28,15 +28,9 @@
|
||||
<script>
|
||||
// TODO(mlaval): remove once we have a proper solution
|
||||
ngDevMode = false;
|
||||
var isBazel = location.pathname.indexOf('/all/') !== 0;
|
||||
// isBazel needed while 'scripts/ci/test-e2e.sh test.e2e.protractor-e2e' is run
|
||||
// on Travis
|
||||
// TODO: port remaining protractor e2e tests to bazel protractor_web_test_suite rule
|
||||
var bazelBundle = document.location.search.endsWith('debug') ? 'bundle.min_debug.js' : 'bundle.min.js';
|
||||
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1]
|
||||
|| '../../bootstrap_ng2.js';
|
||||
document.write('<script src="' + (isBazel ? bazelBundle : mainUrl) + '">\u003c/script>');
|
||||
document.write('<script src="' + bazelBundle + '">\u003c/script>');
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
@ -5,7 +5,7 @@
|
||||
* 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 'reflect-metadata';
|
||||
import {ɵrenderComponent as renderComponent} from '@angular/core';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = function(config) {
|
||||
return protractorUtils.runServer(config.workspace, config.server, '-port', [])
|
||||
.then(serverSpec => {
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
// Since the browser restarts in this benchmark we need to set both the browser.baseUrl
|
||||
// for the first test and the protractor config.baseUrl for the subsequent tests
|
||||
protractor.browser.baseUrl = serverUrl;
|
||||
return protractor.browser.getProcessedConfig().then((config) => config.baseUrl = serverUrl);
|
||||
});
|
||||
};
|
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
const serverSpec = await protractorUtils.runServer(config.workspace, config.server, '-port', []);
|
||||
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
// Since the browser restarts in this benchmark we need to set both the browser.baseUrl
|
||||
// for the first test and the protractor config.baseUrl for the subsequent tests
|
||||
protractor.browser.baseUrl = serverUrl;
|
||||
|
||||
const processedConfig = await protractor.browser.getProcessedConfig();
|
||||
return processedConfig.baseUrl = serverUrl;
|
||||
};
|
@ -6,76 +6,39 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ɵRenderFlags, ɵbind, ɵcontainer, ɵcontainerRefreshEnd, ɵcontainerRefreshStart, ɵdefineComponent, ɵdetectChanges, ɵelementEnd, ɵelementStart, ɵelementStyleProp, ɵelementStyling, ɵembeddedViewEnd, ɵembeddedViewStart, ɵtext, ɵtextBinding as ɵtextBinding} from '@angular/core';
|
||||
import {ComponentDef} from '@angular/core/src/render3/interfaces/definition';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Component, Input, NgModule, ɵdetectChanges} from '@angular/core';
|
||||
|
||||
import {TableCell, buildTable, emptyTable} from '../util';
|
||||
|
||||
const c0 = ['background-color'];
|
||||
@Component({
|
||||
selector: 'largetable',
|
||||
template: `
|
||||
<table>
|
||||
<tbody>
|
||||
<tr *ngFor="let row of data; trackBy: trackByIndex">
|
||||
<td *ngFor="let cell of row; trackBy: trackByIndex" [style.background-color]="getColor(cell.row)">
|
||||
{{cell.value}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`,
|
||||
})
|
||||
export class LargeTableComponent {
|
||||
@Input()
|
||||
data: TableCell[][] = emptyTable;
|
||||
|
||||
/** @nocollapse */
|
||||
static ngComponentDef: ComponentDef<LargeTableComponent> = ɵdefineComponent({
|
||||
type: LargeTableComponent,
|
||||
selectors: [['largetable']],
|
||||
consts: 3,
|
||||
vars: 0,
|
||||
template: function(rf: ɵRenderFlags, ctx: LargeTableComponent) {
|
||||
if (rf & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'table');
|
||||
{
|
||||
ɵelementStart(1, 'tbody');
|
||||
{ ɵcontainer(2); }
|
||||
ɵelementEnd();
|
||||
}
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf & ɵRenderFlags.Update) {
|
||||
ɵcontainerRefreshStart(2);
|
||||
{
|
||||
for (let row of ctx.data) {
|
||||
let rf1 = ɵembeddedViewStart(1, 2, 0);
|
||||
{
|
||||
if (rf1 & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'tr');
|
||||
ɵcontainer(1);
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf1 & ɵRenderFlags.Update) {
|
||||
ɵcontainerRefreshStart(1);
|
||||
{
|
||||
for (let cell of row) {
|
||||
let rf2 = ɵembeddedViewStart(2, 2, 1);
|
||||
{
|
||||
if (rf2 & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'td');
|
||||
ɵelementStyling(null, c0);
|
||||
{ ɵtext(1); }
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf2 & ɵRenderFlags.Update) {
|
||||
ɵelementStyleProp(0, 0, null, cell.row % 2 ? '' : 'grey');
|
||||
ɵtextBinding(1, ɵbind(cell.value));
|
||||
}
|
||||
}
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
}
|
||||
}
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
}
|
||||
},
|
||||
factory: () => new LargeTableComponent(),
|
||||
inputs: {data: 'data'}
|
||||
});
|
||||
trackByIndex(index: number, item: any) { return index; }
|
||||
|
||||
getColor(row: number) { return row % 2 ? '' : 'grey'; }
|
||||
}
|
||||
|
||||
@NgModule({declarations: [LargeTableComponent], imports: [CommonModule]})
|
||||
class TableModule {
|
||||
}
|
||||
|
||||
|
||||
export function destroyDom(component: LargeTableComponent) {
|
||||
component.data = emptyTable;
|
||||
ɵdetectChanges(component);
|
||||
|
@ -13,3 +13,16 @@ ts_library(
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "perf_lib",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"tree_perf.spec.ts",
|
||||
],
|
||||
deps = [
|
||||
"//modules/e2e_util:lib",
|
||||
"//packages:types",
|
||||
"@ngdeps//protractor",
|
||||
],
|
||||
)
|
||||
|
@ -5,17 +5,18 @@ load("//packages/bazel:index.bzl", "protractor_web_test")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
|
||||
ng_module(
|
||||
name = "render3_lib",
|
||||
name = "tree_lib",
|
||||
srcs = glob(
|
||||
[
|
||||
"**/*.ts",
|
||||
],
|
||||
),
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
"//modules/benchmarks/src/tree:util_lib",
|
||||
"//packages:types",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
@ -55,14 +56,12 @@ protractor_web_test(
|
||||
],
|
||||
on_prepare = ":protractor.on_prepare.js",
|
||||
server = ":devserver",
|
||||
tags = [
|
||||
"fixme-ivy-aot",
|
||||
"fixme-ivy-jit",
|
||||
"ivy-only",
|
||||
],
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
"//modules/benchmarks/src/tree:perf_lib",
|
||||
"@ngdeps//node-uuid",
|
||||
"@ngdeps//protractor",
|
||||
"@ngdeps//reflect-metadata",
|
||||
"@ngdeps//yargs",
|
||||
],
|
||||
)
|
||||
|
@ -30,9 +30,8 @@
|
||||
<script>
|
||||
// TODO(mlaval): remove once we have a proper solution
|
||||
ngDevMode = false;
|
||||
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1]
|
||||
|| '../../bootstrap_ng2.js';
|
||||
document.write('<script src="' + mainUrl + '">\u003c/script>');
|
||||
var bazelBundle = document.location.search.endsWith('debug') ? 'bundle.min_debug.js' : 'bundle.min.js';
|
||||
document.write('<script src="' + bazelBundle + '">\u003c/script>');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import 'reflect-metadata';
|
||||
import {ɵrenderComponent as renderComponent} from '@angular/core';
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {TreeComponent, createDom, destroyDom, detectChanges} from './tree';
|
||||
@ -27,3 +28,5 @@ export function main() {
|
||||
profile(() => createDom(component), () => destroyDom(component), 'create'));
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
22
modules/benchmarks/src/tree/render3/protractor.on_prepare.js
Normal file
22
modules/benchmarks/src/tree/render3/protractor.on_prepare.js
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = async function(config) {
|
||||
const serverSpec = await protractorUtils.runServer(config.workspace, config.server, '-port', []);
|
||||
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
// Since the browser restarts in this benchmark we need to set both the browser.baseUrl
|
||||
// for the first test and the protractor config.baseUrl for the subsequent tests
|
||||
protractor.browser.baseUrl = serverUrl;
|
||||
|
||||
const processedConfig = await protractor.browser.getProcessedConfig();
|
||||
return processedConfig.baseUrl = serverUrl;
|
||||
};
|
@ -6,7 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ɵRenderFlags, ɵbind, ɵcontainer, ɵcontainerRefreshEnd, ɵcontainerRefreshStart, ɵdefineComponent, ɵdetectChanges, ɵelementEnd, ɵelementProperty, ɵelementStart, ɵelementStyleProp, ɵelementStyling as s, ɵembeddedViewEnd, ɵembeddedViewStart, ɵinterpolation1, ɵtext, ɵtextBinding as ɵtextBinding} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Component, NgModule, ɵdetectChanges} from '@angular/core';
|
||||
|
||||
import {TreeNode, buildTree, emptyTree} from '../util';
|
||||
|
||||
@ -30,122 +31,17 @@ export function detectChanges(component: TreeComponent) {
|
||||
numberOfChecksEl.textContent = `${detectChangesRuns}`;
|
||||
}
|
||||
|
||||
const c0 = ['background-color'];
|
||||
@Component({
|
||||
selector: 'tree',
|
||||
inputs: ['data'],
|
||||
template:
|
||||
`<span [style.backgroundColor]="bgColor"> {{data.value}} </span><tree *ngIf='data.right != null' [data]='data.right'></tree><tree *ngIf='data.left != null' [data]='data.left'></tree>`
|
||||
})
|
||||
export class TreeComponent {
|
||||
data: TreeNode = emptyTree;
|
||||
|
||||
/** @nocollapse */
|
||||
static ngComponentDef = ɵdefineComponent({
|
||||
type: TreeComponent,
|
||||
selectors: [['tree']],
|
||||
consts: 4,
|
||||
vars: 1,
|
||||
template: function(rf: ɵRenderFlags, ctx: TreeComponent) {
|
||||
if (rf & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'span');
|
||||
s(null, c0);
|
||||
{ ɵtext(1); }
|
||||
ɵelementEnd();
|
||||
ɵcontainer(2);
|
||||
ɵcontainer(3);
|
||||
}
|
||||
if (rf & ɵRenderFlags.Update) {
|
||||
ɵelementStyleProp(0, 0, ctx.data.depth % 2 ? '' : 'grey');
|
||||
ɵtextBinding(1, ɵinterpolation1(' ', ctx.data.value, ' '));
|
||||
ɵcontainerRefreshStart(2);
|
||||
{
|
||||
if (ctx.data.left != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 1, 1);
|
||||
{
|
||||
if (rf0 & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'tree');
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf0 & ɵRenderFlags.Update) {
|
||||
ɵelementProperty(0, 'data', ɵbind(ctx.data.left));
|
||||
}
|
||||
}
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
ɵcontainerRefreshStart(3);
|
||||
{
|
||||
if (ctx.data.right != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 1, 1);
|
||||
{
|
||||
if (rf0 & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'tree');
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf0 & ɵRenderFlags.Update) {
|
||||
ɵelementProperty(0, 'data', ɵbind(ctx.data.right));
|
||||
}
|
||||
}
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
}
|
||||
},
|
||||
factory: () => new TreeComponent,
|
||||
inputs: {data: 'data'},
|
||||
directives: () => [TreeComponent]
|
||||
});
|
||||
data: any = emptyTree;
|
||||
get bgColor() { return this.data.depth % 2 ? '' : 'grey'; }
|
||||
}
|
||||
|
||||
export class TreeFunction {
|
||||
data: TreeNode = emptyTree;
|
||||
|
||||
/** @nocollapse */
|
||||
static ngComponentDef = ɵdefineComponent({
|
||||
type: TreeFunction,
|
||||
selectors: [['tree']],
|
||||
consts: 5,
|
||||
vars: 1,
|
||||
template: function(rf: ɵRenderFlags, ctx: TreeFunction) {
|
||||
// bit of a hack
|
||||
TreeTpl(rf, ctx.data);
|
||||
},
|
||||
factory: () => new TreeFunction,
|
||||
inputs: {data: 'data'}
|
||||
});
|
||||
}
|
||||
|
||||
const c1 = ['background-color'];
|
||||
export function TreeTpl(rf: ɵRenderFlags, ctx: TreeNode) {
|
||||
if (rf & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'tree');
|
||||
{
|
||||
ɵelementStart(1, 'span');
|
||||
s(null, c1);
|
||||
{ ɵtext(2); }
|
||||
ɵelementEnd();
|
||||
ɵcontainer(3);
|
||||
ɵcontainer(4);
|
||||
}
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf & ɵRenderFlags.Update) {
|
||||
ɵelementStyleProp(1, 0, ctx.depth % 2 ? '' : 'grey');
|
||||
ɵtextBinding(2, ɵinterpolation1(' ', ctx.value, ' '));
|
||||
ɵcontainerRefreshStart(3);
|
||||
{
|
||||
if (ctx.left != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 5, 1);
|
||||
{ TreeTpl(rf0, ctx.left); }
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
ɵcontainerRefreshStart(4);
|
||||
{
|
||||
if (ctx.right != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 5, 1);
|
||||
{ TreeTpl(rf0, ctx.right); }
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
}
|
||||
@NgModule({declarations: [TreeComponent], imports: [CommonModule]})
|
||||
export class TreeModule {
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ ng_module(
|
||||
),
|
||||
deps = [
|
||||
"//modules/benchmarks/src/tree:util_lib",
|
||||
"//modules/benchmarks/src/tree/render3:render3_lib",
|
||||
"//modules/benchmarks/src/tree/render3:tree_lib",
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
|
@ -6,9 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ɵrenderComponent as renderComponent} from '@angular/core';
|
||||
import {ɵRenderFlags, ɵcontainer, ɵcontainerRefreshEnd, ɵcontainerRefreshStart, ɵdefineComponent, ɵelementEnd, ɵelementStart, ɵelementStyleProp, ɵelementStyling, ɵembeddedViewEnd, ɵembeddedViewStart, ɵinterpolation1, ɵrenderComponent as renderComponent, ɵtext, ɵtextBinding} from '@angular/core';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {TreeFunction, createDom, destroyDom, detectChanges} from '../render3/tree';
|
||||
import {createDom, destroyDom, detectChanges} from '../render3/tree';
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
|
||||
function noop() {}
|
||||
|
||||
@ -16,14 +18,71 @@ export function main() {
|
||||
let component: TreeFunction;
|
||||
if (typeof window !== 'undefined') {
|
||||
component = renderComponent(TreeFunction);
|
||||
bindAction('#createDom', () => createDom(component));
|
||||
bindAction('#destroyDom', () => destroyDom(component));
|
||||
bindAction('#detectChanges', () => detectChanges(component));
|
||||
bindAction('#createDom', () => createDom(component as any));
|
||||
bindAction('#destroyDom', () => destroyDom(component as any));
|
||||
bindAction('#detectChanges', () => detectChanges(component as any));
|
||||
bindAction(
|
||||
'#detectChangesProfile', profile(() => detectChanges(component), noop, 'detectChanges'));
|
||||
bindAction('#updateDomProfile', profile(() => createDom(component), noop, 'update'));
|
||||
'#detectChangesProfile',
|
||||
profile(() => detectChanges(component as any), noop, 'detectChanges'));
|
||||
bindAction('#updateDomProfile', profile(() => createDom(component as any), noop, 'update'));
|
||||
bindAction(
|
||||
'#createDomProfile',
|
||||
profile(() => createDom(component), () => destroyDom(component), 'create'));
|
||||
profile(() => createDom(component as any), () => destroyDom(component as any), 'create'));
|
||||
}
|
||||
}
|
||||
|
||||
export class TreeFunction {
|
||||
data: TreeNode = emptyTree;
|
||||
|
||||
/** @nocollapse */
|
||||
static ngComponentDef = ɵdefineComponent({
|
||||
type: TreeFunction,
|
||||
selectors: [['tree']],
|
||||
consts: 5,
|
||||
vars: 1,
|
||||
template: function(rf: ɵRenderFlags, ctx: TreeFunction) {
|
||||
// bit of a hack
|
||||
TreeTpl(rf, ctx.data);
|
||||
},
|
||||
factory: () => new TreeFunction,
|
||||
inputs: {data: 'data'}
|
||||
});
|
||||
}
|
||||
|
||||
const c1 = ['background-color'];
|
||||
export function TreeTpl(rf: ɵRenderFlags, ctx: TreeNode) {
|
||||
if (rf & ɵRenderFlags.Create) {
|
||||
ɵelementStart(0, 'tree');
|
||||
{
|
||||
ɵelementStart(1, 'span');
|
||||
ɵelementStyling(null, c1);
|
||||
{ ɵtext(2); }
|
||||
ɵelementEnd();
|
||||
ɵcontainer(3);
|
||||
ɵcontainer(4);
|
||||
}
|
||||
ɵelementEnd();
|
||||
}
|
||||
if (rf & ɵRenderFlags.Update) {
|
||||
ɵelementStyleProp(1, 0, ctx.depth % 2 ? '' : 'grey');
|
||||
ɵtextBinding(2, ɵinterpolation1(' ', ctx.value, ' '));
|
||||
ɵcontainerRefreshStart(3);
|
||||
{
|
||||
if (ctx.left != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 5, 1);
|
||||
{ TreeTpl(rf0, ctx.left); }
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
ɵcontainerRefreshStart(4);
|
||||
{
|
||||
if (ctx.right != null) {
|
||||
let rf0 = ɵembeddedViewStart(0, 5, 1);
|
||||
{ TreeTpl(rf0, ctx.right); }
|
||||
ɵembeddedViewEnd();
|
||||
}
|
||||
}
|
||||
ɵcontainerRefreshEnd();
|
||||
}
|
||||
}
|
||||
|
101
modules/benchmarks/src/tree/tree_perf.spec.ts
Normal file
101
modules/benchmarks/src/tree/tree_perf.spec.ts
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @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 {$, browser} from 'protractor';
|
||||
|
||||
import {openBrowser} from '../../../e2e_util/e2e_util';
|
||||
import {runBenchmark} from '../../../e2e_util/perf_util';
|
||||
|
||||
describe('benchmark render', () => {
|
||||
it('should work for createDestroy', () => {
|
||||
openTreeBenchmark();
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('0');
|
||||
$('#destroyDom').click();
|
||||
expect($('#root').getText() as any).toEqual('');
|
||||
});
|
||||
|
||||
it('should work for update', () => {
|
||||
openTreeBenchmark();
|
||||
$('#createDom').click();
|
||||
$('#createDom').click();
|
||||
expect($('#root').getText()).toContain('A');
|
||||
});
|
||||
|
||||
it('should work for detectChanges', () => {
|
||||
openTreeBenchmark();
|
||||
$('#detectChanges').click();
|
||||
expect($('#numberOfChecks').getText()).toContain('10');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('benchmarks', () => {
|
||||
|
||||
it('should work for createOnly', done => {
|
||||
runTreeBenchmark({
|
||||
id: 'createOnly',
|
||||
prepare: () => $('#destroyDom').click(),
|
||||
work: () => $('#createDom').click()
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should work for destroy', done => {
|
||||
runTreeBenchmark({
|
||||
id: 'createOnly',
|
||||
prepare: () => $('#createDom').click(),
|
||||
work: () => $('#destroyDom').click()
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should work for createDestroy', done => {
|
||||
runTreeBenchmark({
|
||||
id: 'createDestroy',
|
||||
work: () => {
|
||||
$('#destroyDom').click();
|
||||
$('#createDom').click();
|
||||
}
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should work for update', done => {
|
||||
runTreeBenchmark({id: 'update', work: () => $('#createDom').click()}).then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should work for detectChanges', done => {
|
||||
runTreeBenchmark({
|
||||
id: 'detectChanges',
|
||||
work: () => $('#detectChanges').click(),
|
||||
setup: () => $('#destroyDom').click()
|
||||
}).then(done, done.fail);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function runTreeBenchmark({id, prepare, setup, work}:
|
||||
{id: string; prepare ? () : void; setup ? () : void; work(): void;}) {
|
||||
browser.rootEl = '#root';
|
||||
return runBenchmark({
|
||||
id: id,
|
||||
url: '',
|
||||
ignoreBrowserSynchronization: true,
|
||||
params: [{name: 'depth', value: 11}],
|
||||
work: work,
|
||||
prepare: prepare,
|
||||
setup: setup
|
||||
});
|
||||
}
|
||||
|
||||
function openTreeBenchmark() {
|
||||
browser.rootEl = '#root';
|
||||
openBrowser({
|
||||
url: '',
|
||||
ignoreBrowserSynchronization: true,
|
||||
params: [{name: 'depth', value: 4}],
|
||||
});
|
||||
}
|
@ -40,6 +40,7 @@ export function runBenchmark(config: {
|
||||
if (config.setup) {
|
||||
config.setup();
|
||||
}
|
||||
if (!cmdArgs) readCommandLine();
|
||||
const description: {[key: string]: any} = {'bundles': cmdArgs.bundles};
|
||||
config.params.forEach((param) => { description[param.name] = param.value; });
|
||||
return runner.sample({
|
||||
|
96
package.json
96
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "7.0.2",
|
||||
"version": "7.1.0-beta.0",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@ -26,28 +26,43 @@
|
||||
"update-webdriver": "webdriver-manager update --gecko false $CHROMEDRIVER_VERSION_ARG",
|
||||
"check-env": "gulp check-env",
|
||||
"commitmsg": "node ./scripts/git/commit-msg.js",
|
||||
"test-ivy-jit": "bazel test --define=compile=jit --build_tag_filters=-no-ivy-jit,-fixme-ivy-jit --test_tag_filters=-no-ivy-jit,-fixme-ivy-jit",
|
||||
"test-fixme-ivy-jit": "bazel test --define=compile=jit --build_tag_filters=-no-ivy-jit --test_tag_filters=-no-ivy-jit",
|
||||
"test-ivy-aot": "bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot",
|
||||
"test-fixme-ivy-aot": "bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot --test_tag_filters=-no-ivy-aot",
|
||||
"bazel": "bazel"
|
||||
"test-ivy-jit": "bazel test --define=compile=jit --build_tag_filters=ivy-jit --test_tag_filters=ivy-jit",
|
||||
"test-fixme-ivy-jit": "bazel test --define=compile=jit --build_tag_filters=-no-ivy --test_tag_filters=-no-ivy",
|
||||
"test-ivy-aot": "bazel test --define=compile=aot --build_tag_filters=ivy-aot --test_tag_filters=ivy-aot",
|
||||
"test-fixme-ivy-aot": "bazel test --define=compile=aot --build_tag_filters=-no-ivy --test_tag_filters=-no-ivy"
|
||||
},
|
||||
"// 1": "dependencies are used locally and by bazel",
|
||||
"dependencies": {
|
||||
"@angular-devkit/schematics": "^0.5.5",
|
||||
"@bazel/typescript": "0.20.3",
|
||||
"@schematics/angular": "^0.5.4",
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "^6.3.0",
|
||||
"tslib": "^1.7.1",
|
||||
"zone.js": "^0.8.26"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bazel/ibazel": "^0.1.1",
|
||||
"@bazel/karma": "0.20.3",
|
||||
"@bazel/typescript": "0.20.3",
|
||||
"@types/angular": "^1.6.47",
|
||||
"@types/base64-js": "1.2.5",
|
||||
"@types/chokidar": "1.7.3",
|
||||
"@types/convert-source-map": "^1.5.1",
|
||||
"@types/diff": "^3.2.2",
|
||||
"@types/fs-extra": "4.0.2",
|
||||
"@types/hammerjs": "2.0.35",
|
||||
"@types/jasmine": "^2.8.8",
|
||||
"@types/jasminewd2": "^2.0.4",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mock-fs": "^3.6.30",
|
||||
"@types/node": "^10.9.4",
|
||||
"@types/selenium-webdriver": "3.0.7",
|
||||
"@types/shelljs": "^0.7.8",
|
||||
"@types/source-map": "^0.5.1",
|
||||
"@types/systemjs": "0.19.32",
|
||||
"@types/yargs": "^11.1.1",
|
||||
"@webcomponents/custom-elements": "^1.0.4",
|
||||
"angular": "npm:angular@1.7",
|
||||
@ -57,57 +72,23 @@
|
||||
"angular-mocks-1.5": "npm:angular-mocks@1.5",
|
||||
"angular-mocks-1.6": "npm:angular-mocks@1.6",
|
||||
"base64-js": "1.2.1",
|
||||
"canonical-path": "0.0.2",
|
||||
"chokidar": "1.7.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"dependency-graph": "^0.7.2",
|
||||
"domino": "2.1.0",
|
||||
"fs-extra": "4.0.2",
|
||||
"jasmine": "^3.1.0",
|
||||
"jasmine-core": "^3.1.0",
|
||||
"karma": "^2.0.4",
|
||||
"magic-string": "^0.25.0",
|
||||
"minimist": "1.2.0",
|
||||
"mock-fs": "^4.5.0",
|
||||
"node-uuid": "1.4.8",
|
||||
"protractor": "5.1.2",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"selenium-webdriver": "3.5.0",
|
||||
"shelljs": "^0.8.1",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-support": "0.4.18",
|
||||
"tsickle": "0.32.1",
|
||||
"tslib": "^1.7.1",
|
||||
"typescript": "~3.1.1",
|
||||
"xhr2": "0.1.4",
|
||||
"yargs": "9.0.1",
|
||||
"zone.js": "^0.8.26"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "1.1.2"
|
||||
},
|
||||
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
|
||||
"devDependencies": {
|
||||
"@bazel/bazel": "^0.18.1",
|
||||
"@bazel/ibazel": "^0.1.1",
|
||||
"@bazel/karma": "0.20.3",
|
||||
"@types/angular": "^1.6.47",
|
||||
"@types/base64-js": "1.2.5",
|
||||
"@types/jasminewd2": "^2.0.4",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/systemjs": "0.19.32",
|
||||
"bower": "1.8.2",
|
||||
"browserstacktunnel-wrapper": "2.0.1",
|
||||
"canonical-path": "0.0.2",
|
||||
"chokidar": "1.7.0",
|
||||
"clang-format": "1.0.41",
|
||||
"cldr": "4.10.0",
|
||||
"cldr-data-downloader": "0.3.2",
|
||||
"cldrjs": "0.5.0",
|
||||
"conventional-changelog": "^2.0.3",
|
||||
"core-js": "^2.4.1",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"cors": "2.8.4",
|
||||
"dependency-graph": "^0.7.2",
|
||||
"diff": "^3.5.0",
|
||||
"domino": "2.1.0",
|
||||
"entities": "1.1.1",
|
||||
"firefox-profile": "1.0.3",
|
||||
"fs-extra": "4.0.2",
|
||||
"glob": "7.1.2",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-clang-format": "1.0.23",
|
||||
@ -119,29 +100,44 @@
|
||||
"hammerjs": "2.0.8",
|
||||
"husky": "^0.14.3",
|
||||
"incremental-dom": "0.4.1",
|
||||
"jasmine": "^3.1.0",
|
||||
"jasmine-core": "^3.1.0",
|
||||
"jpm": "1.3.1",
|
||||
"karma": "^2.0.4",
|
||||
"karma-browserstack-launcher": "^1.3.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-sauce-launcher": "^1.2.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"madge": "0.5.0",
|
||||
"magic-string": "^0.25.0",
|
||||
"minimist": "1.2.0",
|
||||
"mock-fs": "^4.5.0",
|
||||
"mutation-observer": "^1.0.3",
|
||||
"node-uuid": "1.4.8",
|
||||
"protractor": "5.1.2",
|
||||
"rewire": "2.5.2",
|
||||
"rollup": "0.47.4",
|
||||
"rollup-plugin-commonjs": "8.1.0",
|
||||
"rollup-plugin-node-resolve": "3.0.0",
|
||||
"rollup-plugin-sourcemaps": "0.4.2",
|
||||
"rxjs": "^6.3.0",
|
||||
"selenium-webdriver": "3.5.0",
|
||||
"semver": "5.4.1",
|
||||
"shelljs": "^0.8.1",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-support": "0.4.18",
|
||||
"systemjs": "0.18.10",
|
||||
"tsickle": "0.32.1",
|
||||
"tslint": "5.7.0",
|
||||
"tslint-eslint-rules": "4.1.1",
|
||||
"tsutils": "2.27.2",
|
||||
"typescript": "~3.1.1",
|
||||
"uglify-es": "^3.3.9",
|
||||
"universal-analytics": "0.4.15",
|
||||
"vlq": "0.2.2",
|
||||
"vrsource-tslint-rules": "5.1.1",
|
||||
"webpack": "1.12.9"
|
||||
"webpack": "1.12.9",
|
||||
"xhr2": "0.1.4",
|
||||
"yargs": "9.0.1"
|
||||
}
|
||||
}
|
||||
|
@ -22,4 +22,4 @@ protractor_web_test = _protractor_web_test
|
||||
protractor_web_test_suite = _protractor_web_test_suite
|
||||
ng_setup_workspace = _ng_setup_workspace
|
||||
# DO NOT ADD PUBLIC API without including in the documentation generation
|
||||
# Run `yarn bazel build //packages/bazel/docs` to verify
|
||||
# Run `bazel build //packages/bazel/docs` to verify
|
||||
|
@ -22,13 +22,6 @@ def rules_angular_dependencies():
|
||||
# Download Bazel toolchain dependencies as needed by build actions
|
||||
#
|
||||
# TODO(gmagolan): updated to next tagged rules_typescript release
|
||||
_maybe(
|
||||
http_archive,
|
||||
name = "build_bazel_rules_nodejs",
|
||||
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.15.3.zip",
|
||||
strip_prefix = "rules_nodejs-0.15.3",
|
||||
)
|
||||
|
||||
_maybe(
|
||||
http_archive,
|
||||
name = "build_bazel_rules_typescript",
|
||||
@ -87,11 +80,16 @@ def rules_angular_dev_dependencies():
|
||||
url = "https://github.com/bazelbuild/bazel/archive/0.18.0.zip",
|
||||
)
|
||||
|
||||
# This commit matches the version of buildifier in angular/ngcontainer
|
||||
# If you change this, also check if it matches the version in the angular/ngcontainer
|
||||
# version in /.circleci/config.yml
|
||||
BAZEL_BUILDTOOLS_VERSION = "49a6c199e3fbf5d94534b2771868677d3f9c6de9"
|
||||
|
||||
http_archive(
|
||||
name = "com_github_bazelbuild_buildtools",
|
||||
sha256 = "a82d4b353942b10c1535528b02bff261d020827c9c57e112569eddcb1c93d7f6",
|
||||
strip_prefix = "buildtools-0.17.2",
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/0.17.2.zip",
|
||||
sha256 = "edf39af5fc257521e4af4c40829fffe8fba6d0ebff9f4dd69a6f8f1223ae047b",
|
||||
strip_prefix = "buildtools-%s" % BAZEL_BUILDTOOLS_VERSION,
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/%s.zip" % BAZEL_BUILDTOOLS_VERSION,
|
||||
)
|
||||
|
||||
#############################################
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import * as ng from '@angular/compiler-cli';
|
||||
import {BazelOptions, CachedFileLoader, CompilerHost, FileCache, FileLoader, UncachedFileLoader, constructManifest, debug, fixUmdModuleDeclarations, parseTsconfig, resolveNormalizedPath, runAsWorker, runWorkerLoop} from '@bazel/typescript';
|
||||
import {BazelOptions, CachedFileLoader, CompilerHost, FileCache, FileLoader, UncachedFileLoader, constructManifest, debug, parseTsconfig, resolveNormalizedPath, runAsWorker, runWorkerLoop} from '@bazel/typescript';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as tsickle from 'tsickle';
|
||||
@ -209,20 +209,16 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
|
||||
// compilationTargetSrc.
|
||||
// However we still want to give it an AMD module name for devmode.
|
||||
// We can't easily tell which file is the synthetic one, so we build up the path we expect
|
||||
// it to have and compare against that.
|
||||
// it to have
|
||||
// and compare against that.
|
||||
if (fileName ===
|
||||
path.join(compilerOpts.baseUrl, bazelOpts.package, compilerOpts.flatModuleOutFile + '.ts'))
|
||||
return true;
|
||||
// Also handle the case the target is in an external repository.
|
||||
// Pull the workspace name from the target which is formatted as `@wksp//package:target`
|
||||
// if it the target is from an external workspace. If the target is from the local
|
||||
// workspace then it will be formatted as `//package:target`.
|
||||
const targetWorkspace = bazelOpts.target.split('/')[0].replace(/^@/, '');
|
||||
if (targetWorkspace &&
|
||||
fileName ===
|
||||
path.join(
|
||||
compilerOpts.baseUrl, 'external', targetWorkspace, bazelOpts.package,
|
||||
compilerOpts.flatModuleOutFile + '.ts'))
|
||||
// Also handle the case when angular is built from source as an external repository
|
||||
if (fileName ===
|
||||
path.join(
|
||||
compilerOpts.baseUrl, 'external/angular', bazelOpts.package,
|
||||
compilerOpts.flatModuleOutFile + '.ts'))
|
||||
return true;
|
||||
return origBazelHostShouldNameModule(fileName) || NGC_GEN_FILES.test(fileName);
|
||||
};
|
||||
@ -295,10 +291,7 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
|
||||
program, bazelHost, bazelHost, compilerOpts, targetSourceFile, writeFile,
|
||||
cancellationToken, emitOnlyDtsFiles, {
|
||||
beforeTs: customTransformers.before,
|
||||
afterTs: [
|
||||
...(customTransformers.after || []),
|
||||
fixUmdModuleDeclarations((sf: ts.SourceFile) => bazelHost.amdModuleName(sf)),
|
||||
],
|
||||
afterTs: customTransformers.after,
|
||||
});
|
||||
|
||||
if (!gatherDiagnostics) {
|
||||
|
@ -101,7 +101,7 @@ function runPackageGoldTest(testPackage: TestPackage) {
|
||||
` Diff:\n` +
|
||||
` ${patch}\n\n` +
|
||||
` To accept the new golden file, run:\n` +
|
||||
` yarn bazel run ${process.env['BAZEL_TARGET']}.accept\n`;
|
||||
` bazel run ${process.env['BAZEL_TARGET']}.accept\n`;
|
||||
|
||||
fail(failureMessage);
|
||||
}
|
||||
|
@ -15,6 +15,5 @@ ts_library(
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
"@ngdeps//@types/node",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
@ -26,8 +26,9 @@ ts_library(
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/annotations",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/factories",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/shims",
|
||||
"//packages/compiler-cli/src/ngtsc/switch",
|
||||
"//packages/compiler-cli/src/ngtsc/transform",
|
||||
"//packages/compiler-cli/src/ngtsc/typecheck",
|
||||
"@ngdeps//@bazel/typescript",
|
||||
|
@ -2,7 +2,6 @@ load("//packages/bazel:index.bzl", "ng_module")
|
||||
|
||||
ng_module(
|
||||
name = "test_module",
|
||||
testonly = True,
|
||||
srcs = glob(["*.ts"]),
|
||||
compiler = "//packages/bazel/src/ngc-wrapped",
|
||||
entry_point = "index.ts",
|
||||
@ -10,10 +9,6 @@ ng_module(
|
||||
module_name = "some_npm_module",
|
||||
ng_xi18n = "//packages/bazel/src/ngc-wrapped:xi18n",
|
||||
node_modules = "@ngdeps//typescript:typescript__typings",
|
||||
tags = [
|
||||
"fixme-ivy-aot",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
"@ngdeps//@types",
|
||||
@ -24,7 +19,6 @@ load(":extract_flat_module_index.bzl", "extract_flat_module_index")
|
||||
|
||||
extract_flat_module_index(
|
||||
name = "flat_module_index",
|
||||
testonly = True,
|
||||
deps = [":test_module"],
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ This conversion will allow such "legacy" packages to be used by the Ivy renderin
|
||||
The project is built using Bazel:
|
||||
|
||||
```bash
|
||||
yarn bazel build //packages/compiler-cli/src/ngcc
|
||||
bazel build //packages/compiler-cli/src/ngcc
|
||||
```
|
||||
|
||||
## Unit Testing
|
||||
@ -18,7 +18,7 @@ yarn bazel build //packages/compiler-cli/src/ngcc
|
||||
The unit tests are built and run using Bazel:
|
||||
|
||||
```bash
|
||||
yarn bazel test //packages/compiler-cli/src/ngcc/test
|
||||
bazel test //packages/compiler-cli/src/ngcc/test
|
||||
```
|
||||
|
||||
## Integration Testing
|
||||
@ -26,5 +26,5 @@ yarn bazel test //packages/compiler-cli/src/ngcc/test
|
||||
There are tests that check the behaviour of the overall executable:
|
||||
|
||||
```bash
|
||||
yarn bazel test //packages/compiler-cli/test/ngcc
|
||||
bazel test //packages/compiler-cli/test/ngcc
|
||||
```
|
||||
|
@ -9,8 +9,8 @@ import * as ts from 'typescript';
|
||||
import {ReflectionHost} from '../../../ngtsc/host';
|
||||
import {DecoratedFile} from './decorated_file';
|
||||
|
||||
export const PRE_NGCC_MARKER = '__PRE_NGCC__';
|
||||
export const POST_NGCC_MARKER = '__POST_NGCC__';
|
||||
export const PRE_NGCC_MARKER = '__PRE_R3__';
|
||||
export const POST_NGCC_MARKER = '__POST_R3__';
|
||||
|
||||
export type SwitchableVariableDeclaration = ts.VariableDeclaration & {initializer: ts.Identifier};
|
||||
export function isSwitchableVariableDeclaration(node: ts.Node):
|
||||
|
@ -30,15 +30,15 @@ const TEST_PROGRAM = [
|
||||
name: 'b.js',
|
||||
contents: `
|
||||
export const b = 42;
|
||||
var factoryB = factory__PRE_NGCC__;
|
||||
var factoryB = factory__PRE_R3__;
|
||||
`
|
||||
},
|
||||
{
|
||||
name: 'c.js',
|
||||
contents: `
|
||||
export const c = 'So long, and thanks for all the fish!';
|
||||
var factoryC = factory__PRE_NGCC__;
|
||||
var factoryD = factory__PRE_NGCC__;
|
||||
var factoryC = factory__PRE_R3__;
|
||||
var factoryD = factory__PRE_R3__;
|
||||
`
|
||||
},
|
||||
];
|
||||
@ -62,14 +62,14 @@ describe('SwitchMarkerAnalyzer', () => {
|
||||
expect(analysis.has(b)).toBe(true);
|
||||
expect(analysis.get(b) !.sourceFile).toBe(b);
|
||||
expect(analysis.get(b) !.declarations.map(decl => decl.getText())).toEqual([
|
||||
'factoryB = factory__PRE_NGCC__'
|
||||
'factoryB = factory__PRE_R3__'
|
||||
]);
|
||||
|
||||
expect(analysis.has(c)).toBe(true);
|
||||
expect(analysis.get(c) !.sourceFile).toBe(c);
|
||||
expect(analysis.get(c) !.declarations.map(decl => decl.getText())).toEqual([
|
||||
'factoryC = factory__PRE_NGCC__',
|
||||
'factoryD = factory__PRE_NGCC__',
|
||||
'factoryC = factory__PRE_R3__',
|
||||
'factoryD = factory__PRE_R3__',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -35,15 +35,15 @@ const CLASSES = [
|
||||
const MARKER_FILE = {
|
||||
name: '/marker.js',
|
||||
contents: `
|
||||
let compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;
|
||||
let compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;
|
||||
|
||||
function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
|
||||
const compilerFactory = injector.get(CompilerFactory);
|
||||
const compiler = compilerFactory.createCompiler([options]);
|
||||
return compiler.compileModuleAsync(moduleType);
|
||||
}
|
||||
|
||||
function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
|
||||
ngDevMode && assertNgModuleType(moduleType);
|
||||
return Promise.resolve(new R3NgModuleFactory(moduleType));
|
||||
}
|
||||
@ -113,7 +113,7 @@ describe('Esm2015ReflectionHost', () => {
|
||||
const file = program.getSourceFile(MARKER_FILE.name) !;
|
||||
const declarations = host.getSwitchableDeclarations(file);
|
||||
expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([
|
||||
['compileNgModuleFactory', 'compileNgModuleFactory__PRE_NGCC__']
|
||||
['compileNgModuleFactory', 'compileNgModuleFactory__PRE_R3__']
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -377,15 +377,15 @@ const FUNCTION_BODY_FILE = {
|
||||
const MARKER_FILE = {
|
||||
name: '/marker.js',
|
||||
contents: `
|
||||
var compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;
|
||||
var compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;
|
||||
|
||||
function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
|
||||
var compilerFactory = injector.get(CompilerFactory);
|
||||
var compiler = compilerFactory.createCompiler([options]);
|
||||
return compiler.compileModuleAsync(moduleType);
|
||||
}
|
||||
|
||||
function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
|
||||
ngDevMode && assertNgModuleType(moduleType);
|
||||
return Promise.resolve(new R3NgModuleFactory(moduleType));
|
||||
}
|
||||
@ -1179,7 +1179,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
const file = program.getSourceFile(MARKER_FILE.name) !;
|
||||
const declarations = host.getSwitchableDeclarations(file);
|
||||
expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([
|
||||
['compileNgModuleFactory', 'compileNgModuleFactory__PRE_NGCC__']
|
||||
['compileNgModuleFactory', 'compileNgModuleFactory__PRE_R3__']
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -48,16 +48,16 @@ export class C {}
|
||||
C.decorators = [
|
||||
{ type: Directive, args: [{ selector: '[c]' }] },
|
||||
];
|
||||
let compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;
|
||||
let badlyFormattedVariable = __PRE_NGCC__badlyFormattedVariable;
|
||||
let compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;
|
||||
let badlyFormattedVariable = __PRE_R3__badlyFormattedVariable;
|
||||
|
||||
function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
|
||||
const compilerFactory = injector.get(CompilerFactory);
|
||||
const compiler = compilerFactory.createCompiler([options]);
|
||||
return compiler.compileModuleAsync(moduleType);
|
||||
}
|
||||
|
||||
function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
|
||||
ngDevMode && assertNgModuleType(moduleType);
|
||||
return Promise.resolve(new R3NgModuleFactory(moduleType));
|
||||
}
|
||||
@ -146,17 +146,15 @@ export class A {}`);
|
||||
renderer.rewriteSwitchableDeclarations(
|
||||
output, file, switchMarkerAnalyses.get(sourceFile) !.declarations);
|
||||
expect(output.toString())
|
||||
.not.toContain(`let compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;`);
|
||||
.not.toContain(`let compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;`);
|
||||
expect(output.toString())
|
||||
.toContain(`let badlyFormattedVariable = __PRE_NGCC__badlyFormattedVariable;`);
|
||||
.toContain(`let badlyFormattedVariable = __PRE_R3__badlyFormattedVariable;`);
|
||||
expect(output.toString())
|
||||
.toContain(`let compileNgModuleFactory = compileNgModuleFactory__POST_NGCC__;`);
|
||||
.toContain(`let compileNgModuleFactory = compileNgModuleFactory__POST_R3__;`);
|
||||
expect(output.toString())
|
||||
.toContain(
|
||||
`function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {`);
|
||||
.toContain(`function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {`);
|
||||
expect(output.toString())
|
||||
.toContain(
|
||||
`function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {`);
|
||||
.toContain(`function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -55,15 +55,15 @@ var C = (function() {
|
||||
return C;
|
||||
}());
|
||||
|
||||
var compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;
|
||||
var badlyFormattedVariable = __PRE_NGCC__badlyFormattedVariable;
|
||||
function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {
|
||||
var compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;
|
||||
var badlyFormattedVariable = __PRE_R3__badlyFormattedVariable;
|
||||
function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
|
||||
const compilerFactory = injector.get(CompilerFactory);
|
||||
const compiler = compilerFactory.createCompiler([options]);
|
||||
return compiler.compileModuleAsync(moduleType);
|
||||
}
|
||||
|
||||
function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {
|
||||
function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
|
||||
ngDevMode && assertNgModuleType(moduleType);
|
||||
return Promise.resolve(new R3NgModuleFactory(moduleType));
|
||||
}
|
||||
@ -166,17 +166,15 @@ var A = (function() {`);
|
||||
renderer.rewriteSwitchableDeclarations(
|
||||
output, file, switchMarkerAnalyses.get(sourceFile) !.declarations);
|
||||
expect(output.toString())
|
||||
.not.toContain(`var compileNgModuleFactory = compileNgModuleFactory__PRE_NGCC__;`);
|
||||
.not.toContain(`var compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;`);
|
||||
expect(output.toString())
|
||||
.toContain(`var badlyFormattedVariable = __PRE_NGCC__badlyFormattedVariable;`);
|
||||
.toContain(`var badlyFormattedVariable = __PRE_R3__badlyFormattedVariable;`);
|
||||
expect(output.toString())
|
||||
.toContain(`var compileNgModuleFactory = compileNgModuleFactory__POST_NGCC__;`);
|
||||
.toContain(`var compileNgModuleFactory = compileNgModuleFactory__POST_R3__;`);
|
||||
expect(output.toString())
|
||||
.toContain(
|
||||
`function compileNgModuleFactory__PRE_NGCC__(injector, options, moduleType) {`);
|
||||
.toContain(`function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {`);
|
||||
expect(output.toString())
|
||||
.toContain(
|
||||
`function compileNgModuleFactory__POST_NGCC__(injector, options, moduleType) {`);
|
||||
.toContain(`function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -128,7 +128,7 @@ describe('Renderer', () => {
|
||||
}));
|
||||
expect(addDefinitionsSpy.calls.first().args[2])
|
||||
.toEqual(
|
||||
`A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""]], factory: function A_Factory(t) { return new (t || A)(); }, features: [ɵngcc0.ɵPublicFeature] });`);
|
||||
`A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""]], factory: function A_Factory(t) { return new (t || A)(); } });`);
|
||||
});
|
||||
|
||||
it('should call removeDecorators with the source code, a map of class decorators that have been analyzed',
|
||||
|
@ -118,6 +118,10 @@ export class ComponentDecoratorHandler implements
|
||||
preserveWhitespaces = value;
|
||||
}
|
||||
|
||||
const viewProviders: Expression|null = component.has('viewProviders') ?
|
||||
new WrappedNodeExpr(component.get('viewProviders') !) :
|
||||
null;
|
||||
|
||||
// Go through the root directories for this project, and select the one with the smallest
|
||||
// relative path representation.
|
||||
const filePath = node.getSourceFile().fileName;
|
||||
@ -202,7 +206,7 @@ export class ComponentDecoratorHandler implements
|
||||
directives: EMPTY_MAP,
|
||||
wrapDirectivesInClosure: false, //
|
||||
animations,
|
||||
viewProviders: null,
|
||||
viewProviders
|
||||
},
|
||||
parsedTemplate: template.nodes,
|
||||
},
|
||||
|
@ -146,6 +146,9 @@ export function extractDirectiveMetadata(
|
||||
|
||||
const host = extractHostBindings(directive, decoratedElements, reflector, checker, coreModule);
|
||||
|
||||
const providers: Expression|null =
|
||||
directive.has('providers') ? new WrappedNodeExpr(directive.get('providers') !) : null;
|
||||
|
||||
// Determine if `ngOnChanges` is a lifecycle hook defined on the component.
|
||||
const usesOnChanges = members.some(
|
||||
member => !member.isStatic && member.kind === ClassMemberKind.Method &&
|
||||
@ -176,8 +179,7 @@ export function extractDirectiveMetadata(
|
||||
outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector,
|
||||
type: new WrappedNodeExpr(clazz.name !),
|
||||
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
|
||||
typeSourceSpan: null !, usesInheritance, exportAs,
|
||||
providers: null,
|
||||
typeSourceSpan: null !, usesInheritance, exportAs, providers
|
||||
};
|
||||
return {decoratedElements, decorator: directive, metadata};
|
||||
}
|
||||
@ -328,7 +330,7 @@ function parseFieldToPropertyMapping(
|
||||
*/
|
||||
function parseDecoratedFields(
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker) {
|
||||
checker: ts.TypeChecker): {[field: string]: string} {
|
||||
return fields.reduce(
|
||||
(results, field) => {
|
||||
const fieldName = field.member.name;
|
||||
@ -354,14 +356,6 @@ function parseDecoratedFields(
|
||||
{} as{[field: string]: string});
|
||||
}
|
||||
|
||||
function resolveInput(publicName: string, internalName: string): [string, string] {
|
||||
return [publicName, internalName];
|
||||
}
|
||||
|
||||
function resolveOutput(publicName: string, internalName: string) {
|
||||
return publicName;
|
||||
}
|
||||
|
||||
export function queriesFromFields(
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker): R3QueryMetadata[] {
|
||||
|
@ -64,18 +64,6 @@ export function getConstructorDependencies(
|
||||
ErrorCode.PARAM_MISSING_TOKEN, param.nameNode,
|
||||
`No suitable token for parameter ${param.name || idx} of class ${clazz.name!.text}`);
|
||||
}
|
||||
if (ts.isIdentifier(tokenExpr)) {
|
||||
const importedSymbol = reflector.getImportOfIdentifier(tokenExpr);
|
||||
if (importedSymbol !== null && importedSymbol.from === '@angular/core') {
|
||||
switch (importedSymbol.name) {
|
||||
case 'Injector':
|
||||
resolved = R3ResolvedDependencyType.Injector;
|
||||
break;
|
||||
default:
|
||||
// Leave as a Token or Attribute.
|
||||
}
|
||||
}
|
||||
}
|
||||
const token = new WrappedNodeExpr(tokenExpr);
|
||||
useType.push({token, optional, self, skipSelf, host, resolved});
|
||||
});
|
||||
|
@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @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 * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
const TS_DTS_SUFFIX = /(\.d)?\.ts$/;
|
||||
|
||||
/**
|
||||
* Generates ts.SourceFiles which contain variable declarations for NgFactories for every exported
|
||||
* class of an input ts.SourceFile.
|
||||
*/
|
||||
export class FactoryGenerator {
|
||||
factoryFor(original: ts.SourceFile, genFilePath: string): ts.SourceFile {
|
||||
const relativePathToSource =
|
||||
'./' + path.posix.basename(original.fileName).replace(TS_DTS_SUFFIX, '');
|
||||
// Collect a list of classes that need to have factory types emitted for them.
|
||||
const symbolNames = original
|
||||
.statements
|
||||
// Pick out top level class declarations...
|
||||
.filter(ts.isClassDeclaration)
|
||||
// which are named, exported, and have decorators.
|
||||
.filter(
|
||||
decl => isExported(decl) && decl.decorators !== undefined &&
|
||||
decl.name !== undefined)
|
||||
// Grab the symbol name.
|
||||
.map(decl => decl.name !.text);
|
||||
|
||||
// For each symbol name, generate a constant export of the corresponding NgFactory.
|
||||
// This will encompass a lot of symbols which don't need factories, but that's okay
|
||||
// because it won't miss any that do.
|
||||
const varLines = symbolNames.map(
|
||||
name => `export const ${name}NgFactory = new i0.ɵNgModuleFactory(${name});`);
|
||||
const sourceText = [
|
||||
// This might be incorrect if the current package being compiled is Angular core, but it's
|
||||
// okay to leave in at type checking time. TypeScript can handle this reference via its path
|
||||
// mapping, but downstream bundlers can't. If the current package is core itself, this will be
|
||||
// replaced in the factory transformer before emit.
|
||||
`import * as i0 from '@angular/core';`,
|
||||
`import {${symbolNames.join(', ')}} from '${relativePathToSource}';`,
|
||||
...varLines,
|
||||
].join('\n');
|
||||
return ts.createSourceFile(
|
||||
genFilePath, sourceText, original.languageVersion, true, ts.ScriptKind.TS);
|
||||
}
|
||||
|
||||
computeFactoryFileMap(files: ReadonlyArray<string>): Map<string, string> {
|
||||
const map = new Map<string, string>();
|
||||
files.filter(sourceFile => !sourceFile.endsWith('.d.ts'))
|
||||
.forEach(sourceFile => map.set(sourceFile.replace(/\.ts$/, '.ngfactory.ts'), sourceFile));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
function isExported(decl: ts.Declaration): boolean {
|
||||
return decl.modifiers !== undefined &&
|
||||
decl.modifiers.some(mod => mod.kind == ts.SyntaxKind.ExportKeyword);
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/**
|
||||
* @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 * as ts from 'typescript';
|
||||
|
||||
import {relativePathBetween} from '../../util/src/path';
|
||||
|
||||
const STRIP_NG_FACTORY = /(.*)NgFactory$/;
|
||||
|
||||
export interface FactoryInfo {
|
||||
sourceFilePath: string;
|
||||
moduleSymbolNames: Set<string>;
|
||||
}
|
||||
|
||||
export function generatedFactoryTransform(
|
||||
factoryMap: Map<string, FactoryInfo>,
|
||||
coreImportsFrom: ts.SourceFile | null): ts.TransformerFactory<ts.SourceFile> {
|
||||
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
|
||||
return (file: ts.SourceFile): ts.SourceFile => {
|
||||
return transformFactorySourceFile(factoryMap, context, coreImportsFrom, file);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function transformFactorySourceFile(
|
||||
factoryMap: Map<string, FactoryInfo>, context: ts.TransformationContext,
|
||||
coreImportsFrom: ts.SourceFile | null, file: ts.SourceFile): ts.SourceFile {
|
||||
// If this is not a generated file, it won't have factory info associated with it.
|
||||
if (!factoryMap.has(file.fileName)) {
|
||||
// Don't transform non-generated code.
|
||||
return file;
|
||||
}
|
||||
|
||||
const {moduleSymbolNames, sourceFilePath} = factoryMap.get(file.fileName) !;
|
||||
|
||||
const clone = ts.getMutableClone(file);
|
||||
|
||||
const transformedStatements = file.statements.map(stmt => {
|
||||
if (coreImportsFrom !== null && ts.isImportDeclaration(stmt) &&
|
||||
ts.isStringLiteral(stmt.moduleSpecifier) && stmt.moduleSpecifier.text === '@angular/core') {
|
||||
const path = relativePathBetween(sourceFilePath, coreImportsFrom.fileName);
|
||||
if (path !== null) {
|
||||
return ts.updateImportDeclaration(
|
||||
stmt, stmt.decorators, stmt.modifiers, stmt.importClause, ts.createStringLiteral(path));
|
||||
} else {
|
||||
return ts.createNotEmittedStatement(stmt);
|
||||
}
|
||||
} else if (ts.isVariableStatement(stmt) && stmt.declarationList.declarations.length === 1) {
|
||||
const decl = stmt.declarationList.declarations[0];
|
||||
if (ts.isIdentifier(decl.name)) {
|
||||
const match = STRIP_NG_FACTORY.exec(decl.name.text);
|
||||
if (match === null || !moduleSymbolNames.has(match[1])) {
|
||||
// Remove the given factory as it wasn't actually for an NgModule.
|
||||
return ts.createNotEmittedStatement(stmt);
|
||||
}
|
||||
}
|
||||
return stmt;
|
||||
} else {
|
||||
return stmt;
|
||||
}
|
||||
});
|
||||
if (!transformedStatements.some(ts.isVariableStatement)) {
|
||||
// If the resulting file has no factories, include an empty export to
|
||||
// satisfy closure compiler.
|
||||
transformedStatements.push(ts.createVariableStatement(
|
||||
[ts.createModifier(ts.SyntaxKind.ExportKeyword)],
|
||||
ts.createVariableDeclarationList(
|
||||
[ts.createVariableDeclaration('ɵNonEmptyModule', undefined, ts.createTrue())],
|
||||
ts.NodeFlags.Const)));
|
||||
}
|
||||
clone.statements = ts.createNodeArray(transformedStatements);
|
||||
return clone;
|
||||
}
|
@ -15,9 +15,10 @@ import {nocollapseHack} from '../transformers/nocollapse_hack';
|
||||
|
||||
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ResourceLoader, SelectorScopeRegistry} from './annotations';
|
||||
import {BaseDefDecoratorHandler} from './annotations/src/base_def';
|
||||
import {FactoryGenerator, FactoryInfo, GeneratedFactoryHostWrapper, generatedFactoryTransform} from './factories';
|
||||
import {TypeScriptReflectionHost} from './metadata';
|
||||
import {FileResourceLoader, HostResourceLoader} from './resource_loader';
|
||||
import {FactoryGenerator, FactoryInfo, GeneratedShimsHostWrapper, SummaryGenerator, generatedFactoryTransform} from './shims';
|
||||
import {ivySwitchTransform} from './switch';
|
||||
import {IvyCompilation, ivyTransformFactory} from './transform';
|
||||
import {TypeCheckContext, TypeCheckProgramHost} from './typecheck';
|
||||
|
||||
@ -50,13 +51,16 @@ export class NgtscProgram implements api.Program {
|
||||
this.resourceLoader = host.readResource !== undefined ?
|
||||
new HostResourceLoader(host.readResource.bind(host)) :
|
||||
new FileResourceLoader();
|
||||
const shouldGenerateFactories = options.allowEmptyCodegenFiles || false;
|
||||
const shouldGenerateShims = options.allowEmptyCodegenFiles || false;
|
||||
this.host = host;
|
||||
let rootFiles = [...rootNames];
|
||||
if (shouldGenerateFactories) {
|
||||
const generator = new FactoryGenerator();
|
||||
const factoryFileMap = generator.computeFactoryFileMap(rootNames);
|
||||
rootFiles.push(...Array.from(factoryFileMap.keys()));
|
||||
if (shouldGenerateShims) {
|
||||
// Summary generation.
|
||||
const summaryGenerator = SummaryGenerator.forRootFiles(rootNames);
|
||||
|
||||
// Factory generation.
|
||||
const factoryGenerator = FactoryGenerator.forRootFiles(rootNames);
|
||||
const factoryFileMap = factoryGenerator.factoryFileMap;
|
||||
this.factoryToSourceInfo = new Map<string, FactoryInfo>();
|
||||
this.sourceToFactorySymbols = new Map<string, Set<string>>();
|
||||
factoryFileMap.forEach((sourceFilePath, factoryPath) => {
|
||||
@ -64,7 +68,10 @@ export class NgtscProgram implements api.Program {
|
||||
this.sourceToFactorySymbols !.set(sourceFilePath, moduleSymbolNames);
|
||||
this.factoryToSourceInfo !.set(factoryPath, {sourceFilePath, moduleSymbolNames});
|
||||
});
|
||||
this.host = new GeneratedFactoryHostWrapper(host, generator, factoryFileMap);
|
||||
|
||||
const factoryFileNames = Array.from(factoryFileMap.keys());
|
||||
rootFiles.push(...factoryFileNames, ...summaryGenerator.getSummaryFileNames());
|
||||
this.host = new GeneratedShimsHostWrapper(host, [summaryGenerator, factoryGenerator]);
|
||||
}
|
||||
|
||||
this.tsProgram =
|
||||
@ -177,6 +184,9 @@ export class NgtscProgram implements api.Program {
|
||||
if (this.factoryToSourceInfo !== null) {
|
||||
transforms.push(generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom));
|
||||
}
|
||||
if (this.isCore) {
|
||||
transforms.push(ivySwitchTransform);
|
||||
}
|
||||
// Run the emit, including a custom transformer that will downlevel the Ivy decorators in code.
|
||||
const emitResult = emitCallback({
|
||||
program: this.tsProgram,
|
||||
|
@ -3,12 +3,12 @@ package(default_visibility = ["//visibility:public"])
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "factories",
|
||||
name = "shims",
|
||||
srcs = glob([
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/factories",
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/shims",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/host",
|
@ -8,6 +8,6 @@
|
||||
|
||||
/// <reference types="node" />
|
||||
|
||||
export {FactoryGenerator} from './src/generator';
|
||||
export {GeneratedFactoryHostWrapper} from './src/host';
|
||||
export {FactoryInfo, generatedFactoryTransform} from './src/transform';
|
||||
export {FactoryGenerator, FactoryInfo, generatedFactoryTransform} from './src/factory_generator';
|
||||
export {GeneratedShimsHostWrapper} from './src/host';
|
||||
export {SummaryGenerator} from './src/summary_generator';
|
144
packages/compiler-cli/src/ngtsc/shims/src/factory_generator.ts
Normal file
144
packages/compiler-cli/src/ngtsc/shims/src/factory_generator.ts
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @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 * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {relativePathBetween} from '../../util/src/path';
|
||||
|
||||
import {ShimGenerator} from './host';
|
||||
import {isNonDeclarationTsFile} from './util';
|
||||
|
||||
const TS_DTS_SUFFIX = /(\.d)?\.ts$/;
|
||||
const STRIP_NG_FACTORY = /(.*)NgFactory$/;
|
||||
|
||||
/**
|
||||
* Generates ts.SourceFiles which contain variable declarations for NgFactories for every exported
|
||||
* class of an input ts.SourceFile.
|
||||
*/
|
||||
export class FactoryGenerator implements ShimGenerator {
|
||||
private constructor(private map: Map<string, string>) {}
|
||||
|
||||
get factoryFileMap(): Map<string, string> { return this.map; }
|
||||
|
||||
getOriginalSourceOfShim(fileName: string): string|null { return this.map.get(fileName) || null; }
|
||||
|
||||
generate(original: ts.SourceFile, genFilePath: string): ts.SourceFile {
|
||||
const relativePathToSource =
|
||||
'./' + path.posix.basename(original.fileName).replace(TS_DTS_SUFFIX, '');
|
||||
// Collect a list of classes that need to have factory types emitted for them. This list is
|
||||
// overly broad as at this point the ts.TypeChecker hasn't been created, and can't be used to
|
||||
// semantically understand which decorated types are actually decorated with Angular decorators.
|
||||
//
|
||||
// The exports generated here are pruned in the factory transform during emit.
|
||||
const symbolNames = original
|
||||
.statements
|
||||
// Pick out top level class declarations...
|
||||
.filter(ts.isClassDeclaration)
|
||||
// which are named, exported, and have decorators.
|
||||
.filter(
|
||||
decl => isExported(decl) && decl.decorators !== undefined &&
|
||||
decl.name !== undefined)
|
||||
// Grab the symbol name.
|
||||
.map(decl => decl.name !.text);
|
||||
|
||||
// For each symbol name, generate a constant export of the corresponding NgFactory.
|
||||
// This will encompass a lot of symbols which don't need factories, but that's okay
|
||||
// because it won't miss any that do.
|
||||
const varLines = symbolNames.map(
|
||||
name => `export const ${name}NgFactory = new i0.ɵNgModuleFactory(${name});`);
|
||||
const sourceText = [
|
||||
// This might be incorrect if the current package being compiled is Angular core, but it's
|
||||
// okay to leave in at type checking time. TypeScript can handle this reference via its path
|
||||
// mapping, but downstream bundlers can't. If the current package is core itself, this will be
|
||||
// replaced in the factory transformer before emit.
|
||||
`import * as i0 from '@angular/core';`,
|
||||
`import {${symbolNames.join(', ')}} from '${relativePathToSource}';`,
|
||||
...varLines,
|
||||
].join('\n');
|
||||
return ts.createSourceFile(
|
||||
genFilePath, sourceText, original.languageVersion, true, ts.ScriptKind.TS);
|
||||
}
|
||||
|
||||
static forRootFiles(files: ReadonlyArray<string>): FactoryGenerator {
|
||||
const map = new Map<string, string>();
|
||||
files.filter(sourceFile => isNonDeclarationTsFile(sourceFile))
|
||||
.forEach(sourceFile => map.set(sourceFile.replace(/\.ts$/, '.ngfactory.ts'), sourceFile));
|
||||
return new FactoryGenerator(map);
|
||||
}
|
||||
}
|
||||
|
||||
function isExported(decl: ts.Declaration): boolean {
|
||||
return decl.modifiers !== undefined &&
|
||||
decl.modifiers.some(mod => mod.kind == ts.SyntaxKind.ExportKeyword);
|
||||
}
|
||||
|
||||
export interface FactoryInfo {
|
||||
sourceFilePath: string;
|
||||
moduleSymbolNames: Set<string>;
|
||||
}
|
||||
|
||||
export function generatedFactoryTransform(
|
||||
factoryMap: Map<string, FactoryInfo>,
|
||||
coreImportsFrom: ts.SourceFile | null): ts.TransformerFactory<ts.SourceFile> {
|
||||
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
|
||||
return (file: ts.SourceFile): ts.SourceFile => {
|
||||
return transformFactorySourceFile(factoryMap, context, coreImportsFrom, file);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function transformFactorySourceFile(
|
||||
factoryMap: Map<string, FactoryInfo>, context: ts.TransformationContext,
|
||||
coreImportsFrom: ts.SourceFile | null, file: ts.SourceFile): ts.SourceFile {
|
||||
// If this is not a generated file, it won't have factory info associated with it.
|
||||
if (!factoryMap.has(file.fileName)) {
|
||||
// Don't transform non-generated code.
|
||||
return file;
|
||||
}
|
||||
|
||||
const {moduleSymbolNames, sourceFilePath} = factoryMap.get(file.fileName) !;
|
||||
|
||||
const clone = ts.getMutableClone(file);
|
||||
|
||||
const transformedStatements = file.statements.map(stmt => {
|
||||
if (coreImportsFrom !== null && ts.isImportDeclaration(stmt) &&
|
||||
ts.isStringLiteral(stmt.moduleSpecifier) && stmt.moduleSpecifier.text === '@angular/core') {
|
||||
const path = relativePathBetween(sourceFilePath, coreImportsFrom.fileName);
|
||||
if (path !== null) {
|
||||
return ts.updateImportDeclaration(
|
||||
stmt, stmt.decorators, stmt.modifiers, stmt.importClause, ts.createStringLiteral(path));
|
||||
} else {
|
||||
return ts.createNotEmittedStatement(stmt);
|
||||
}
|
||||
} else if (ts.isVariableStatement(stmt) && stmt.declarationList.declarations.length === 1) {
|
||||
const decl = stmt.declarationList.declarations[0];
|
||||
if (ts.isIdentifier(decl.name)) {
|
||||
const match = STRIP_NG_FACTORY.exec(decl.name.text);
|
||||
if (match === null || !moduleSymbolNames.has(match[1])) {
|
||||
// Remove the given factory as it wasn't actually for an NgModule.
|
||||
return ts.createNotEmittedStatement(stmt);
|
||||
}
|
||||
}
|
||||
return stmt;
|
||||
} else {
|
||||
return stmt;
|
||||
}
|
||||
});
|
||||
if (!transformedStatements.some(ts.isVariableStatement)) {
|
||||
// If the resulting file has no factories, include an empty export to
|
||||
// satisfy closure compiler.
|
||||
transformedStatements.push(ts.createVariableStatement(
|
||||
[ts.createModifier(ts.SyntaxKind.ExportKeyword)],
|
||||
ts.createVariableDeclarationList(
|
||||
[ts.createVariableDeclaration('ɵNonEmptyModule', undefined, ts.createTrue())],
|
||||
ts.NodeFlags.Const)));
|
||||
}
|
||||
clone.statements = ts.createNodeArray(transformedStatements);
|
||||
return clone;
|
||||
}
|
@ -9,15 +9,26 @@
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {FactoryGenerator} from './generator';
|
||||
export interface ShimGenerator {
|
||||
/**
|
||||
* Get the original source file for the given shim path, the contents of which determine the
|
||||
* contents of the shim file.
|
||||
*
|
||||
* If this returns `null` then the given file was not a shim file handled by this generator.
|
||||
*/
|
||||
getOriginalSourceOfShim(fileName: string): string|null;
|
||||
|
||||
/**
|
||||
* Generate a shim's `ts.SourceFile` for the given original file.
|
||||
*/
|
||||
generate(original: ts.SourceFile, genFileName: string): ts.SourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around a `ts.CompilerHost` which supports generated files.
|
||||
*/
|
||||
export class GeneratedFactoryHostWrapper implements ts.CompilerHost {
|
||||
constructor(
|
||||
private delegate: ts.CompilerHost, private generator: FactoryGenerator,
|
||||
private factoryToSourceMap: Map<string, string>) {
|
||||
export class GeneratedShimsHostWrapper implements ts.CompilerHost {
|
||||
constructor(private delegate: ts.CompilerHost, private shimGenerators: ShimGenerator[]) {
|
||||
if (delegate.resolveTypeReferenceDirectives) {
|
||||
// Backward compatibility with TypeScript 2.9 and older since return
|
||||
// type has changed from (ts.ResolvedTypeReferenceDirective | undefined)[]
|
||||
@ -38,14 +49,20 @@ export class GeneratedFactoryHostWrapper implements ts.CompilerHost {
|
||||
onError?: ((message: string) => void)|undefined,
|
||||
shouldCreateNewSourceFile?: boolean|undefined): ts.SourceFile|undefined {
|
||||
const canonical = this.getCanonicalFileName(fileName);
|
||||
if (this.factoryToSourceMap.has(canonical)) {
|
||||
const sourceFileName = this.getCanonicalFileName(this.factoryToSourceMap.get(canonical) !);
|
||||
const sourceFile = this.delegate.getSourceFile(
|
||||
sourceFileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (sourceFile === undefined) {
|
||||
return undefined;
|
||||
for (let i = 0; i < this.shimGenerators.length; i++) {
|
||||
const generator = this.shimGenerators[i];
|
||||
const originalFile = generator.getOriginalSourceOfShim(canonical);
|
||||
if (originalFile !== null) {
|
||||
// This shim generator has recognized the filename being requested, and is now responsible
|
||||
// for generating its contents, based on the contents of the original file it has requested.
|
||||
const originalSource = this.delegate.getSourceFile(
|
||||
originalFile, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (originalSource === undefined) {
|
||||
// The original requested file doesn't exist, so the shim cannot exist either.
|
||||
return undefined;
|
||||
}
|
||||
return generator.generate(originalSource, fileName);
|
||||
}
|
||||
return this.generator.factoryFor(sourceFile, fileName);
|
||||
}
|
||||
return this.delegate.getSourceFile(
|
||||
fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
@ -75,7 +92,11 @@ export class GeneratedFactoryHostWrapper implements ts.CompilerHost {
|
||||
getNewLine(): string { return this.delegate.getNewLine(); }
|
||||
|
||||
fileExists(fileName: string): boolean {
|
||||
return this.factoryToSourceMap.has(fileName) || this.delegate.fileExists(fileName);
|
||||
const canonical = this.getCanonicalFileName(fileName);
|
||||
// Consider the file as existing whenever 1) it really does exist in the delegate host, or
|
||||
// 2) at least one of the shim generators recognizes it.
|
||||
return this.delegate.fileExists(fileName) ||
|
||||
this.shimGenerators.some(gen => gen.getOriginalSourceOfShim(canonical) !== null);
|
||||
}
|
||||
|
||||
readFile(fileName: string): string|undefined { return this.delegate.readFile(fileName); }
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @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 * as ts from 'typescript';
|
||||
|
||||
import {ShimGenerator} from './host';
|
||||
import {isNonDeclarationTsFile} from './util';
|
||||
|
||||
export class SummaryGenerator implements ShimGenerator {
|
||||
private constructor(private map: Map<string, string>) {}
|
||||
|
||||
getSummaryFileNames(): string[] { return Array.from(this.map.keys()); }
|
||||
|
||||
getOriginalSourceOfShim(fileName: string): string|null { return this.map.get(fileName) || null; }
|
||||
|
||||
generate(original: ts.SourceFile, genFilePath: string): ts.SourceFile {
|
||||
// Collect a list of classes that need to have factory types emitted for them. This list is
|
||||
// overly broad as at this point the ts.TypeChecker has not been created and so it can't be used
|
||||
// to semantically understand which decorators are Angular decorators. It's okay to output an
|
||||
// overly broad set of summary exports as the exports are no-ops anyway, and summaries are a
|
||||
// compatibility layer which will be removed after Ivy is enabled.
|
||||
const symbolNames = original
|
||||
.statements
|
||||
// Pick out top level class declarations...
|
||||
.filter(ts.isClassDeclaration)
|
||||
// which are named, exported, and have decorators.
|
||||
.filter(
|
||||
decl => isExported(decl) && decl.decorators !== undefined &&
|
||||
decl.name !== undefined)
|
||||
// Grab the symbol name.
|
||||
.map(decl => decl.name !.text);
|
||||
|
||||
const varLines = symbolNames.map(name => `export const ${name}NgSummary: any = null;`);
|
||||
|
||||
if (varLines.length === 0) {
|
||||
// In the event there are no other exports, add an empty export to ensure the generated
|
||||
// summary file is still an ES module.
|
||||
varLines.push(`export const ɵempty = null;`);
|
||||
}
|
||||
const sourceText = varLines.join('\n');
|
||||
return ts.createSourceFile(
|
||||
genFilePath, sourceText, original.languageVersion, true, ts.ScriptKind.TS);
|
||||
}
|
||||
|
||||
static forRootFiles(files: ReadonlyArray<string>): SummaryGenerator {
|
||||
const map = new Map<string, string>();
|
||||
files.filter(sourceFile => isNonDeclarationTsFile(sourceFile))
|
||||
.forEach(sourceFile => map.set(sourceFile.replace(/\.ts$/, '.ngsummary.ts'), sourceFile));
|
||||
return new SummaryGenerator(map);
|
||||
}
|
||||
}
|
||||
|
||||
function isExported(decl: ts.Declaration): boolean {
|
||||
return decl.modifiers !== undefined &&
|
||||
decl.modifiers.some(mod => mod.kind == ts.SyntaxKind.ExportKeyword);
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
@ -7,4 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export * from './ivy_switch_on';
|
||||
const TS_FILE = /\.tsx?$/;
|
||||
const D_TS_FILE = /\.d\.ts$/;
|
||||
|
||||
export function isNonDeclarationTsFile(file: string): boolean {
|
||||
return TS_FILE.exec(file) !== null && D_TS_FILE.exec(file) === null;
|
||||
}
|
19
packages/compiler-cli/src/ngtsc/switch/BUILD.bazel
Normal file
19
packages/compiler-cli/src/ngtsc/switch/BUILD.bazel
Normal file
@ -0,0 +1,19 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "switch",
|
||||
srcs = glob([
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/switch",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/host",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/util",
|
||||
"@ngdeps//typescript",
|
||||
],
|
||||
)
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
@ -7,4 +6,4 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export * from './ivy_switch_on';
|
||||
export {ivySwitchTransform} from './src/switch';
|
152
packages/compiler-cli/src/ngtsc/switch/src/switch.ts
Normal file
152
packages/compiler-cli/src/ngtsc/switch/src/switch.ts
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @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 * as ts from 'typescript';
|
||||
|
||||
const IVY_SWITCH_PRE_SUFFIX = '__PRE_R3__';
|
||||
const IVY_SWITCH_POST_SUFFIX = '__POST_R3__';
|
||||
|
||||
export function ivySwitchTransform(_: ts.TransformationContext): ts.Transformer<ts.SourceFile> {
|
||||
return flipIvySwitchInFile;
|
||||
}
|
||||
|
||||
function flipIvySwitchInFile(sf: ts.SourceFile): ts.SourceFile {
|
||||
// To replace the statements array, it must be copied. This only needs to happen if a statement
|
||||
// must actually be replaced within the array, so the newStatements array is lazily initialized.
|
||||
let newStatements: ts.Statement[]|undefined = undefined;
|
||||
|
||||
// Iterate over the statements in the file.
|
||||
for (let i = 0; i < sf.statements.length; i++) {
|
||||
const statement = sf.statements[i];
|
||||
|
||||
// Skip over everything that isn't a variable statement.
|
||||
if (!ts.isVariableStatement(statement) || !hasIvySwitches(statement)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This statement needs to be replaced. Check if the newStatements array needs to be lazily
|
||||
// initialized to a copy of the original statements.
|
||||
if (newStatements === undefined) {
|
||||
newStatements = [...sf.statements];
|
||||
}
|
||||
|
||||
// Flip any switches in the VariableStatement. If there were any, a new statement will be
|
||||
// returned; otherwise the old statement will be.
|
||||
newStatements[i] = flipIvySwitchesInVariableStatement(statement, sf.statements);
|
||||
}
|
||||
|
||||
// Only update the statements in the SourceFile if any have changed.
|
||||
if (newStatements !== undefined) {
|
||||
sf.statements = ts.createNodeArray(newStatements);
|
||||
}
|
||||
return sf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for the ts.Identifier of a ts.Declaration with this name.
|
||||
*
|
||||
* The real identifier is needed (rather than fabricating one) as TypeScript decides how to
|
||||
* reference this identifier based on information stored against its node in the AST, which a
|
||||
* synthetic node would not have. In particular, since the post-switch variable is often exported,
|
||||
* TypeScript needs to know this so it can write `exports.VAR` instead of just `VAR` when emitting
|
||||
* code.
|
||||
*
|
||||
* Only variable, function, and class declarations are currently searched.
|
||||
*/
|
||||
function findPostSwitchIdentifier(
|
||||
statements: ReadonlyArray<ts.Statement>, name: string): ts.Identifier|null {
|
||||
for (const stmt of statements) {
|
||||
if (ts.isVariableStatement(stmt)) {
|
||||
const decl = stmt.declarationList.declarations.find(
|
||||
decl => ts.isIdentifier(decl.name) && decl.name.text === name);
|
||||
if (decl !== undefined) {
|
||||
return decl.name as ts.Identifier;
|
||||
}
|
||||
} else if (ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) {
|
||||
if (stmt.name !== undefined && ts.isIdentifier(stmt.name) && stmt.name.text === name) {
|
||||
return stmt.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip any Ivy switches which are discovered in the given ts.VariableStatement.
|
||||
*/
|
||||
function flipIvySwitchesInVariableStatement(
|
||||
stmt: ts.VariableStatement, statements: ReadonlyArray<ts.Statement>): ts.VariableStatement {
|
||||
// Build a new list of variable declarations. Specific declarations that are initialized to a
|
||||
// pre-switch identifier will be replaced with a declaration initialized to the post-switch
|
||||
// identifier.
|
||||
const newDeclarations = [...stmt.declarationList.declarations];
|
||||
for (let i = 0; i < newDeclarations.length; i++) {
|
||||
const decl = newDeclarations[i];
|
||||
|
||||
// Skip declarations that aren't initialized to an identifier.
|
||||
if (decl.initializer === undefined || !ts.isIdentifier(decl.initializer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip declarations that aren't Ivy switches.
|
||||
if (!decl.initializer.text.endsWith(IVY_SWITCH_PRE_SUFFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine the name of the post-switch variable.
|
||||
const postSwitchName =
|
||||
decl.initializer.text.replace(IVY_SWITCH_PRE_SUFFIX, IVY_SWITCH_POST_SUFFIX);
|
||||
|
||||
// Find the post-switch variable identifier. If one can't be found, it's an error. This is
|
||||
// reported as a thrown error and not a diagnostic as transformers cannot output diagnostics.
|
||||
let newIdentifier = findPostSwitchIdentifier(statements, postSwitchName);
|
||||
if (newIdentifier === null) {
|
||||
throw new Error(
|
||||
`Unable to find identifier ${postSwitchName} in ${stmt.getSourceFile().fileName} for the Ivy switch.`);
|
||||
}
|
||||
|
||||
// Copy the identifier with updateIdentifier(). This copies the internal information which
|
||||
// allows TS to write a correct reference to the identifier.
|
||||
newIdentifier = ts.updateIdentifier(newIdentifier);
|
||||
|
||||
newDeclarations[i] = ts.updateVariableDeclaration(
|
||||
/* node */ decl,
|
||||
/* name */ decl.name,
|
||||
/* type */ decl.type,
|
||||
/* initializer */ newIdentifier);
|
||||
|
||||
// Keeping parent pointers up to date is important for emit.
|
||||
newIdentifier.parent = newDeclarations[i];
|
||||
}
|
||||
|
||||
const newDeclList = ts.updateVariableDeclarationList(
|
||||
/* declarationList */ stmt.declarationList,
|
||||
/* declarations */ newDeclarations);
|
||||
|
||||
const newStmt = ts.updateVariableStatement(
|
||||
/* statement */ stmt,
|
||||
/* modifiers */ stmt.modifiers,
|
||||
/* declarationList */ newDeclList);
|
||||
|
||||
// Keeping parent pointers up to date is important for emit.
|
||||
for (const decl of newDeclarations) {
|
||||
decl.parent = newDeclList;
|
||||
}
|
||||
newDeclList.parent = newStmt;
|
||||
newStmt.parent = stmt.parent;
|
||||
return newStmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given VariableStatement has any Ivy switch variables.
|
||||
*/
|
||||
function hasIvySwitches(stmt: ts.VariableStatement) {
|
||||
return stmt.declarationList.declarations.some(
|
||||
decl => decl.initializer !== undefined && ts.isIdentifier(decl.initializer) &&
|
||||
decl.initializer.text.endsWith(IVY_SWITCH_PRE_SUFFIX));
|
||||
}
|
@ -518,7 +518,7 @@ function tcbGetInputBindingExpressions(
|
||||
// is desired. Invert `dir.inputs` into `propMatch` to create this map.
|
||||
const propMatch = new Map<string, string>();
|
||||
const inputs = dir.inputs;
|
||||
Object.keys(inputs).forEach(key => propMatch.set(inputs[key] as string, key));
|
||||
Object.keys(inputs).forEach(key => propMatch.set(inputs[key], key));
|
||||
|
||||
// Add a binding expression to the map for each input of the directive that has a
|
||||
// matching binding.
|
||||
|
@ -10,11 +10,15 @@ import {GeneratedFile} from '@angular/compiler';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ivySwitchTransform} from '../ngtsc/switch';
|
||||
import * as api from '../transformers/api';
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of the `Program` API which behaves like plain `tsc` and does not include any
|
||||
* Angular-specific behavior whatsoever.
|
||||
* An implementation of the `Program` API which behaves similarly to plain `tsc`.
|
||||
*
|
||||
* The only Angular specific behavior included in this `Program` is the operation of the Ivy
|
||||
* switch to turn on render3 behavior.
|
||||
*
|
||||
* This allows `ngc` to behave like `tsc` in cases where JIT code needs to be tested.
|
||||
*/
|
||||
@ -95,6 +99,7 @@ export class TscPassThroughProgram implements api.Program {
|
||||
host: this.host,
|
||||
options: this.options,
|
||||
emitOnlyDtsFiles: false,
|
||||
customTransformers: {before: [ivySwitchTransform]},
|
||||
});
|
||||
return emitResult;
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
Tests in this directory should be run with:
|
||||
|
||||
```
|
||||
yarn bazel test --define=compile=aot packages/compiler-cli/test/compliance:compliance
|
||||
```
|
||||
bazel test --define=compile=aot packages/compiler-cli/test/compliance:compliance
|
||||
|
@ -415,7 +415,6 @@ describe('compiler compliance', () => {
|
||||
factory: function MyComponent_Factory(t){
|
||||
return new (t || MyComponent)();
|
||||
},
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf,ctx){
|
||||
@ -470,7 +469,6 @@ describe('compiler compliance', () => {
|
||||
type: ChildComponent,
|
||||
selectors: [["child"]],
|
||||
factory: function ChildComponent_Factory(t) { return new (t || ChildComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function ChildComponent_Template(rf, ctx) {
|
||||
@ -485,8 +483,7 @@ describe('compiler compliance', () => {
|
||||
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: SomeDirective,
|
||||
selectors: [["", "some-directive", ""]],
|
||||
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); },
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
|
||||
});
|
||||
`;
|
||||
|
||||
@ -498,7 +495,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -543,8 +539,7 @@ describe('compiler compliance', () => {
|
||||
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: SomeDirective,
|
||||
selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]],
|
||||
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); },
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
|
||||
});
|
||||
`;
|
||||
|
||||
@ -553,8 +548,7 @@ describe('compiler compliance', () => {
|
||||
OtherDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: OtherDirective,
|
||||
selectors: [["", 5, "span", "title", "", 9, "baz"]],
|
||||
factory: function OtherDirective_Factory(t) {return new (t || OtherDirective)(); },
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
factory: function OtherDirective_Factory(t) {return new (t || OtherDirective)(); }
|
||||
});
|
||||
`;
|
||||
|
||||
@ -590,8 +584,7 @@ describe('compiler compliance', () => {
|
||||
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
|
||||
},
|
||||
hostVars: 1,
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
hostVars: 1
|
||||
});
|
||||
`;
|
||||
|
||||
@ -635,7 +628,6 @@ describe('compiler compliance', () => {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
|
||||
},
|
||||
hostVars: 3,
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function HostBindingComp_Template(rf, ctx) {}
|
||||
@ -679,7 +671,6 @@ describe('compiler compliance', () => {
|
||||
$r3$.ɵdirectiveInject(ElementRef), $r3$.ɵdirectiveInject(ViewContainerRef),
|
||||
$r3$.ɵdirectiveInject(ChangeDetectorRef));
|
||||
},
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {}
|
||||
@ -720,8 +711,7 @@ describe('compiler compliance', () => {
|
||||
IfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: IfDirective,
|
||||
selectors: [["", "if", ""]],
|
||||
factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef)); },
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef)); }
|
||||
});`;
|
||||
const MyComponentDefinition = `
|
||||
const $c1$ = ["foo", ""];
|
||||
@ -743,7 +733,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 3,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -806,7 +795,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 3,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -888,7 +876,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 11,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -952,7 +939,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 3,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -1020,7 +1006,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 8,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -1079,7 +1064,6 @@ describe('compiler compliance', () => {
|
||||
type: SimpleComponent,
|
||||
selectors: [["simple"]],
|
||||
factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 0,
|
||||
template: function SimpleComponent_Template(rf, ctx) {
|
||||
@ -1102,7 +1086,6 @@ describe('compiler compliance', () => {
|
||||
type: ComplexComponent,
|
||||
selectors: [["complex"]],
|
||||
factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 4,
|
||||
vars: 0,
|
||||
template: function ComplexComponent_Template(rf, ctx) {
|
||||
@ -1171,7 +1154,6 @@ describe('compiler compliance', () => {
|
||||
type: ViewQueryComponent,
|
||||
selectors: [["view-query-component"]],
|
||||
factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
viewQuery: function ViewQueryComponent_Query(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵquery(0, SomeDirective, true);
|
||||
@ -1348,9 +1330,9 @@ describe('compiler compliance', () => {
|
||||
factory: function ContentQueryComponent_Factory(t) {
|
||||
return new (t || ContentQueryComponent)();
|
||||
},
|
||||
contentQueries: function ContentQueryComponent_ContentQueries() {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true));
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false));
|
||||
contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true), dirIndex);
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false), dirIndex);
|
||||
},
|
||||
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
|
||||
const instance = $r3$.ɵload(dirIndex);
|
||||
@ -1358,7 +1340,6 @@ describe('compiler compliance', () => {
|
||||
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && ($instance$.someDir = $tmp$.first));
|
||||
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && ($instance$.someDirList = $tmp$));
|
||||
},
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 0,
|
||||
template: function ContentQueryComponent_Template(rf, ctx) {
|
||||
@ -1406,9 +1387,9 @@ describe('compiler compliance', () => {
|
||||
…
|
||||
ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
…
|
||||
contentQueries: function ContentQueryComponent_ContentQueries() {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$, true));
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false));
|
||||
contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$, true), dirIndex);
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false), dirIndex);
|
||||
},
|
||||
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
|
||||
const instance = $r3$.ɵload(dirIndex);
|
||||
@ -1459,11 +1440,11 @@ describe('compiler compliance', () => {
|
||||
…
|
||||
ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
…
|
||||
contentQueries: function ContentQueryComponent_ContentQueries() {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$ , true, TemplateRef));
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true, ElementRef));
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false, ElementRef));
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false, TemplateRef));
|
||||
contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$ , true, TemplateRef), dirIndex);
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true, ElementRef), dirIndex);
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false, ElementRef), dirIndex);
|
||||
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false, TemplateRef), dirIndex);
|
||||
},
|
||||
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
|
||||
const instance = $r3$.ɵload(dirIndex);
|
||||
@ -1552,7 +1533,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 6,
|
||||
vars: 17,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -1616,7 +1596,6 @@ describe('compiler compliance', () => {
|
||||
type: MyApp,
|
||||
selectors: [["my-app"]],
|
||||
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 6,
|
||||
vars: 27,
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
@ -1671,7 +1650,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 3,
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -1765,7 +1743,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 6,
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -1911,7 +1888,7 @@ describe('compiler compliance', () => {
|
||||
selectors: [["lifecycle-comp"]],
|
||||
factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
|
||||
inputs: {nameMin: "name"},
|
||||
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature],
|
||||
features: [$r3$.ɵNgOnChangesFeature],
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function LifecycleComp_Template(rf, ctx) {}
|
||||
@ -1922,7 +1899,6 @@ describe('compiler compliance', () => {
|
||||
type: SimpleLayout,
|
||||
selectors: [["simple-layout"]],
|
||||
factory: function SimpleLayout_Factory(t) { return new (t || SimpleLayout)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 2,
|
||||
template: function SimpleLayout_Template(rf, ctx) {
|
||||
@ -2032,7 +2008,7 @@ describe('compiler compliance', () => {
|
||||
factory: function ForOfDirective_Factory(t) {
|
||||
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
||||
},
|
||||
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature],
|
||||
features: [$r3$.ɵNgOnChangesFeature],
|
||||
inputs: {forOf: "forOf"}
|
||||
});
|
||||
`;
|
||||
@ -2052,7 +2028,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx){
|
||||
@ -2108,7 +2083,7 @@ describe('compiler compliance', () => {
|
||||
factory: function ForOfDirective_Factory(t) {
|
||||
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
||||
},
|
||||
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature],
|
||||
features: [$r3$.ɵNgOnChangesFeature],
|
||||
inputs: {forOf: "forOf"}
|
||||
});
|
||||
`;
|
||||
@ -2131,7 +2106,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -2231,7 +2205,6 @@ describe('compiler compliance', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 2,
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
|
@ -42,7 +42,6 @@ describe('compiler compliance: directives', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
@ -88,7 +87,6 @@ describe('compiler compliance: directives', () => {
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
features: [$r3$.ɵPublicFeature],
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user