Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
77f531b6f7 | |||
3041240cbc | |||
257ac83095 | |||
bc93d47129 | |||
3f61071638 | |||
ea571aa9d1 | |||
40cd0371d2 | |||
8356577670 | |||
45d3c8093b | |||
e7eec2e44b | |||
c44b93253c | |||
cd444bc2ba | |||
e9ae26a272 | |||
f9856974e3 | |||
b3c6409763 | |||
4c3e9a32d2 | |||
2700952040 | |||
6d92c99c49 | |||
7cefb3efd4 | |||
1c0ab3468d | |||
b5ede01c09 | |||
98b1a9dcfe | |||
c277c198d2 | |||
b7d7609872 | |||
415e3e06ed | |||
0f7a850699 | |||
1e2525b8a7 | |||
bc9f534bf4 | |||
ea2a3ca705 | |||
802e996e64 | |||
aa7dd1267b | |||
91916e7113 | |||
0e92f1eee5 | |||
4ac3b2e2bd | |||
20ce134961 | |||
c01f3409f3 | |||
71580c8e37 | |||
e58f8b7be0 | |||
046c96a3f1 | |||
00e6569e0f | |||
5dbf9f721b | |||
c63bc02846 | |||
2f3308e4f0 | |||
cc5e4fb93f | |||
3ab9947c7f | |||
b1f92db22b | |||
bda1e52b50 | |||
1084ebc091 | |||
5a3af00398 | |||
7a088af3ff | |||
3e8d8ec2f5 | |||
d4ea7f1f7e | |||
23096501e2 | |||
023874426e | |||
aeffcdd417 | |||
6d7d7c77e3 | |||
8da6c369e5 |
@ -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 ngcontainer docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it angular/ngcontainer`
|
||||
- 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`
|
||||
- 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,40 +7,20 @@
|
||||
# To validate changes, use an online parser, eg.
|
||||
# http://yaml-online-parser.appspot.com/
|
||||
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# Define common ENV vars
|
||||
var_3: &define_env_vars
|
||||
var_4: &define_env_vars
|
||||
run:
|
||||
name: Define environment variables
|
||||
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
|
||||
command: ./.circleci/env.sh
|
||||
|
||||
var_5: &setup_bazel_remote_execution
|
||||
run:
|
||||
@ -48,59 +28,73 @@ 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
|
||||
anchor_1: &job_defaults
|
||||
var_6: &job_defaults
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: *docker_image
|
||||
- image: *default_docker_image
|
||||
|
||||
var_7: &start-xvfb
|
||||
run:
|
||||
name: Running X virtual framebuffer
|
||||
command: Xvfb :99 -screen 0 1280x1024x24
|
||||
background: true
|
||||
|
||||
# After checkout, rebase on top of master.
|
||||
# Similar to travis behavior, but not quite the same.
|
||||
# See https://discuss.circleci.com/t/1662
|
||||
anchor_2: &post_checkout
|
||||
var_8: &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
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
|
||||
# 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
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
|
||||
- run: bazel info release
|
||||
- run: bazel run @nodejs//:yarn
|
||||
# Setup remote execution and run RBE-compatible tests.
|
||||
- *setup_bazel_remote_execution
|
||||
- run: bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-local
|
||||
- run: yarn 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: bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||
- run: yarn 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.
|
||||
@ -134,14 +128,16 @@ jobs:
|
||||
steps:
|
||||
# don't run this job on the patch branch (to preserve resources)
|
||||
- run: circleci step halt
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
|
||||
- run: bazel run @yarn//:yarn
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- *setup_bazel_remote_execution
|
||||
- run: bazel test //... --define=compile=jit --build_tag_filters=ivy-jit --test_tag_filters=ivy-jit
|
||||
|
||||
- run: yarn test-ivy-jit //...
|
||||
|
||||
test_ivy_aot:
|
||||
<<: *job_defaults
|
||||
@ -149,77 +145,96 @@ jobs:
|
||||
steps:
|
||||
# don't run this job on the patch branch (to preserve resources)
|
||||
- run: circleci step halt
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- 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
|
||||
|
||||
test_and_deploy_aio:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- *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: yarn test-ivy-aot //...
|
||||
|
||||
test_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- 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:
|
||||
name: Run PWA-score tests
|
||||
command: xvfb-run --auto-servernum yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
- run: 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: xvfb-run --auto-servernum yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
# Run e2e tests
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio e2e
|
||||
- run: 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: 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
|
||||
- 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
|
||||
|
||||
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
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
# 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:
|
||||
name: Run PWA-score tests
|
||||
command: xvfb-run --auto-servernum yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run unit tests
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
# Run e2e tests
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio e2e
|
||||
- run: yarn --cwd aio e2e
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
# Install
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd aio extract-cli-command-docs
|
||||
@ -229,37 +244,45 @@ 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
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
# Install root
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- *yarn_install
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio example-e2e --setup --local --shard=0/2
|
||||
- run: 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
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
# Install root
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- *yarn_install
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: xvfb-run --auto-servernum yarn --cwd aio example-e2e --setup --local --shard=1/2
|
||||
- run: 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:
|
||||
@ -267,12 +290,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
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- *define_env_vars
|
||||
- *yarn_install
|
||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||
- store_artifacts:
|
||||
path: *aio_preview_artifact_path
|
||||
@ -283,16 +306,20 @@ 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: xvfb-run --auto-servernum node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
command: 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.
|
||||
@ -305,12 +332,15 @@ jobs:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- *define_env_vars
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- run: bazel run @nodejs//:yarn
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
@ -330,23 +360,31 @@ 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
|
||||
- run: xvfb-run --auto-servernum ./integration/run_tests.sh
|
||||
- *define_env_vars
|
||||
- *start-xvfb
|
||||
- run: ./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.
|
||||
@ -358,8 +396,6 @@ 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
|
||||
@ -373,15 +409,24 @@ 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: xvfb-run --auto-servernum ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
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
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@ -392,7 +437,10 @@ workflows:
|
||||
- test_ivy_jit
|
||||
- test_ivy_aot
|
||||
- build-packages-dist
|
||||
- test_and_deploy_aio
|
||||
- test_aio
|
||||
- deploy_aio:
|
||||
requires:
|
||||
- test_aio
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
@ -427,6 +475,10 @@ workflows:
|
||||
- test_ivy_jit
|
||||
- test_ivy_aot
|
||||
- integration_test
|
||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||
- test_aio_local
|
||||
- test_docs_examples_0
|
||||
- test_docs_examples_1
|
||||
# Get the artifacts to publish from the build-packages-dist job
|
||||
# since the publishing script expects the legacy outputs layout.
|
||||
- build-packages-dist
|
||||
|
38
.circleci/env-helpers.inc.sh
Normal file
38
.circleci/env-helpers.inc.sh
Normal file
@ -0,0 +1,38 @@
|
||||
####################################################################################################
|
||||
# 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";
|
||||
}
|
35
.circleci/env.sh
Executable file
35
.circleci/env.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/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,13 +8,6 @@ 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
|
||||
|
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,15 @@
|
||||
<a name="7.0.2"></a>
|
||||
## [7.0.2](https://github.com/angular/angular/compare/7.0.1...7.0.2) (2018-10-31)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
<a name="7.0.1"></a>
|
||||
## [7.0.1](https://github.com/angular/angular/compare/7.0.0...7.0.1) (2018-10-24)
|
||||
|
||||
@ -79,7 +91,6 @@ 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,6 +6,16 @@ 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,8 +49,6 @@ 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.
|
||||
|
@ -13,6 +13,10 @@ describe('Elements', () => {
|
||||
browser.wait(EC.elementToBeClickable(elem), 5000);
|
||||
elem.click();
|
||||
};
|
||||
const waitForText = (elem: ElementFinder) => {
|
||||
// Waiting for the element to have some text, makes the tests less flaky.
|
||||
browser.wait(async () => /\S/.test(await elem.getText()), 5000);
|
||||
}
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
@ -33,6 +37,8 @@ describe('Elements', () => {
|
||||
messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
click(popupComponentButton);
|
||||
waitForText(popupComponent);
|
||||
|
||||
expect(popupComponent.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
@ -62,6 +68,8 @@ describe('Elements', () => {
|
||||
messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
click(popupElementButton);
|
||||
waitForText(popupElement);
|
||||
|
||||
expect(popupElement.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
|
@ -12,7 +12,7 @@ h2, h3 {
|
||||
body {
|
||||
margin: 2em;
|
||||
}
|
||||
body, input[text], button {
|
||||
body, input[type="text"], button {
|
||||
color: #888;
|
||||
font-family: Cambria, Georgia;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ export class HeroService {
|
||||
// #enddocregion getHeroes-1
|
||||
.pipe(
|
||||
// #enddocregion getHeroes-2
|
||||
tap(heroes => this.log('fetched heroes')),
|
||||
tap(_ => this.log('fetched heroes')),
|
||||
// #docregion getHeroes-2
|
||||
catchError(this.handleError('getHeroes', []))
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by, ElementFinder } from 'protractor';
|
||||
import { browser, element, by, ElementArrayFinder, ElementFinder } from 'protractor';
|
||||
|
||||
// Angular E2E Testing Guide:
|
||||
// https://docs.angularjs.org/guide/e2e-testing
|
||||
@ -20,6 +20,12 @@ describe('PhoneCat Application', function() {
|
||||
|
||||
describe('View: Phone list', function() {
|
||||
|
||||
// Helpers
|
||||
const waitForCount = (elems: ElementArrayFinder, count: number) => {
|
||||
// Wait for the list to stabilize, which may take a while (e.g. due to animations).
|
||||
browser.wait(() => elems.count().then(c => c === count), 5000);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
browser.get('index.html#!/phones');
|
||||
});
|
||||
@ -28,13 +34,16 @@ describe('PhoneCat Application', function() {
|
||||
let phoneList = element.all(by.repeater('phone in $ctrl.phones'));
|
||||
let query = element(by.model('$ctrl.query'));
|
||||
|
||||
waitForCount(phoneList, 20);
|
||||
expect(phoneList.count()).toBe(20);
|
||||
|
||||
query.sendKeys('nexus');
|
||||
waitForCount(phoneList, 1);
|
||||
expect(phoneList.count()).toBe(1);
|
||||
|
||||
query.clear();
|
||||
query.sendKeys('motorola');
|
||||
waitForCount(phoneList, 8);
|
||||
expect(phoneList.count()).toBe(8);
|
||||
});
|
||||
|
||||
@ -51,6 +60,7 @@ describe('PhoneCat Application', function() {
|
||||
}
|
||||
|
||||
queryField.sendKeys('tablet'); // Let's narrow the dataset to make the assertions shorter
|
||||
waitForCount(phoneNameColumn, 2);
|
||||
|
||||
expect(getNames()).toEqual([
|
||||
'Motorola XOOM\u2122 with Wi-Fi',
|
||||
@ -66,10 +76,16 @@ describe('PhoneCat Application', function() {
|
||||
});
|
||||
|
||||
it('should render phone specific links', function() {
|
||||
let phoneList = element.all(by.repeater('phone in $ctrl.phones'));
|
||||
let query = element(by.model('$ctrl.query'));
|
||||
query.sendKeys('nexus');
|
||||
|
||||
element.all(by.css('.phones li a')).first().click();
|
||||
query.sendKeys('nexus');
|
||||
waitForCount(phoneList, 1);
|
||||
|
||||
let nexusPhone = phoneList.first();
|
||||
let detailLink = nexusPhone.all(by.css('a')).first()
|
||||
|
||||
detailLink.click();
|
||||
expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s');
|
||||
});
|
||||
|
||||
|
@ -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, build for development and copy the output directory to a web server.
|
||||
For the simplest deployment, create a production build and copy the output directory to a web server.
|
||||
|
||||
1. Start with the development build:
|
||||
1. Start with the production build:
|
||||
|
||||
<code-example language="none" class="code-shell">
|
||||
ng build
|
||||
ng build --prod
|
||||
</code-example>
|
||||
|
||||
|
||||
@ -22,8 +22,7 @@ For the simplest deployment, build for development and copy the output directory
|
||||
3. Configure the server to redirect requests for missing files to `index.html`.
|
||||
Learn more about server-side redirects [below](#fallback).
|
||||
|
||||
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).
|
||||
This is the simplest production-ready deployment of your application.
|
||||
|
||||
{@a deploy-to-github}
|
||||
|
||||
@ -31,7 +30,7 @@ It might be good enough for sharing your progress and ideas internally with mana
|
||||
|
||||
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:
|
||||
@ -39,9 +38,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).
|
||||
|
||||
@ -97,51 +96,6 @@ 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/):
|
||||
@ -230,19 +184,9 @@ Read about how to enable CORS for specific servers at
|
||||
|
||||
{@a optimize}
|
||||
|
||||
## Optimize for production
|
||||
## Production optimizations
|
||||
|
||||
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.
|
||||
The `--prod` _meta-flag_ engages the following build 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_.
|
||||
@ -251,25 +195,22 @@ The `--prod` _meta-flag_ engages the following optimization features.
|
||||
* Uglification: rewrites code to use short, cryptic variable and function names.
|
||||
* Dead code elimination: removes unreferenced modules and much unused code.
|
||||
|
||||
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 production mode
|
||||
### Enable runtime production mode
|
||||
|
||||
Angular apps run in development mode by default, as you can see by the following message on the browser
|
||||
console:
|
||||
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:
|
||||
|
||||
<code-example format="nocode">
|
||||
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
|
||||
</code-example>
|
||||
|
||||
Switching to _production mode_ can make it run faster by disabling development specific checks such as the dual change detection cycles.
|
||||
Switching to _production mode_ makes it run faster by disabling development specific checks such as the dual change detection cycles.
|
||||
|
||||
Building for production (or appending the `--environment=prod` flag) enables _production mode_
|
||||
Look at the CLI-generated `main.ts` to see how this works.
|
||||
When you enable production builds via `--prod` command line flag, the runtime production mode is enabled as well.
|
||||
|
||||
{@a lazy-loading}
|
||||
|
||||
@ -293,7 +234,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
|
||||
@ -388,7 +329,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.
|
||||
@ -401,12 +342,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 `CustomerDashboardModule`:
|
||||
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`:
|
||||
|
||||
<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 a configuration
|
||||
* With [AOT](guide/i18n#merge-aot), you pass the information as configuration settings.
|
||||
* 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 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/).
|
||||
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/).
|
||||
|
||||
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.
|
||||
|
135
aio/content/guide/workspace-config.md
Normal file
135
aio/content/guide/workspace-config.md
Normal file
@ -0,0 +1,135 @@
|
||||
# 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://github.com/angular/universal"
|
||||
"url": "https://angular.io/guide/universal"
|
||||
},
|
||||
"c1": {
|
||||
"desc": "Lightweight development only Node.js® server",
|
||||
@ -273,6 +273,13 @@
|
||||
"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/"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -362,7 +369,7 @@
|
||||
"logo": "",
|
||||
"rev": true,
|
||||
"title": "Angular Material",
|
||||
"url": "https://github.com/angular/material2"
|
||||
"url": "https://material.angular.io/"
|
||||
},
|
||||
"mcc": {
|
||||
"desc": "Material components made by the community",
|
||||
@ -377,6 +384,12 @@
|
||||
"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,8 +513,14 @@
|
||||
{
|
||||
"url": "guide/file-structure",
|
||||
"title": "Project File Structure",
|
||||
"tooltip": "How your Angular workspace looks in your filesystem."
|
||||
"tooltip": "How your Angular workspace looks on 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 a2129510d7d57d1c02bec563872adf0204e11a2f",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 4faa81e25",
|
||||
"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,6 +30,8 @@
|
||||
"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",
|
||||
@ -109,11 +111,11 @@
|
||||
"cross-spawn": "^5.1.0",
|
||||
"css-selector-parser": "^1.3.0",
|
||||
"dgeni": "^0.4.7",
|
||||
"dgeni-packages": "^0.26.9",
|
||||
"dgeni-packages": "^0.26.12",
|
||||
"entities": "^1.1.1",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-plugin-jasmine": "^2.2.0",
|
||||
"firebase-tools": "^3.2.1",
|
||||
"firebase-tools": "^5.1.1",
|
||||
"fs-extra": "^2.1.2",
|
||||
"globby": "^6.1.0",
|
||||
"hast-util-is-element": "^1.0.0",
|
||||
@ -163,4 +165,4 @@
|
||||
"xregexp": "^4.0.0",
|
||||
"yargs": "^7.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
yarn build --progress=false
|
||||
|
||||
# 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
|
||||
yarn build-for $deployEnv --progress=false
|
||||
|
||||
# Include any mode-specific files
|
||||
cp -rf src/extra-files/$deployEnv/. dist/
|
||||
@ -106,8 +106,8 @@ fi
|
||||
yarn payload-size
|
||||
|
||||
# Deploy to Firebase
|
||||
firebase use "$projectId" --token "$firebaseToken"
|
||||
firebase deploy --message "Commit: $CI_COMMIT" --non-interactive --token "$firebaseToken"
|
||||
yarn firebase use "$projectId" --token "$firebaseToken"
|
||||
yarn 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,8 +45,9 @@ 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 PWA tests.
|
||||
then(() => runPwaTests());
|
||||
// The preview is now available. Run the tests.
|
||||
then(() => yarnRun('smoke-tests', previewUrl)).
|
||||
then(() => yarnRun('test-pwa-score', previewUrl, minPwaScore));
|
||||
}).
|
||||
catch(onError);
|
||||
|
||||
@ -93,15 +94,6 @@ 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$/, ''));
|
||||
@ -119,3 +111,12 @@ 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
|
||||
yarn install --frozen-lockfile --non-interactive
|
||||
yarn update-webdriver
|
||||
|
||||
# Run checks for all URLs.
|
||||
|
@ -3,9 +3,11 @@
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./*.e2e-spec.ts'
|
||||
],
|
||||
suites: {
|
||||
full: './*.e2e-spec.ts',
|
||||
smoke: './smoke-tests.e2e-spec.ts',
|
||||
},
|
||||
suite: 'full',
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
// For Travis
|
||||
|
@ -59,7 +59,9 @@ 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,6 +29,8 @@ 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]);
|
||||
});
|
||||
});
|
||||
@ -39,7 +41,7 @@ describe(browser.baseUrl, () => {
|
||||
api: 'api list',
|
||||
'guide/architecture': 'architecture',
|
||||
'guide/http': 'httpclient',
|
||||
'guide/quickstart': 'quickstart',
|
||||
'guide/quickstart': 'getting started',
|
||||
'guide/security': 'security',
|
||||
tutorial: 'tutorial',
|
||||
};
|
||||
@ -47,6 +49,8 @@ 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]);
|
||||
});
|
||||
});
|
||||
@ -68,6 +72,8 @@ 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-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/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-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.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-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.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-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/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-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.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-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.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-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/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-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.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",
|
||||
"@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",
|
||||
"@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-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/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-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.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",
|
||||
"@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",
|
||||
"@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,7 +30,9 @@ 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)) &&
|
||||
if (autoLinkCodeImpl.codeElements.some(elementType =>
|
||||
is(node, elementType)) &&
|
||||
(!node.properties.className || node.properties.className.indexOf('no-auto-link') === -1) &&
|
||||
ancestors.every(ancestor => !is(ancestor, 'a'))) {
|
||||
visit(node, 'text', (node, ancestors) => {
|
||||
// Only interested in text nodes that are not inside links
|
||||
|
@ -109,4 +109,11 @@ 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,40 +47,6 @@ 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]; })
|
||||
@ -104,14 +70,10 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
if (isString(value) && !propertiesToIgnore[key]) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
|
||||
// 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); });
|
||||
}
|
||||
});
|
||||
|
||||
extractMemberWords(doc, members, membersMap);
|
||||
|
||||
// Extract all the keywords from the headings
|
||||
if (doc.vFile && doc.vFile.headings) {
|
||||
Object.keys(doc.vFile.headings).forEach(function(headingTag) {
|
||||
@ -166,4 +128,54 @@ 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,6 +128,46 @@ 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,9 +12,14 @@
|
||||
{$ 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>{$ command.name $}</code></a></td>
|
||||
<td>{% for alias in command.commandAliases %}<code>{$ alias $} </code>{% endfor %}</td>
|
||||
<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>{$ 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">ng {%if prefix %}{$ prefix $} {% endif %}<span class="cli-name">{$ name $}</span>
|
||||
<code-example hideCopy="true" class="no-box api-heading no-auto-link">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><<var>{$ option.name $}</var>></code></td>
|
||||
<td><code class="no-auto-link"><<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><a class="code-anchor" href="#{$ subcommand.name $}-command">{$ subcommand.name $}</a></code></li>
|
||||
<li><code class="no-auto-link"><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">{$ renderOption(option.name, option.type, option.default, option.enum) $}</code>
|
||||
<code class="cli-option-syntax no-auto-link">{$ 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>{$ option.default $}</code></p>{% endif %}
|
||||
{% if option.default !== undefined %}<p><span class="cli-default">Default:</span> <code class="no-auto-link">{$ 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><a id="{$ subcommand.name $}-command"></a>{$ subcommand.name $}</code></h3>
|
||||
<h3><code class="no-auto-link"><a id="{$ subcommand.name $}-command"></a>{$ subcommand.name $}</code></h3>
|
||||
{% for name in container.names %}
|
||||
{$ renderSyntax(subcommand, name) $}
|
||||
{% endfor %}
|
||||
|
1850
aio/yarn.lock
1850
aio/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -9,21 +9,14 @@ Bazel.
|
||||
|
||||
## Installation
|
||||
|
||||
Install Bazel from the distribution, see [install] instructions.
|
||||
On Mac, just `brew install bazel`.
|
||||
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.
|
||||
|
||||
Bazel will install a hermetic version of Node, npm, and Yarn when
|
||||
you run the first build.
|
||||
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.
|
||||
|
||||
[install]: https://bazel.build/versions/master/docs/install.html
|
||||
|
||||
### Installation of ibazel
|
||||
|
||||
Install interactive bazel runner / fs watcher via:
|
||||
|
||||
```
|
||||
yarn global add @bazel/ibazel
|
||||
```
|
||||
You can access Bazel with the `yarn bazel` command
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -33,12 +26,6 @@ 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
|
||||
@ -50,8 +37,8 @@ want Bazel to create several symlinks in your project directory
|
||||
|
||||
## Building Angular
|
||||
|
||||
- Build a package: `bazel build packages/core`
|
||||
- Build all packages: `bazel build packages/...`
|
||||
- Build a package: `yarn bazel build packages/core`
|
||||
- Build all packages: `yarn 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
|
||||
@ -61,9 +48,9 @@ new as of May 2017 and not very stable yet.
|
||||
|
||||
## Testing Angular
|
||||
|
||||
- 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/...`
|
||||
- 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/...`
|
||||
|
||||
You can use [ibazel] to get a "watch mode" that continuously
|
||||
keeps the outputs up-to-date as you save sources.
|
||||
@ -72,19 +59,20 @@ 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=ivy=false` is defined as default.
|
||||
See also: [`//.bazelrc`](https://github.com/angular/angular/blob/master/.bazelrc) where `--define=compile=legacy` 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).
|
||||
- `legacy`: (default behavior) compile against View Engine, e.g. `--define=compile=legacy`
|
||||
- `jit`: Compile in ivy JIT mode, e.g. `--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`.
|
||||
- `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`).
|
||||
|
||||
|
||||
### Debugging a Node Test
|
||||
@ -92,7 +80,7 @@ of your rules in any given `BUILD.bazel`.
|
||||
|
||||
- Open chrome at: [chrome://inspect](chrome://inspect)
|
||||
- Click on `Open dedicated DevTools for Node` to launch a debugger.
|
||||
- Run test: `bazel test packages/core/test:test --config=debug`
|
||||
- Run test: `yarn 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).
|
||||
|
||||
@ -129,7 +117,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 (`bazel test <target> --config=debug`).
|
||||
and launch the bazel corresponding test (`yarn 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
|
||||
@ -137,7 +125,7 @@ Apple+Shift+D on Mac) and click on the green play icon next to the configuration
|
||||
|
||||
### Debugging a Karma Test
|
||||
|
||||
- Run test: `bazel run packages/core/test:test_web`
|
||||
- Run test: `yarn bazel run packages/core/test:test_web`
|
||||
- Open chrome at: [http://localhost:9876/debug.html](http://localhost:9876/debug.html)
|
||||
- Open chrome inspector
|
||||
|
||||
@ -150,7 +138,7 @@ open $(bazel info output_base)/external
|
||||
|
||||
See subcommands that bazel executes (helpful for debugging):
|
||||
```sh
|
||||
bazel build //packages/core:package -s
|
||||
yarn bazel build //packages/core:package -s
|
||||
```
|
||||
|
||||
To debug nodejs_binary executable paths uncomment `find . -name rollup 1>&2` (~ line 96) in
|
||||
@ -167,7 +155,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 `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 `yarn 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
|
||||
|
||||
@ -205,7 +193,7 @@ See [bazelbuild/intellij#246](https://github.com/bazelbuild/intellij/issues/246)
|
||||
If you see the following error:
|
||||
|
||||
```
|
||||
$ bazel build packages/...
|
||||
$ yarn 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
|
||||
```
|
||||
@ -227,7 +215,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
|
||||
bazel build //packages/core # Run a build outside VSCode to pre-build the xcode; then safe to run VSCode
|
||||
yarn 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,6 +5,9 @@
|
||||
"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,3 +2,24 @@
|
||||
# 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,7 +17,7 @@ ts_library(
|
||||
"//modules/benchmarks/src/largetable:util_lib",
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
@ -59,7 +59,11 @@ protractor_web_test(
|
||||
],
|
||||
on_prepare = ":protractor.on-prepare.js",
|
||||
server = ":devserver",
|
||||
tags = ["manual"],
|
||||
tags = [
|
||||
"fixme-ivy-aot",
|
||||
"fixme-ivy-jit",
|
||||
"ivy-only",
|
||||
],
|
||||
deps = [
|
||||
"//modules/benchmarks/src/largetable:perf_lib",
|
||||
],
|
||||
|
@ -1,6 +1,8 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//tools:defaults.bzl", "ng_module")
|
||||
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")
|
||||
|
||||
ng_module(
|
||||
name = "render3_lib",
|
||||
@ -13,6 +15,54 @@ ng_module(
|
||||
"//modules/benchmarks/src/tree:util_lib",
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
ng_rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "modules/benchmarks/src/tree/render3/index.js",
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
":tree_lib",
|
||||
],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "favicon",
|
||||
srcs = ["//modules/benchmarks:favicon"],
|
||||
outs = ["favicon.ico"],
|
||||
cmd = "cp $< $@",
|
||||
)
|
||||
|
||||
ts_devserver(
|
||||
name = "devserver",
|
||||
static_files = [
|
||||
":bundle.min_debug.js",
|
||||
":bundle.min.js",
|
||||
"index.html",
|
||||
":favicon",
|
||||
],
|
||||
tags = ["ivy-only"],
|
||||
)
|
||||
|
||||
protractor_web_test(
|
||||
name = "perf",
|
||||
configuration = "//:protractor-perf.conf.js",
|
||||
data = [
|
||||
"//packages/bazel/src/protractor/utils",
|
||||
"//packages/benchpress",
|
||||
],
|
||||
on_prepare = ":protractor.on_prepare.js",
|
||||
server = ":devserver",
|
||||
tags = [
|
||||
"fixme-ivy-aot",
|
||||
"fixme-ivy-jit",
|
||||
"ivy-only",
|
||||
],
|
||||
deps = [
|
||||
"@ngdeps//node-uuid",
|
||||
"@ngdeps//protractor",
|
||||
"@ngdeps//yargs",
|
||||
],
|
||||
)
|
||||
|
96
package.json
96
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "7.0.1",
|
||||
"version": "7.0.2",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@ -26,43 +26,28 @@
|
||||
"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=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"
|
||||
"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"
|
||||
},
|
||||
"// 1": "dependencies are used locally and by bazel",
|
||||
"dependencies": {
|
||||
"@angular-devkit/schematics": "^0.5.5",
|
||||
"@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",
|
||||
"@schematics/angular": "^0.5.4",
|
||||
"@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",
|
||||
@ -72,23 +57,57 @@
|
||||
"angular-mocks-1.5": "npm:angular-mocks@1.5",
|
||||
"angular-mocks-1.6": "npm:angular-mocks@1.6",
|
||||
"base64-js": "1.2.1",
|
||||
"bower": "1.8.2",
|
||||
"browserstacktunnel-wrapper": "2.0.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",
|
||||
"clang-format": "1.0.41",
|
||||
"cldr": "4.10.0",
|
||||
"cldr-data-downloader": "0.3.2",
|
||||
"cldrjs": "0.5.0",
|
||||
"conventional-changelog": "^2.0.3",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"core-js": "^2.4.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",
|
||||
@ -100,44 +119,29 @@
|
||||
"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",
|
||||
"selenium-webdriver": "3.5.0",
|
||||
"rxjs": "^6.3.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",
|
||||
"xhr2": "0.1.4",
|
||||
"yargs": "9.0.1"
|
||||
"webpack": "1.12.9"
|
||||
}
|
||||
}
|
||||
|
@ -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 `bazel build //packages/bazel/docs` to verify
|
||||
# Run `yarn bazel build //packages/bazel/docs` to verify
|
||||
|
@ -22,6 +22,13 @@ 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",
|
||||
@ -80,16 +87,11 @@ 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 = "edf39af5fc257521e4af4c40829fffe8fba6d0ebff9f4dd69a6f8f1223ae047b",
|
||||
strip_prefix = "buildtools-%s" % BAZEL_BUILDTOOLS_VERSION,
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/%s.zip" % BAZEL_BUILDTOOLS_VERSION,
|
||||
sha256 = "a82d4b353942b10c1535528b02bff261d020827c9c57e112569eddcb1c93d7f6",
|
||||
strip_prefix = "buildtools-0.17.2",
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/0.17.2.zip",
|
||||
)
|
||||
|
||||
#############################################
|
||||
|
@ -209,16 +209,20 @@ 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 when angular is built from source as an external repository
|
||||
if (fileName ===
|
||||
path.join(
|
||||
compilerOpts.baseUrl, 'external/angular', bazelOpts.package,
|
||||
compilerOpts.flatModuleOutFile + '.ts'))
|
||||
// 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'))
|
||||
return true;
|
||||
return origBazelHostShouldNameModule(fileName) || NGC_GEN_FILES.test(fileName);
|
||||
};
|
||||
|
@ -101,7 +101,7 @@ function runPackageGoldTest(testPackage: TestPackage) {
|
||||
` Diff:\n` +
|
||||
` ${patch}\n\n` +
|
||||
` To accept the new golden file, run:\n` +
|
||||
` bazel run ${process.env['BAZEL_TARGET']}.accept\n`;
|
||||
` yarn bazel run ${process.env['BAZEL_TARGET']}.accept\n`;
|
||||
|
||||
fail(failureMessage);
|
||||
}
|
||||
|
@ -15,5 +15,6 @@ ts_library(
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
"@ngdeps//@types/node",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ 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",
|
||||
@ -9,6 +10,10 @@ 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",
|
||||
@ -19,6 +24,7 @@ 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
|
||||
bazel build //packages/compiler-cli/src/ngcc
|
||||
yarn bazel build //packages/compiler-cli/src/ngcc
|
||||
```
|
||||
|
||||
## Unit Testing
|
||||
@ -18,7 +18,7 @@ bazel build //packages/compiler-cli/src/ngcc
|
||||
The unit tests are built and run using Bazel:
|
||||
|
||||
```bash
|
||||
bazel test //packages/compiler-cli/src/ngcc/test
|
||||
yarn bazel test //packages/compiler-cli/src/ngcc/test
|
||||
```
|
||||
|
||||
## Integration Testing
|
||||
@ -26,5 +26,5 @@ bazel test //packages/compiler-cli/src/ngcc/test
|
||||
There are tests that check the behaviour of the overall executable:
|
||||
|
||||
```bash
|
||||
bazel test //packages/compiler-cli/test/ngcc
|
||||
yarn bazel test //packages/compiler-cli/test/ngcc
|
||||
```
|
||||
|
@ -202,6 +202,7 @@ export class ComponentDecoratorHandler implements
|
||||
directives: EMPTY_MAP,
|
||||
wrapDirectivesInClosure: false, //
|
||||
animations,
|
||||
viewProviders: null,
|
||||
},
|
||||
parsedTemplate: template.nodes,
|
||||
},
|
||||
|
@ -177,6 +177,7 @@ export function extractDirectiveMetadata(
|
||||
type: new WrappedNodeExpr(clazz.name !),
|
||||
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
|
||||
typeSourceSpan: null !, usesInheritance, exportAs,
|
||||
providers: null,
|
||||
};
|
||||
return {decoratedElements, decorator: directive, metadata};
|
||||
}
|
||||
@ -327,7 +328,7 @@ function parseFieldToPropertyMapping(
|
||||
*/
|
||||
function parseDecoratedFields(
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker): {[field: string]: string} {
|
||||
checker: ts.TypeChecker) {
|
||||
return fields.reduce(
|
||||
(results, field) => {
|
||||
const fieldName = field.member.name;
|
||||
@ -353,6 +354,14 @@ 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[] {
|
||||
|
@ -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], key));
|
||||
Object.keys(inputs).forEach(key => propMatch.set(inputs[key] as string, key));
|
||||
|
||||
// Add a binding expression to the map for each input of the directive that has a
|
||||
// matching binding.
|
||||
|
@ -1,3 +1,5 @@
|
||||
Tests in this directory should be run with:
|
||||
|
||||
bazel test --define=compile=aot packages/compiler-cli/test/compliance:compliance
|
||||
```
|
||||
yarn bazel test --define=compile=aot packages/compiler-cli/test/compliance:compliance
|
||||
```
|
@ -13,6 +13,9 @@
|
||||
"paths": {
|
||||
"@angular/compiler": ["../../dist/packages/compiler"]
|
||||
},
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"outDir": "../../dist/packages/compiler-cli"
|
||||
},
|
||||
"bazelOptions": {
|
||||
|
@ -22,5 +22,5 @@
|
||||
"ng-update": {
|
||||
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
"sideEffects": true
|
||||
}
|
@ -353,8 +353,8 @@ export class StaticSymbolResolver {
|
||||
// correctly.
|
||||
const originFilePath = this.resolveModule(origin, filePath);
|
||||
if (!originFilePath) {
|
||||
this.reportError(
|
||||
new Error(`Couldn't resolve original symbol for ${origin} from ${filePath}`));
|
||||
this.reportError(new Error(
|
||||
`Couldn't resolve original symbol for ${origin} from ${this.host.getOutputName(filePath)}`));
|
||||
} else {
|
||||
this.symbolResourcePaths.set(symbol, originFilePath);
|
||||
}
|
||||
@ -420,7 +420,8 @@ export class StaticSymbolResolver {
|
||||
if (!filePath) {
|
||||
return {
|
||||
__symbolic: 'error',
|
||||
message: `Could not resolve ${module} relative to ${sourceSymbol.filePath}.`,
|
||||
message:
|
||||
`Could not resolve ${module} relative to ${self.host.getMetadataFor(sourceSymbol.filePath)}.`,
|
||||
line: map.line,
|
||||
character: map.character,
|
||||
fileName: getOriginalName()
|
||||
@ -504,7 +505,7 @@ export class StaticSymbolResolver {
|
||||
if (moduleMetadata['version'] != SUPPORTED_SCHEMA_VERSION) {
|
||||
const errorMessage = moduleMetadata['version'] == 2 ?
|
||||
`Unsupported metadata version ${moduleMetadata['version']} for module ${module}. This module should be compiled with a newer version of ngc` :
|
||||
`Metadata version mismatch for module ${module}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`;
|
||||
`Metadata version mismatch for module ${this.host.getOutputName(module)}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`;
|
||||
this.reportError(new Error(errorMessage));
|
||||
}
|
||||
this.metadataCache.set(module, moduleMetadata);
|
||||
@ -518,7 +519,7 @@ export class StaticSymbolResolver {
|
||||
if (!filePath) {
|
||||
this.reportError(
|
||||
new Error(`Could not resolve module ${module}${containingFile ? ' relative to ' +
|
||||
containingFile : ''}`));
|
||||
this.host.getOutputName(containingFile) : ''}`));
|
||||
return this.getStaticSymbol(`ERROR:${module}`, symbolName);
|
||||
}
|
||||
return this.getStaticSymbol(filePath, symbolName);
|
||||
|
@ -6,6 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
//////////////////////////////////////
|
||||
// THIS FILE HAS GLOBAL SIDE EFFECT //
|
||||
// (see bottom of file) //
|
||||
//////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @module
|
||||
* @description
|
||||
@ -23,6 +28,8 @@
|
||||
*/
|
||||
|
||||
import * as core from './core';
|
||||
import {publishFacade} from './jit_compiler_facade';
|
||||
import {global} from './util';
|
||||
|
||||
export {core};
|
||||
|
||||
@ -91,4 +98,9 @@ export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compile
|
||||
export {makeBindingParser, parseTemplate} from './render3/view/template';
|
||||
export {R3Reference} from './render3/util';
|
||||
export {compileBaseDefFromMetadata, R3BaseRefMetaData, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
|
||||
export {publishFacade} from './jit_compiler_facade';
|
||||
// This file only reexports content of the `src` folder. Keep it that way.
|
||||
|
||||
// This function call has a global side effects and publishes the compiler into global namespace for
|
||||
// the late binding of the Compiler to the @angular/core for jit compilation.
|
||||
publishFacade(global);
|
146
packages/compiler/src/compiler_facade_interface.ts
Normal file
146
packages/compiler/src/compiler_facade_interface.ts
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A set of interfaces which are shared between `@angular/core` and `@angular/compiler` to allow
|
||||
* for late binding of `@angular/compiler` for JIT purposes.
|
||||
*
|
||||
* This file has two copies. Please ensure that they are in sync:
|
||||
* - packages/compiler/src/compiler_facade_interface.ts (master)
|
||||
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
|
||||
*
|
||||
* Please ensure that the two files are in sync using this command:
|
||||
* ```
|
||||
* cp packages/compiler/src/compiler_facade_interface.ts \
|
||||
* packages/core/src/render3/jit/compiler_facade_interface.ts
|
||||
* ```
|
||||
*/
|
||||
|
||||
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; }
|
||||
|
||||
export interface CompilerFacade {
|
||||
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
|
||||
any;
|
||||
compileInjectable(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectableMetadataFacade): any;
|
||||
compileInjector(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectorMetadataFacade): any;
|
||||
compileNgModule(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3NgModuleMetadataFacade): any;
|
||||
compileDirective(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
|
||||
compileComponent(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
|
||||
|
||||
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
|
||||
}
|
||||
|
||||
export interface CoreEnvironment { [name: string]: Function; }
|
||||
|
||||
export type StringMap = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
export type StringMapWithRename = {
|
||||
[key: string]: string | [string, string];
|
||||
};
|
||||
|
||||
export type Provider = any;
|
||||
|
||||
export enum R3ResolvedDependencyType {
|
||||
Token = 0,
|
||||
Attribute = 1,
|
||||
Injector = 2,
|
||||
}
|
||||
|
||||
export interface R3DependencyMetadataFacade {
|
||||
token: any;
|
||||
resolved: R3ResolvedDependencyType;
|
||||
host: boolean;
|
||||
optional: boolean;
|
||||
self: boolean;
|
||||
skipSelf: boolean;
|
||||
}
|
||||
|
||||
export interface R3PipeMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
pipeName: string;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
pure: boolean;
|
||||
}
|
||||
|
||||
export interface R3InjectableMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
ctorDeps: R3DependencyMetadataFacade[]|null;
|
||||
providedIn: any;
|
||||
useClass?: any;
|
||||
useFactory?: any;
|
||||
useExisting?: any;
|
||||
useValue?: any;
|
||||
userDeps?: R3DependencyMetadataFacade[];
|
||||
}
|
||||
|
||||
export interface R3NgModuleMetadataFacade {
|
||||
type: any;
|
||||
bootstrap: Function[];
|
||||
declarations: Function[];
|
||||
imports: Function[];
|
||||
exports: Function[];
|
||||
emitInline: boolean;
|
||||
}
|
||||
|
||||
export interface R3InjectorMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
providers: any;
|
||||
imports: any;
|
||||
}
|
||||
|
||||
export interface R3DirectiveMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
typeArgumentCount: number;
|
||||
typeSourceSpan: null;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
selector: string|null;
|
||||
queries: R3QueryMetadataFacade[];
|
||||
host: {[key: string]: string};
|
||||
propMetadata: {[key: string]: any[]};
|
||||
lifecycle: {usesOnChanges: boolean;};
|
||||
inputs: string[];
|
||||
outputs: string[];
|
||||
usesInheritance: boolean;
|
||||
exportAs: string|null;
|
||||
providers: Provider[]|null;
|
||||
}
|
||||
|
||||
export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
|
||||
template: string;
|
||||
preserveWhitespaces: boolean;
|
||||
animations: any[]|undefined;
|
||||
viewQueries: R3QueryMetadataFacade[];
|
||||
pipes: Map<string, any>;
|
||||
directives: Map<string, any>;
|
||||
styles: string[];
|
||||
encapsulation: ViewEncapsulation;
|
||||
viewProviders: Provider[]|null;
|
||||
}
|
||||
|
||||
export type ViewEncapsulation = number;
|
||||
|
||||
export interface R3QueryMetadataFacade {
|
||||
propertyName: string;
|
||||
first: boolean;
|
||||
predicate: any|string[];
|
||||
descendants: boolean;
|
||||
read: any|null;
|
||||
}
|
294
packages/compiler/src/jit_compiler_facade.ts
Normal file
294
packages/compiler/src/jit_compiler_facade.ts
Normal file
@ -0,0 +1,294 @@
|
||||
/**
|
||||
* @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 {CompilerFacade, CoreEnvironment, ExportedCompilerFacade, R3ComponentMetadataFacade, R3DependencyMetadataFacade, R3DirectiveMetadataFacade, R3InjectableMetadataFacade, R3InjectorMetadataFacade, R3NgModuleMetadataFacade, R3PipeMetadataFacade, R3QueryMetadataFacade, StringMap, StringMapWithRename} from './compiler_facade_interface';
|
||||
import {ConstantPool} from './constant_pool';
|
||||
import {HostBinding, HostListener, Input, Output, Type} from './core';
|
||||
import {compileInjectable} from './injectable_compiler_2';
|
||||
import {Expression, LiteralExpr, WrappedNodeExpr} from './output/output_ast';
|
||||
import {R3DependencyMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
||||
import {jitExpression} from './render3/r3_jit';
|
||||
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler';
|
||||
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
|
||||
import {R3Reference} from './render3/util';
|
||||
import {R3DirectiveMetadata, R3QueryMetadata} from './render3/view/api';
|
||||
import {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
|
||||
import {makeBindingParser, parseTemplate} from './render3/view/template';
|
||||
|
||||
export class CompilerFacadeImpl implements CompilerFacade {
|
||||
R3ResolvedDependencyType = R3ResolvedDependencyType as any;
|
||||
|
||||
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade):
|
||||
any {
|
||||
const res = compilePipeFromMetadata({
|
||||
name: facade.name,
|
||||
type: new WrappedNodeExpr(facade.type),
|
||||
deps: convertR3DependencyMetadataArray(facade.deps),
|
||||
pipeName: facade.pipeName,
|
||||
pure: facade.pure,
|
||||
});
|
||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
||||
}
|
||||
|
||||
compileInjectable(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
|
||||
facade: R3InjectableMetadataFacade): any {
|
||||
const {expression, statements} = compileInjectable({
|
||||
name: facade.name,
|
||||
type: new WrappedNodeExpr(facade.type),
|
||||
providedIn: computeProvidedIn(facade.providedIn),
|
||||
useClass: wrapExpression(facade, USE_CLASS),
|
||||
useFactory: wrapExpression(facade, USE_FACTORY),
|
||||
useValue: wrapExpression(facade, USE_VALUE),
|
||||
useExisting: wrapExpression(facade, USE_EXISTING),
|
||||
ctorDeps: convertR3DependencyMetadataArray(facade.ctorDeps),
|
||||
userDeps: convertR3DependencyMetadataArray(facade.userDeps) || undefined,
|
||||
});
|
||||
|
||||
return jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
|
||||
}
|
||||
|
||||
compileInjector(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
|
||||
facade: R3InjectorMetadataFacade): any {
|
||||
const meta: R3InjectorMetadata = {
|
||||
name: facade.name,
|
||||
type: new WrappedNodeExpr(facade.type),
|
||||
deps: convertR3DependencyMetadataArray(facade.deps),
|
||||
providers: new WrappedNodeExpr(facade.providers),
|
||||
imports: new WrappedNodeExpr(facade.imports),
|
||||
};
|
||||
const res = compileInjector(meta);
|
||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
||||
}
|
||||
|
||||
compileNgModule(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
|
||||
facade: R3NgModuleMetadataFacade): any {
|
||||
const meta: R3NgModuleMetadata = {
|
||||
type: new WrappedNodeExpr(facade.type),
|
||||
bootstrap: facade.bootstrap.map(wrapReference),
|
||||
declarations: facade.declarations.map(wrapReference),
|
||||
imports: facade.imports.map(wrapReference),
|
||||
exports: facade.exports.map(wrapReference),
|
||||
emitInline: true,
|
||||
};
|
||||
const res = compileNgModule(meta);
|
||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
|
||||
}
|
||||
|
||||
compileDirective(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
|
||||
facade: R3DirectiveMetadataFacade): any {
|
||||
const constantPool = new ConstantPool();
|
||||
const bindingParser = makeBindingParser();
|
||||
|
||||
const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade);
|
||||
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
|
||||
const preStatements = [...constantPool.statements, ...res.statements];
|
||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
||||
}
|
||||
|
||||
compileComponent(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
|
||||
facade: R3ComponentMetadataFacade): any {
|
||||
// The ConstantPool is a requirement of the JIT'er.
|
||||
const constantPool = new ConstantPool();
|
||||
|
||||
// Parse the template and check for errors.
|
||||
const template = parseTemplate(
|
||||
facade.template, sourceMapUrl, {
|
||||
preserveWhitespaces: facade.preserveWhitespaces || false,
|
||||
},
|
||||
'');
|
||||
if (template.errors !== undefined) {
|
||||
const errors = template.errors.map(err => err.toString()).join(', ');
|
||||
throw new Error(`Errors during JIT compilation of template for ${facade.name}: ${errors}`);
|
||||
}
|
||||
|
||||
// Compile the component metadata, including template, into an expression.
|
||||
// TODO(alxhub): implement inputs, outputs, queries, etc.
|
||||
const res = compileComponentFromMetadata(
|
||||
{
|
||||
...facade as R3ComponentMetadataFacadeNoPropAndWhitespace,
|
||||
...convertDirectiveFacadeToMetadata(facade),
|
||||
template,
|
||||
viewQueries: facade.viewQueries.map(convertToR3QueryMetadata),
|
||||
wrapDirectivesInClosure: false,
|
||||
styles: facade.styles || [],
|
||||
encapsulation: facade.encapsulation as any,
|
||||
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
|
||||
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) :
|
||||
null,
|
||||
},
|
||||
constantPool, makeBindingParser());
|
||||
const preStatements = [...constantPool.statements, ...res.statements];
|
||||
|
||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
||||
}
|
||||
}
|
||||
|
||||
// This seems to be needed to placate TS v3.0 only
|
||||
type R3ComponentMetadataFacadeNoPropAndWhitespace = Pick<
|
||||
R3ComponentMetadataFacade,
|
||||
Exclude<Exclude<keyof R3ComponentMetadataFacade, 'preserveWhitespaces'>, 'propMetadata'>>;
|
||||
|
||||
const USE_CLASS = Object.keys({useClass: null})[0];
|
||||
const USE_FACTORY = Object.keys({useFactory: null})[0];
|
||||
const USE_VALUE = Object.keys({useValue: null})[0];
|
||||
const USE_EXISTING = Object.keys({useExisting: null})[0];
|
||||
|
||||
const wrapReference = function(value: Type): R3Reference {
|
||||
const wrapped = new WrappedNodeExpr(value);
|
||||
return {value: wrapped, type: wrapped};
|
||||
};
|
||||
|
||||
function convertToR3QueryMetadata(facade: R3QueryMetadataFacade): R3QueryMetadata {
|
||||
return {
|
||||
...facade,
|
||||
predicate: Array.isArray(facade.predicate) ? facade.predicate :
|
||||
new WrappedNodeExpr(facade.predicate),
|
||||
read: facade.read ? new WrappedNodeExpr(facade.read) : null,
|
||||
};
|
||||
}
|
||||
|
||||
function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3DirectiveMetadata {
|
||||
const inputsFromMetadata = parseInputOutputs(facade.inputs || []);
|
||||
const outputsFromMetadata = parseInputOutputs(facade.outputs || []);
|
||||
const propMetadata = facade.propMetadata;
|
||||
const inputsFromType: StringMapWithRename = {};
|
||||
const outputsFromType: StringMap = {};
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isInput(ann)) {
|
||||
inputsFromType[field] =
|
||||
ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field;
|
||||
} else if (isOutput(ann)) {
|
||||
outputsFromType[field] = ann.bindingPropertyName || field;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...facade as R3DirectiveMetadataFacadeNoPropAndWhitespace,
|
||||
typeSourceSpan: null !,
|
||||
type: new WrappedNodeExpr(facade.type),
|
||||
deps: convertR3DependencyMetadataArray(facade.deps),
|
||||
host: extractHostBindings(facade.host, facade.propMetadata),
|
||||
inputs: {...inputsFromMetadata, ...inputsFromType},
|
||||
outputs: {...outputsFromMetadata, ...outputsFromType},
|
||||
providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null,
|
||||
};
|
||||
}
|
||||
|
||||
// This seems to be needed to placate TS v3.0 only
|
||||
type R3DirectiveMetadataFacadeNoPropAndWhitespace =
|
||||
Pick<R3DirectiveMetadataFacade, Exclude<keyof R3DirectiveMetadataFacade, 'propMetadata'>>;
|
||||
|
||||
function wrapExpression(obj: any, property: string): WrappedNodeExpr<any>|undefined {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
return new WrappedNodeExpr(obj[property]);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function computeProvidedIn(providedIn: Type | string | null | undefined): Expression {
|
||||
if (providedIn == null || typeof providedIn === 'string') {
|
||||
return new LiteralExpr(providedIn);
|
||||
} else {
|
||||
return new WrappedNodeExpr(providedIn);
|
||||
}
|
||||
}
|
||||
|
||||
function convertR3DependencyMetadata(facade: R3DependencyMetadataFacade): R3DependencyMetadata {
|
||||
let tokenExpr;
|
||||
if (facade.token === null) {
|
||||
tokenExpr = new LiteralExpr(null);
|
||||
} else if (facade.resolved === R3ResolvedDependencyType.Attribute) {
|
||||
tokenExpr = new LiteralExpr(facade.token);
|
||||
} else {
|
||||
tokenExpr = new WrappedNodeExpr(facade.token);
|
||||
}
|
||||
return {
|
||||
token: tokenExpr,
|
||||
resolved: facade.resolved,
|
||||
host: facade.host,
|
||||
optional: facade.optional,
|
||||
self: facade.self,
|
||||
skipSelf: facade.skipSelf
|
||||
};
|
||||
}
|
||||
|
||||
function convertR3DependencyMetadataArray(facades: R3DependencyMetadataFacade[] | null | undefined):
|
||||
R3DependencyMetadata[]|null {
|
||||
return facades == null ? null : facades.map(convertR3DependencyMetadata);
|
||||
}
|
||||
|
||||
function extractHostBindings(host: {[key: string]: string}, propMetadata: {[key: string]: any[]}): {
|
||||
attributes: StringMap,
|
||||
listeners: StringMap,
|
||||
properties: StringMap,
|
||||
} {
|
||||
// First parse the declarations from the metadata.
|
||||
const {attributes, listeners, properties, animations} = parseHostBindings(host || {});
|
||||
|
||||
if (Object.keys(animations).length > 0) {
|
||||
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
|
||||
}
|
||||
|
||||
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isHostBinding(ann)) {
|
||||
properties[ann.hostPropertyName || field] = field;
|
||||
} else if (isHostListener(ann)) {
|
||||
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {attributes, listeners, properties};
|
||||
}
|
||||
|
||||
function isHostBinding(value: any): value is HostBinding {
|
||||
return value.ngMetadataName === 'HostBinding';
|
||||
}
|
||||
|
||||
function isHostListener(value: any): value is HostListener {
|
||||
return value.ngMetadataName === 'HostListener';
|
||||
}
|
||||
|
||||
|
||||
function isInput(value: any): value is Input {
|
||||
return value.ngMetadataName === 'Input';
|
||||
}
|
||||
|
||||
function isOutput(value: any): value is Output {
|
||||
return value.ngMetadataName === 'Output';
|
||||
}
|
||||
|
||||
function parseInputOutputs(values: string[]): StringMap {
|
||||
return values.reduce(
|
||||
(map, value) => {
|
||||
const [field, property] = value.split(',').map(piece => piece.trim());
|
||||
map[field] = property || field;
|
||||
return map;
|
||||
},
|
||||
{} as StringMap);
|
||||
}
|
||||
|
||||
export function publishFacade(global: any) {
|
||||
const ng: ExportedCompilerFacade = global.ng || (global.ng = {});
|
||||
ng.ɵcompilerFacade = new CompilerFacadeImpl();
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {StaticSymbol} from '../aot/static_symbol';
|
||||
import {CompileShallowModuleMetadata, identifierName} from '../compile_metadata';
|
||||
import {InjectableCompiler} from '../injectable_compiler';
|
||||
import {mapLiteral} from '../output/map_util';
|
||||
|
@ -86,7 +86,7 @@ export interface R3DirectiveMetadata {
|
||||
/**
|
||||
* A mapping of input field names to the property names.
|
||||
*/
|
||||
inputs: {[field: string]: string};
|
||||
inputs: {[field: string]: string | [string, string]};
|
||||
|
||||
/**
|
||||
* A mapping of output field names to the property names.
|
||||
@ -103,6 +103,11 @@ export interface R3DirectiveMetadata {
|
||||
* if any.
|
||||
*/
|
||||
exportAs: string|null;
|
||||
|
||||
/**
|
||||
* The list of providers defined in the directive.
|
||||
*/
|
||||
providers: o.Expression|null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,6 +185,11 @@ export interface R3ComponentMetadata extends R3DirectiveMetadata {
|
||||
* A collection of animation triggers that will be used in the component template.
|
||||
*/
|
||||
animations: o.Expression|null;
|
||||
|
||||
/**
|
||||
* The list of view providers defined in the component.
|
||||
*/
|
||||
viewProviders: o.Expression|null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,6 +320,7 @@ export function compileComponentFromRender2(
|
||||
encapsulation:
|
||||
(summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated,
|
||||
animations: null,
|
||||
viewProviders: null,
|
||||
};
|
||||
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
|
||||
|
||||
@ -362,6 +363,7 @@ function directiveMetadataFromGlobalMetadata(
|
||||
outputs: directive.outputs,
|
||||
usesInheritance: false,
|
||||
exportAs: null,
|
||||
providers: null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -505,7 +507,7 @@ function stringAsType(str: string): o.Type {
|
||||
return o.expressionType(o.literal(str));
|
||||
}
|
||||
|
||||
function stringMapAsType(map: {[key: string]: string}): o.Type {
|
||||
function stringMapAsType(map: {[key: string]: string | [string, string]}): o.Type {
|
||||
const mapValues = Object.keys(map).map(key => ({
|
||||
key,
|
||||
value: o.literal(map[key]),
|
||||
|
@ -44,7 +44,7 @@ export interface DirectiveMeta {
|
||||
*
|
||||
* Goes from property names to field names.
|
||||
*/
|
||||
inputs: {[property: string]: string};
|
||||
inputs: {[property: string]: string | [string, string]};
|
||||
|
||||
/**
|
||||
* Set of outputs which this directive claims.
|
||||
|
@ -67,8 +67,8 @@ export function asLiteral(value: any): o.Expression {
|
||||
return o.literal(value, o.INFERRED_TYPE);
|
||||
}
|
||||
|
||||
export function conditionallyCreateMapObjectLiteral(keys: {[key: string]: string}): o.Expression|
|
||||
null {
|
||||
export function conditionallyCreateMapObjectLiteral(
|
||||
keys: {[key: string]: string | [string, string]}): o.Expression|null {
|
||||
if (Object.getOwnPropertyNames(keys).length > 0) {
|
||||
return mapToExpression(keys);
|
||||
}
|
||||
|
@ -233,3 +233,19 @@ export interface Console {
|
||||
log(message: string): void;
|
||||
warn(message: string): void;
|
||||
}
|
||||
|
||||
|
||||
declare var WorkerGlobalScope: any;
|
||||
// CommonJS / Node have global context exposed as "global" variable.
|
||||
// We don't want to include the whole node.d.ts this this compilation unit so we'll just fake
|
||||
// the global "global" var for now.
|
||||
declare var global: any;
|
||||
const __window = typeof window !== 'undefined' && window;
|
||||
const __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
|
||||
self instanceof WorkerGlobalScope && self;
|
||||
const __global = typeof global !== 'undefined' && global;
|
||||
|
||||
// Check __global first, because in Node tests both __global and __window may be defined and _global
|
||||
// should be __global in that case.
|
||||
const _global: {[name: string]: any} = __global || __window || __self;
|
||||
export {_global as global};
|
||||
|
100
packages/compiler/test/compiler_facade_interface_spec.ts
Normal file
100
packages/compiler/test/compiler_facade_interface_spec.ts
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @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 core from '../../core/src/render3/jit/compiler_facade_interface';
|
||||
import {R3ResolvedDependencyType} from '../public_api';
|
||||
import * as compiler from '../src/compiler_facade_interface';
|
||||
|
||||
/**
|
||||
* This file is compiler level file which asserts that the set of interfaces in `@angular/core` and
|
||||
* `@angular/compiler` match. (Build time failure.)
|
||||
*
|
||||
* If this file fails to compile it means these two files when out of sync:
|
||||
* - packages/compiler/src/compiler_facade_interface.ts (master)
|
||||
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
|
||||
*
|
||||
* Please ensure that the two files are in sync using this command:
|
||||
* ```
|
||||
* cp packages/compiler/src/compiler_facade_interface.ts \
|
||||
* packages/core/src/render3/jit/compiler_facade_interface.ts
|
||||
* ```
|
||||
*/
|
||||
|
||||
const coreExportedCompilerFacade1: core.ExportedCompilerFacade =
|
||||
null !as compiler.ExportedCompilerFacade;
|
||||
const compilerExportedCompilerFacade2: compiler.ExportedCompilerFacade =
|
||||
null !as core.ExportedCompilerFacade;
|
||||
|
||||
const coreCompilerFacade: core.CompilerFacade = null !as compiler.CompilerFacade;
|
||||
const compilerCompilerFacade: compiler.CompilerFacade = null !as core.CompilerFacade;
|
||||
|
||||
const coreCoreEnvironment: core.CoreEnvironment = null !as compiler.CoreEnvironment;
|
||||
const compilerCoreEnvironment: compiler.CoreEnvironment = null !as core.CoreEnvironment;
|
||||
|
||||
const coreStringMap: core.StringMap = null !as compiler.StringMap;
|
||||
const compilerStringMap: compiler.StringMap = null !as core.StringMap;
|
||||
|
||||
const coreProvider: core.Provider = null !as compiler.Provider;
|
||||
const compilerProvider: compiler.Provider = null !as core.Provider;
|
||||
|
||||
const coreR3ResolvedDependencyType: core.R3ResolvedDependencyType =
|
||||
null !as compiler.R3ResolvedDependencyType;
|
||||
const compilerR3ResolvedDependencyType: compiler.R3ResolvedDependencyType =
|
||||
null !as core.R3ResolvedDependencyType;
|
||||
|
||||
const coreR3ResolvedDependencyType2: R3ResolvedDependencyType =
|
||||
null !as core.R3ResolvedDependencyType;
|
||||
const compilerR3ResolvedDependencyType2: R3ResolvedDependencyType =
|
||||
null !as core.R3ResolvedDependencyType;
|
||||
|
||||
const coreR3ResolvedDependencyType3: core.R3ResolvedDependencyType =
|
||||
null !as R3ResolvedDependencyType;
|
||||
const compilerR3ResolvedDependencyType3: compiler.R3ResolvedDependencyType =
|
||||
null !as R3ResolvedDependencyType;
|
||||
|
||||
const coreR3DependencyMetadataFacade: core.R3DependencyMetadataFacade =
|
||||
null !as compiler.R3DependencyMetadataFacade;
|
||||
const compilerR3DependencyMetadataFacade: compiler.R3DependencyMetadataFacade =
|
||||
null !as core.R3DependencyMetadataFacade;
|
||||
|
||||
const coreR3PipeMetadataFacade: core.R3PipeMetadataFacade = null !as compiler.R3PipeMetadataFacade;
|
||||
const compilerR3PipeMetadataFacade: compiler.R3PipeMetadataFacade =
|
||||
null !as core.R3PipeMetadataFacade;
|
||||
|
||||
const coreR3InjectableMetadataFacade: core.R3InjectableMetadataFacade =
|
||||
null !as compiler.R3InjectableMetadataFacade;
|
||||
const compilerR3InjectableMetadataFacade: compiler.R3InjectableMetadataFacade =
|
||||
null !as core.R3InjectableMetadataFacade;
|
||||
|
||||
const coreR3NgModuleMetadataFacade: core.R3NgModuleMetadataFacade =
|
||||
null !as compiler.R3NgModuleMetadataFacade;
|
||||
const compilerR3NgModuleMetadataFacade: compiler.R3NgModuleMetadataFacade =
|
||||
null !as core.R3NgModuleMetadataFacade;
|
||||
|
||||
const coreR3InjectorMetadataFacade: core.R3InjectorMetadataFacade =
|
||||
null !as compiler.R3InjectorMetadataFacade;
|
||||
const compilerR3InjectorMetadataFacade: compiler.R3InjectorMetadataFacade =
|
||||
null !as core.R3InjectorMetadataFacade;
|
||||
|
||||
const coreR3DirectiveMetadataFacade: core.R3DirectiveMetadataFacade =
|
||||
null !as compiler.R3DirectiveMetadataFacade;
|
||||
const compilerR3DirectiveMetadataFacade: compiler.R3DirectiveMetadataFacade =
|
||||
null !as core.R3DirectiveMetadataFacade;
|
||||
|
||||
const coreR3ComponentMetadataFacade: core.R3ComponentMetadataFacade =
|
||||
null !as compiler.R3ComponentMetadataFacade;
|
||||
const compilerR3ComponentMetadataFacade: compiler.R3ComponentMetadataFacade =
|
||||
null !as core.R3ComponentMetadataFacade;
|
||||
|
||||
const coreViewEncapsulation: core.ViewEncapsulation = null !as compiler.ViewEncapsulation;
|
||||
const compilerViewEncapsulation: compiler.ViewEncapsulation = null !as core.ViewEncapsulation;
|
||||
|
||||
const coreR3QueryMetadataFacade: core.R3QueryMetadataFacade =
|
||||
null !as compiler.R3QueryMetadataFacade;
|
||||
const compilerR3QueryMetadataFacade: compiler.R3QueryMetadataFacade =
|
||||
null !as core.R3QueryMetadataFacade;
|
@ -20,7 +20,6 @@ ng_module(
|
||||
module_name = "@angular/core",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"@ngdeps//zone.js",
|
||||
"@rxjs",
|
||||
"@rxjs//operators",
|
||||
|
@ -16,7 +16,6 @@
|
||||
"tslib": "^1.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/compiler": "0.0.0-PLACEHOLDER",
|
||||
"rxjs": "^6.0.0",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
@ -28,4 +27,4 @@
|
||||
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
}
|
@ -18,9 +18,9 @@ import {GetterFn, MethodFn, SetterFn} from './types';
|
||||
* Attention: These regex has to hold even if the code is minified!
|
||||
*/
|
||||
export const DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/;
|
||||
export const INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[A-Za-z\d$_]+\s*{/;
|
||||
export const INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
|
||||
export const INHERITED_CLASS_WITH_CTOR =
|
||||
/^class\s+[A-Za-z\d$_]*\s*extends\s+[A-Za-z\d$_]+\s*{[\s\S]*constructor\s*\(/;
|
||||
/^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/;
|
||||
|
||||
export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||
private _reflect: any;
|
||||
|
@ -448,6 +448,7 @@ function searchDirectivesOnInjector<T>(
|
||||
*/
|
||||
export function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>): number|Function|
|
||||
undefined {
|
||||
ngDevMode && assertDefined(token, 'token must be defined');
|
||||
const tokenId: number|undefined = (token as any)[NG_ELEMENT_ID];
|
||||
return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId;
|
||||
}
|
||||
|
22
packages/core/src/render3/jit/compiler_facade.ts
Normal file
22
packages/core/src/render3/jit/compiler_facade.ts
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
|
||||
*/
|
||||
import {global} from '../../util';
|
||||
import {CompilerFacade, ExportedCompilerFacade} from './compiler_facade_interface';
|
||||
export * from './compiler_facade_interface';
|
||||
|
||||
export function getCompilerFacade(): CompilerFacade {
|
||||
const globalNg: ExportedCompilerFacade = global.ng;
|
||||
if (!globalNg || !globalNg.ɵcompilerFacade) {
|
||||
throw new Error(
|
||||
`Angular JIT compilation failed: '@angular/compiler' not loaded!\n` +
|
||||
` - JIT compilation is discouraged for production use-cases! Consider AOT mode instead.\n` +
|
||||
` - Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?\n` +
|
||||
` - Alternatively provide the compiler with 'import "@angular/compiler";' before bootstrapping.`);
|
||||
}
|
||||
return globalNg.ɵcompilerFacade;
|
||||
}
|
146
packages/core/src/render3/jit/compiler_facade_interface.ts
Normal file
146
packages/core/src/render3/jit/compiler_facade_interface.ts
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A set of interfaces which are shared between `@angular/core` and `@angular/compiler` to allow
|
||||
* for late binding of `@angular/compiler` for JIT purposes.
|
||||
*
|
||||
* This file has two copies. Please ensure that they are in sync:
|
||||
* - packages/compiler/src/compiler_facade_interface.ts (master)
|
||||
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
|
||||
*
|
||||
* Please ensure that the two files are in sync using this command:
|
||||
* ```
|
||||
* cp packages/compiler/src/compiler_facade_interface.ts \
|
||||
* packages/core/src/render3/jit/compiler_facade_interface.ts
|
||||
* ```
|
||||
*/
|
||||
|
||||
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; }
|
||||
|
||||
export interface CompilerFacade {
|
||||
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
|
||||
any;
|
||||
compileInjectable(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectableMetadataFacade): any;
|
||||
compileInjector(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectorMetadataFacade): any;
|
||||
compileNgModule(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3NgModuleMetadataFacade): any;
|
||||
compileDirective(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
|
||||
compileComponent(
|
||||
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
|
||||
|
||||
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
|
||||
}
|
||||
|
||||
export interface CoreEnvironment { [name: string]: Function; }
|
||||
|
||||
export type StringMap = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
export type StringMapWithRename = {
|
||||
[key: string]: string | [string, string];
|
||||
};
|
||||
|
||||
export type Provider = any;
|
||||
|
||||
export enum R3ResolvedDependencyType {
|
||||
Token = 0,
|
||||
Attribute = 1,
|
||||
Injector = 2,
|
||||
}
|
||||
|
||||
export interface R3DependencyMetadataFacade {
|
||||
token: any;
|
||||
resolved: R3ResolvedDependencyType;
|
||||
host: boolean;
|
||||
optional: boolean;
|
||||
self: boolean;
|
||||
skipSelf: boolean;
|
||||
}
|
||||
|
||||
export interface R3PipeMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
pipeName: string;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
pure: boolean;
|
||||
}
|
||||
|
||||
export interface R3InjectableMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
ctorDeps: R3DependencyMetadataFacade[]|null;
|
||||
providedIn: any;
|
||||
useClass?: any;
|
||||
useFactory?: any;
|
||||
useExisting?: any;
|
||||
useValue?: any;
|
||||
userDeps?: R3DependencyMetadataFacade[];
|
||||
}
|
||||
|
||||
export interface R3NgModuleMetadataFacade {
|
||||
type: any;
|
||||
bootstrap: Function[];
|
||||
declarations: Function[];
|
||||
imports: Function[];
|
||||
exports: Function[];
|
||||
emitInline: boolean;
|
||||
}
|
||||
|
||||
export interface R3InjectorMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
providers: any;
|
||||
imports: any;
|
||||
}
|
||||
|
||||
export interface R3DirectiveMetadataFacade {
|
||||
name: string;
|
||||
type: any;
|
||||
typeArgumentCount: number;
|
||||
typeSourceSpan: null;
|
||||
deps: R3DependencyMetadataFacade[]|null;
|
||||
selector: string|null;
|
||||
queries: R3QueryMetadataFacade[];
|
||||
host: {[key: string]: string};
|
||||
propMetadata: {[key: string]: any[]};
|
||||
lifecycle: {usesOnChanges: boolean;};
|
||||
inputs: string[];
|
||||
outputs: string[];
|
||||
usesInheritance: boolean;
|
||||
exportAs: string|null;
|
||||
providers: Provider[]|null;
|
||||
}
|
||||
|
||||
export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
|
||||
template: string;
|
||||
preserveWhitespaces: boolean;
|
||||
animations: any[]|undefined;
|
||||
viewQueries: R3QueryMetadataFacade[];
|
||||
pipes: Map<string, any>;
|
||||
directives: Map<string, any>;
|
||||
styles: string[];
|
||||
encapsulation: ViewEncapsulation;
|
||||
viewProviders: Provider[]|null;
|
||||
}
|
||||
|
||||
export type ViewEncapsulation = number;
|
||||
|
||||
export interface R3QueryMetadataFacade {
|
||||
propertyName: string;
|
||||
first: boolean;
|
||||
predicate: any|string[];
|
||||
descendants: boolean;
|
||||
read: any|null;
|
||||
}
|
@ -6,22 +6,22 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ConstantPool, R3DirectiveMetadata, WrappedNodeExpr, compileComponentFromMetadata as compileR3Component, compileDirectiveFromMetadata as compileR3Directive, jitExpression, makeBindingParser, parseHostBindings, parseTemplate} from '@angular/compiler';
|
||||
|
||||
import {Component, Directive, HostBinding, HostListener, Input, Output} from '../../metadata/directives';
|
||||
import {Query} from '../../metadata/di';
|
||||
import {Component, Directive} from '../../metadata/directives';
|
||||
import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from '../../metadata/resource_loading';
|
||||
import {ViewEncapsulation} from '../../metadata/view';
|
||||
import {Type} from '../../type';
|
||||
import {stringify} from '../../util';
|
||||
import {EMPTY_ARRAY} from '../definition';
|
||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF} from '../fields';
|
||||
|
||||
import {R3DirectiveMetadataFacade, getCompilerFacade} from './compiler_facade';
|
||||
import {R3ComponentMetadataFacade, R3QueryMetadataFacade} from './compiler_facade_interface';
|
||||
import {angularCoreEnv} from './environment';
|
||||
import {patchComponentDefWithScope, transitiveScopesFor} from './module';
|
||||
import {getReflect, reflectDependencies} from './util';
|
||||
|
||||
type StringMap = {
|
||||
[key: string]: string
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile an Angular component according to its decorator metadata, and patch the resulting
|
||||
@ -38,6 +38,7 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
|
||||
maybeQueueResolutionOfComponentResources(metadata);
|
||||
Object.defineProperty(type, NG_COMPONENT_DEF, {
|
||||
get: () => {
|
||||
const compiler = getCompilerFacade();
|
||||
if (ngComponentDef === null) {
|
||||
if (componentNeedsResolution(metadata)) {
|
||||
const error = [`Component '${stringify(type)}' is not resolved:`];
|
||||
@ -50,42 +51,20 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
|
||||
error.push(`Did you run and wait for 'resolveComponentResources()'?`);
|
||||
throw new Error(error.join('\n'));
|
||||
}
|
||||
// The ConstantPool is a requirement of the JIT'er.
|
||||
const constantPool = new ConstantPool();
|
||||
|
||||
// Parse the template and check for errors.
|
||||
const template = parseTemplate(
|
||||
metadata.template !, `ng://${stringify(type)}/template.html`, {
|
||||
preserveWhitespaces: metadata.preserveWhitespaces || false,
|
||||
},
|
||||
'');
|
||||
if (template.errors !== undefined) {
|
||||
const errors = template.errors.map(err => err.toString()).join(', ');
|
||||
throw new Error(
|
||||
`Errors during JIT compilation of template for ${stringify(type)}: ${errors}`);
|
||||
}
|
||||
|
||||
const animations =
|
||||
metadata.animations !== null ? new WrappedNodeExpr(metadata.animations) : null;
|
||||
|
||||
// Compile the component metadata, including template, into an expression.
|
||||
// TODO(alxhub): implement inputs, outputs, queries, etc.
|
||||
const res = compileR3Component(
|
||||
{
|
||||
...directiveMetadata(type, metadata),
|
||||
template,
|
||||
directives: new Map(),
|
||||
pipes: new Map(),
|
||||
viewQueries: [],
|
||||
wrapDirectivesInClosure: false,
|
||||
styles: metadata.styles || [],
|
||||
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated, animations,
|
||||
},
|
||||
constantPool, makeBindingParser());
|
||||
const preStatements = [...constantPool.statements, ...res.statements];
|
||||
|
||||
ngComponentDef = jitExpression(
|
||||
res.expression, angularCoreEnv, `ng://${type.name}/ngComponentDef.js`, preStatements);
|
||||
const meta: R3ComponentMetadataFacade = {
|
||||
...directiveMetadata(type, metadata),
|
||||
template: metadata.template || '',
|
||||
preserveWhitespaces: metadata.preserveWhitespaces || false,
|
||||
styles: metadata.styles || EMPTY_ARRAY,
|
||||
animations: metadata.animations,
|
||||
viewQueries: extractQueriesMetadata(getReflect().propMetadata(type), isViewQuery),
|
||||
directives: new Map(),
|
||||
pipes: new Map(),
|
||||
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated,
|
||||
viewProviders: metadata.viewProviders || null,
|
||||
};
|
||||
ngComponentDef = compiler.compileComponent(
|
||||
angularCoreEnv, `ng://${stringify(type)}/template.html`, meta);
|
||||
|
||||
// If component compilation is async, then the @NgModule annotation which declares the
|
||||
// component may execute and set an ngSelectorScope property on the component type. This
|
||||
@ -120,12 +99,9 @@ export function compileDirective(type: Type<any>, directive: Directive): void {
|
||||
Object.defineProperty(type, NG_DIRECTIVE_DEF, {
|
||||
get: () => {
|
||||
if (ngDirectiveDef === null) {
|
||||
const constantPool = new ConstantPool();
|
||||
const sourceMapUrl = `ng://${type && type.name}/ngDirectiveDef.js`;
|
||||
const res = compileR3Directive(
|
||||
directiveMetadata(type, directive), constantPool, makeBindingParser());
|
||||
const preStatements = [...constantPool.statements, ...res.statements];
|
||||
ngDirectiveDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
||||
const facade = directiveMetadata(type, directive);
|
||||
ngDirectiveDef = getCompilerFacade().compileDirective(
|
||||
angularCoreEnv, `ng://${type && type.name}/ngDirectiveDef.js`, facade);
|
||||
}
|
||||
return ngDirectiveDef;
|
||||
},
|
||||
@ -142,97 +118,72 @@ export function extendsDirectlyFromObject(type: Type<any>): boolean {
|
||||
* Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
|
||||
* `Component`).
|
||||
*/
|
||||
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadata {
|
||||
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadataFacade {
|
||||
// Reflect inputs and outputs.
|
||||
const propMetadata = getReflect().propMetadata(type);
|
||||
|
||||
const host = extractHostBindings(metadata, propMetadata);
|
||||
|
||||
const inputsFromMetadata = parseInputOutputs(metadata.inputs || []);
|
||||
const outputsFromMetadata = parseInputOutputs(metadata.outputs || []);
|
||||
|
||||
const inputsFromType: StringMap = {};
|
||||
const outputsFromType: StringMap = {};
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isInput(ann)) {
|
||||
inputsFromType[field] = ann.bindingPropertyName || field;
|
||||
} else if (isOutput(ann)) {
|
||||
outputsFromType[field] = ann.bindingPropertyName || field;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: type.name,
|
||||
type: new WrappedNodeExpr(type),
|
||||
type: type,
|
||||
typeArgumentCount: 0,
|
||||
selector: metadata.selector !,
|
||||
deps: reflectDependencies(type), host,
|
||||
inputs: {...inputsFromMetadata, ...inputsFromType},
|
||||
outputs: {...outputsFromMetadata, ...outputsFromType},
|
||||
queries: [],
|
||||
deps: reflectDependencies(type),
|
||||
host: metadata.host || EMPTY_OBJ,
|
||||
propMetadata: propMetadata,
|
||||
inputs: metadata.inputs || EMPTY_ARRAY,
|
||||
outputs: metadata.outputs || EMPTY_ARRAY,
|
||||
queries: extractQueriesMetadata(propMetadata, isContentQuery),
|
||||
lifecycle: {
|
||||
usesOnChanges: type.prototype.ngOnChanges !== undefined,
|
||||
},
|
||||
typeSourceSpan: null !,
|
||||
usesInheritance: !extendsDirectlyFromObject(type),
|
||||
exportAs: metadata.exportAs || null,
|
||||
providers: metadata.providers || null,
|
||||
};
|
||||
}
|
||||
|
||||
function extractHostBindings(metadata: Directive, propMetadata: {[key: string]: any[]}): {
|
||||
attributes: StringMap,
|
||||
listeners: StringMap,
|
||||
properties: StringMap,
|
||||
} {
|
||||
// First parse the declarations from the metadata.
|
||||
const {attributes, listeners, properties, animations} = parseHostBindings(metadata.host || {});
|
||||
const EMPTY_OBJ = {};
|
||||
|
||||
if (Object.keys(animations).length > 0) {
|
||||
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
|
||||
}
|
||||
function convertToR3QueryPredicate(selector: any): any|string[] {
|
||||
return typeof selector === 'string' ? splitByComma(selector) : selector;
|
||||
}
|
||||
|
||||
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
|
||||
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadataFacade {
|
||||
return {
|
||||
propertyName: propertyName,
|
||||
predicate: convertToR3QueryPredicate(ann.selector),
|
||||
descendants: ann.descendants,
|
||||
first: ann.first,
|
||||
read: ann.read ? ann.read : null
|
||||
};
|
||||
}
|
||||
function extractQueriesMetadata(
|
||||
propMetadata: {[key: string]: any[]},
|
||||
isQueryAnn: (ann: any) => ann is Query): R3QueryMetadataFacade[] {
|
||||
const queriesMeta: R3QueryMetadataFacade[] = [];
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isHostBinding(ann)) {
|
||||
properties[ann.hostPropertyName || field] = field;
|
||||
} else if (isHostListener(ann)) {
|
||||
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
|
||||
if (isQueryAnn(ann)) {
|
||||
queriesMeta.push(convertToR3QueryMetadata(field, ann));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {attributes, listeners, properties};
|
||||
return queriesMeta;
|
||||
}
|
||||
|
||||
function isInput(value: any): value is Input {
|
||||
return value.ngMetadataName === 'Input';
|
||||
function isContentQuery(value: any): value is Query {
|
||||
const name = value.ngMetadataName;
|
||||
return name === 'ContentChild' || name === 'ContentChildren';
|
||||
}
|
||||
|
||||
function isOutput(value: any): value is Output {
|
||||
return value.ngMetadataName === 'Output';
|
||||
function isViewQuery(value: any): value is Query {
|
||||
const name = value.ngMetadataName;
|
||||
return name === 'ViewChild' || name === 'ViewChildren';
|
||||
}
|
||||
|
||||
function isHostBinding(value: any): value is HostBinding {
|
||||
return value.ngMetadataName === 'HostBinding';
|
||||
}
|
||||
|
||||
function isHostListener(value: any): value is HostListener {
|
||||
return value.ngMetadataName === 'HostListener';
|
||||
}
|
||||
|
||||
function parseInputOutputs(values: string[]): StringMap {
|
||||
return values.reduce(
|
||||
(map, value) => {
|
||||
const [field, property] = value.split(',').map(piece => piece.trim());
|
||||
map[field] = property || field;
|
||||
return map;
|
||||
},
|
||||
{} as StringMap);
|
||||
function splitByComma(value: string): string[] {
|
||||
return value.split(',').map(piece => piece.trim());
|
||||
}
|
||||
|
@ -6,14 +6,13 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Expression, LiteralExpr, R3DependencyMetadata, R3InjectableMetadata, WrappedNodeExpr, compileInjectable as compileR3Injectable, jitExpression} from '@angular/compiler';
|
||||
|
||||
import {Injectable} from '../../di/injectable';
|
||||
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
|
||||
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
|
||||
import {Type} from '../../type';
|
||||
import {getClosureSafeProperty} from '../../util/property';
|
||||
import {NG_INJECTABLE_DEF} from '../fields';
|
||||
|
||||
import {R3InjectableMetadataFacade, getCompilerFacade} from './compiler_facade';
|
||||
import {angularCoreEnv} from './environment';
|
||||
import {convertDependencies, reflectDependencies} from './util';
|
||||
|
||||
@ -31,84 +30,60 @@ export function compileInjectable(type: Type<any>, srcMeta?: Injectable): void {
|
||||
Object.defineProperty(type, NG_INJECTABLE_DEF, {
|
||||
get: () => {
|
||||
if (def === null) {
|
||||
// Check whether the injectable metadata includes a provider specification.
|
||||
const meta: Injectable = srcMeta || {providedIn: null};
|
||||
const hasAProvider = isUseClassProvider(meta) || isUseFactoryProvider(meta) ||
|
||||
isUseValueProvider(meta) || isUseExistingProvider(meta);
|
||||
|
||||
const ctorDeps = reflectDependencies(type);
|
||||
|
||||
let userDeps: R3DependencyMetadata[]|undefined = undefined;
|
||||
const compilerMeta: R3InjectableMetadataFacade = {
|
||||
name: type.name,
|
||||
type: type,
|
||||
providedIn: meta.providedIn,
|
||||
ctorDeps: reflectDependencies(type),
|
||||
userDeps: undefined
|
||||
};
|
||||
if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
|
||||
userDeps = convertDependencies(meta.deps);
|
||||
compilerMeta.userDeps = convertDependencies(meta.deps);
|
||||
}
|
||||
|
||||
// Decide which flavor of factory to generate, based on the provider specified.
|
||||
// Only one of the use* fields should be set.
|
||||
let useClass: Expression|undefined = undefined;
|
||||
let useFactory: Expression|undefined = undefined;
|
||||
let useValue: Expression|undefined = undefined;
|
||||
let useExisting: Expression|undefined = undefined;
|
||||
|
||||
if (!hasAProvider) {
|
||||
// In the case the user specifies a type provider, treat it as {provide: X, useClass: X}.
|
||||
// The deps will have been reflected above, causing the factory to create the class by
|
||||
// calling
|
||||
// its constructor with injected deps.
|
||||
useClass = new WrappedNodeExpr(type);
|
||||
compilerMeta.useClass = type;
|
||||
} else if (isUseClassProvider(meta)) {
|
||||
// The user explicitly specified useClass, and may or may not have provided deps.
|
||||
useClass = new WrappedNodeExpr(meta.useClass);
|
||||
compilerMeta.useClass = meta.useClass;
|
||||
} else if (isUseValueProvider(meta)) {
|
||||
// The user explicitly specified useValue.
|
||||
useValue = new WrappedNodeExpr(meta.useValue);
|
||||
compilerMeta.useValue = meta.useValue;
|
||||
} else if (isUseFactoryProvider(meta)) {
|
||||
// The user explicitly specified useFactory.
|
||||
useFactory = new WrappedNodeExpr(meta.useFactory);
|
||||
compilerMeta.useFactory = meta.useFactory;
|
||||
} else if (isUseExistingProvider(meta)) {
|
||||
// The user explicitly specified useExisting.
|
||||
useExisting = new WrappedNodeExpr(meta.useExisting);
|
||||
compilerMeta.useExisting = meta.useExisting;
|
||||
} else {
|
||||
// Can't happen - either hasAProvider will be false, or one of the providers will be set.
|
||||
throw new Error(`Unreachable state.`);
|
||||
}
|
||||
|
||||
const {expression, statements} = compileR3Injectable({
|
||||
name: type.name,
|
||||
type: new WrappedNodeExpr(type),
|
||||
providedIn: computeProvidedIn(meta.providedIn),
|
||||
useClass,
|
||||
useFactory,
|
||||
useValue,
|
||||
useExisting,
|
||||
ctorDeps,
|
||||
userDeps,
|
||||
});
|
||||
|
||||
def = jitExpression(
|
||||
expression, angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, statements);
|
||||
def = getCompilerFacade().compileInjectable(
|
||||
angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, compilerMeta);
|
||||
}
|
||||
return def;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function computeProvidedIn(providedIn: Type<any>| string | null | undefined): Expression {
|
||||
if (providedIn == null || typeof providedIn === 'string') {
|
||||
return new LiteralExpr(providedIn);
|
||||
} else {
|
||||
return new WrappedNodeExpr(providedIn);
|
||||
}
|
||||
}
|
||||
|
||||
type UseClassProvider = Injectable & ClassSansProvider & {deps?: any[]};
|
||||
|
||||
const USE_VALUE =
|
||||
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
|
||||
|
||||
function isUseClassProvider(meta: Injectable): meta is UseClassProvider {
|
||||
return (meta as UseClassProvider).useClass !== undefined;
|
||||
}
|
||||
|
||||
const USE_VALUE =
|
||||
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
|
||||
|
||||
function isUseValueProvider(meta: Injectable): meta is Injectable&ValueSansProvider {
|
||||
return USE_VALUE in meta;
|
||||
}
|
||||
|
@ -6,14 +6,13 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Expression, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, WrappedNodeExpr, compileInjector, compileNgModule as compileR3NgModule, jitExpression} from '@angular/compiler';
|
||||
|
||||
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
|
||||
import {Type} from '../../type';
|
||||
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
|
||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_INJECTOR_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
|
||||
import {ComponentDef} from '../interfaces/definition';
|
||||
|
||||
import {R3InjectorMetadataFacade, getCompilerFacade} from './compiler_facade';
|
||||
import {angularCoreEnv} from './environment';
|
||||
import {reflectDependencies} from './util';
|
||||
|
||||
@ -37,48 +36,39 @@ export function compileNgModuleDefs(moduleType: Type<any>, ngModule: NgModule):
|
||||
|
||||
let ngModuleDef: any = null;
|
||||
Object.defineProperty(moduleType, NG_MODULE_DEF, {
|
||||
configurable: true,
|
||||
get: () => {
|
||||
if (ngModuleDef === null) {
|
||||
const meta: R3NgModuleMetadata = {
|
||||
type: wrap(moduleType),
|
||||
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(wrapReference),
|
||||
declarations: declarations.map(wrapReference),
|
||||
imports: flatten(ngModule.imports || EMPTY_ARRAY)
|
||||
.map(expandModuleWithProviders)
|
||||
.map(wrapReference),
|
||||
exports: flatten(ngModule.exports || EMPTY_ARRAY)
|
||||
.map(expandModuleWithProviders)
|
||||
.map(wrapReference),
|
||||
emitInline: true,
|
||||
};
|
||||
const res = compileR3NgModule(meta);
|
||||
ngModuleDef = jitExpression(
|
||||
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, []);
|
||||
ngModuleDef = getCompilerFacade().compileNgModule(
|
||||
angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, {
|
||||
type: moduleType,
|
||||
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY),
|
||||
declarations: declarations,
|
||||
imports: flatten(ngModule.imports || EMPTY_ARRAY).map(expandModuleWithProviders),
|
||||
exports: flatten(ngModule.exports || EMPTY_ARRAY).map(expandModuleWithProviders),
|
||||
emitInline: true,
|
||||
});
|
||||
}
|
||||
return ngModuleDef;
|
||||
},
|
||||
// Make the property configurable in dev mode to allow overriding in tests
|
||||
configurable: !!ngDevMode,
|
||||
}
|
||||
});
|
||||
|
||||
let ngInjectorDef: any = null;
|
||||
Object.defineProperty(moduleType, NG_INJECTOR_DEF, {
|
||||
get: () => {
|
||||
if (ngInjectorDef === null) {
|
||||
const meta: R3InjectorMetadata = {
|
||||
const meta: R3InjectorMetadataFacade = {
|
||||
name: moduleType.name,
|
||||
type: wrap(moduleType),
|
||||
type: moduleType,
|
||||
deps: reflectDependencies(moduleType),
|
||||
providers: new WrappedNodeExpr(ngModule.providers || EMPTY_ARRAY),
|
||||
imports: new WrappedNodeExpr([
|
||||
providers: ngModule.providers || EMPTY_ARRAY,
|
||||
imports: [
|
||||
ngModule.imports || EMPTY_ARRAY,
|
||||
ngModule.exports || EMPTY_ARRAY,
|
||||
]),
|
||||
],
|
||||
};
|
||||
const res = compileInjector(meta);
|
||||
ngInjectorDef = jitExpression(
|
||||
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`,
|
||||
res.statements);
|
||||
ngInjectorDef = getCompilerFacade().compileInjector(
|
||||
angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`, meta);
|
||||
}
|
||||
return ngInjectorDef;
|
||||
},
|
||||
@ -235,15 +225,6 @@ function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): T
|
||||
return value;
|
||||
}
|
||||
|
||||
function wrap(value: Type<any>): Expression {
|
||||
return new WrappedNodeExpr(value);
|
||||
}
|
||||
|
||||
function wrapReference(value: Type<any>): R3Reference {
|
||||
const wrapped = wrap(value);
|
||||
return {value: wrapped, type: wrapped};
|
||||
}
|
||||
|
||||
function isModuleWithProviders(value: any): value is ModuleWithProviders<{}> {
|
||||
return (value as{ngModule?: any}).ngModule !== undefined;
|
||||
}
|
||||
|
@ -6,13 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {WrappedNodeExpr, compilePipeFromMetadata, jitExpression} from '@angular/compiler';
|
||||
|
||||
import {Pipe} from '../../metadata/directives';
|
||||
import {Type} from '../../type';
|
||||
import {NG_PIPE_DEF} from '../fields';
|
||||
import {stringify} from '../util';
|
||||
|
||||
import {getCompilerFacade} from './compiler_facade';
|
||||
import {angularCoreEnv} from './environment';
|
||||
import {reflectDependencies} from './util';
|
||||
|
||||
@ -21,18 +20,14 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
|
||||
Object.defineProperty(type, NG_PIPE_DEF, {
|
||||
get: () => {
|
||||
if (ngPipeDef === null) {
|
||||
const sourceMapUrl = `ng://${stringify(type)}/ngPipeDef.js`;
|
||||
|
||||
const name = type.name;
|
||||
const res = compilePipeFromMetadata({
|
||||
name,
|
||||
type: new WrappedNodeExpr(type),
|
||||
deps: reflectDependencies(type),
|
||||
pipeName: meta.name,
|
||||
pure: meta.pure !== undefined ? meta.pure : true,
|
||||
});
|
||||
|
||||
ngPipeDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
||||
ngPipeDef = getCompilerFacade().compilePipe(
|
||||
angularCoreEnv, `ng://${stringify(type)}/ngPipeDef.js`, {
|
||||
type: type,
|
||||
name: type.name,
|
||||
deps: reflectDependencies(type),
|
||||
pipeName: meta.name,
|
||||
pure: meta.pure !== undefined ? meta.pure : true
|
||||
});
|
||||
}
|
||||
return ngPipeDef;
|
||||
},
|
||||
|
@ -6,48 +6,41 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {LiteralExpr, R3DependencyMetadata, R3ResolvedDependencyType, WrappedNodeExpr} from '@angular/compiler';
|
||||
|
||||
import {Injector} from '../../di/injector';
|
||||
import {Host, Inject, Optional, Self, SkipSelf} from '../../di/metadata';
|
||||
import {ElementRef} from '../../linker/element_ref';
|
||||
import {TemplateRef} from '../../linker/template_ref';
|
||||
import {ViewContainerRef} from '../../linker/view_container_ref';
|
||||
import {Attribute} from '../../metadata/di';
|
||||
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
|
||||
import {Type} from '../../type';
|
||||
|
||||
import {CompilerFacade, R3DependencyMetadataFacade, getCompilerFacade} from './compiler_facade';
|
||||
|
||||
let _reflect: ReflectionCapabilities|null = null;
|
||||
|
||||
export function getReflect(): ReflectionCapabilities {
|
||||
return (_reflect = _reflect || new ReflectionCapabilities());
|
||||
}
|
||||
|
||||
export function reflectDependencies(type: Type<any>): R3DependencyMetadata[] {
|
||||
export function reflectDependencies(type: Type<any>): R3DependencyMetadataFacade[] {
|
||||
return convertDependencies(getReflect().parameters(type));
|
||||
}
|
||||
|
||||
export function convertDependencies(deps: any[]): R3DependencyMetadata[] {
|
||||
return deps.map(dep => reflectDependency(dep));
|
||||
export function convertDependencies(deps: any[]): R3DependencyMetadataFacade[] {
|
||||
const compiler = getCompilerFacade();
|
||||
return deps.map(dep => reflectDependency(compiler, dep));
|
||||
}
|
||||
|
||||
function reflectDependency(dep: any | any[]): R3DependencyMetadata {
|
||||
const meta: R3DependencyMetadata = {
|
||||
token: new LiteralExpr(null),
|
||||
function reflectDependency(compiler: CompilerFacade, dep: any | any[]): R3DependencyMetadataFacade {
|
||||
const meta: R3DependencyMetadataFacade = {
|
||||
token: null,
|
||||
host: false,
|
||||
optional: false,
|
||||
resolved: R3ResolvedDependencyType.Token,
|
||||
resolved: compiler.R3ResolvedDependencyType.Token,
|
||||
self: false,
|
||||
skipSelf: false,
|
||||
};
|
||||
|
||||
function setTokenAndResolvedType(token: any): void {
|
||||
if (token === Injector) {
|
||||
meta.resolved = R3ResolvedDependencyType.Injector;
|
||||
} else {
|
||||
meta.resolved = R3ResolvedDependencyType.Token;
|
||||
}
|
||||
meta.token = new WrappedNodeExpr(token);
|
||||
meta.resolved = compiler.R3ResolvedDependencyType.Token;
|
||||
meta.token = token;
|
||||
}
|
||||
|
||||
if (Array.isArray(dep)) {
|
||||
@ -65,13 +58,13 @@ function reflectDependency(dep: any | any[]): R3DependencyMetadata {
|
||||
} else if (param instanceof Host || param.__proto__.ngMetadataName === 'Host') {
|
||||
meta.host = true;
|
||||
} else if (param instanceof Inject) {
|
||||
meta.token = new WrappedNodeExpr(param.token);
|
||||
meta.token = param.token;
|
||||
} else if (param instanceof Attribute) {
|
||||
if (param.attributeName === undefined) {
|
||||
throw new Error(`Attribute name must be defined.`);
|
||||
}
|
||||
meta.token = new LiteralExpr(param.attributeName);
|
||||
meta.resolved = R3ResolvedDependencyType.Attribute;
|
||||
meta.token = param.attributeName;
|
||||
meta.resolved = compiler.R3ResolvedDependencyType.Attribute;
|
||||
} else {
|
||||
setTokenAndResolvedType(param);
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ load("//tools/http-server:http_server.bzl", "http_server")
|
||||
ng_module(
|
||||
name = "animation_world",
|
||||
srcs = ["index.ts"],
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
type_check = False, # see #26462
|
||||
deps = [
|
||||
"//packages/common",
|
||||
@ -25,7 +28,10 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/animation_world/index.js",
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":animation_world",
|
||||
"//packages/core",
|
||||
@ -38,6 +44,7 @@ js_expected_symbol_test(
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
@ -50,4 +57,8 @@ http_server(
|
||||
":bundle.min.js",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
@ -57,7 +57,7 @@
|
||||
"name": "EMPTY_ARR"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
"name": "EMPTY_ARRAY"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_OBJ"
|
||||
@ -213,7 +213,7 @@
|
||||
"name": "ViewContainerRef"
|
||||
},
|
||||
{
|
||||
"name": "ViewEncapsulation$1"
|
||||
"name": "ViewEncapsulation"
|
||||
},
|
||||
{
|
||||
"name": "ViewRef"
|
||||
@ -402,7 +402,7 @@
|
||||
"name": "createNodeAtIndex"
|
||||
},
|
||||
{
|
||||
"name": "createOutput$1"
|
||||
"name": "createOutput"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponent"
|
||||
@ -1032,10 +1032,10 @@
|
||||
"name": "storeCleanupWithContext"
|
||||
},
|
||||
{
|
||||
"name": "stringify$1"
|
||||
"name": "stringify"
|
||||
},
|
||||
{
|
||||
"name": "stringify$2"
|
||||
"name": "stringify$1"
|
||||
},
|
||||
{
|
||||
"name": "swapMultiContextEntries"
|
||||
|
@ -7,7 +7,10 @@ load("//tools/http-server:http_server.bzl", "http_server")
|
||||
ng_module(
|
||||
name = "hello_world",
|
||||
srcs = ["index.ts"],
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
@ -22,7 +25,10 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/hello_world/index.js",
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":hello_world",
|
||||
"//packages/core",
|
||||
@ -33,8 +39,13 @@ ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(["*_spec.ts"]),
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/core/testing",
|
||||
"//packages/private/testing",
|
||||
],
|
||||
@ -50,6 +61,7 @@ jasmine_node_test(
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@ -60,6 +72,7 @@ js_expected_symbol_test(
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
@ -70,4 +83,8 @@ http_server(
|
||||
":bundle.min.js",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
@ -27,7 +27,7 @@
|
||||
"name": "EMPTY$1"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
"name": "EMPTY_ARRAY"
|
||||
},
|
||||
{
|
||||
"name": "EmptyErrorImpl"
|
||||
@ -114,7 +114,7 @@
|
||||
"name": "VIEWS"
|
||||
},
|
||||
{
|
||||
"name": "ViewEncapsulation$1"
|
||||
"name": "ViewEncapsulation"
|
||||
},
|
||||
{
|
||||
"name": "_getViewData"
|
||||
@ -360,7 +360,7 @@
|
||||
"name": "setUpBloom"
|
||||
},
|
||||
{
|
||||
"name": "stringify$2"
|
||||
"name": "stringify$1"
|
||||
},
|
||||
{
|
||||
"name": "syncViewWithBlueprint"
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import '@angular/compiler';
|
||||
import {withBody} from '@angular/private/testing';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
@ -6,6 +6,7 @@ load("//tools/http-server:http_server.bzl", "http_server")
|
||||
ivy_ng_module(
|
||||
name = "hello_world_i18n",
|
||||
srcs = ["index.ts"],
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
@ -20,6 +21,7 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/hello_world_i18n/index.js",
|
||||
tags = ["ivy-only"],
|
||||
deps = [
|
||||
":hello_world_i18n",
|
||||
"//packages/core",
|
||||
@ -33,4 +35,5 @@ http_server(
|
||||
":bundle.min.js",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = ["ivy-only"],
|
||||
)
|
||||
|
@ -7,6 +7,10 @@ load("//tools/http-server:http_server.bzl", "http_server")
|
||||
ng_module(
|
||||
name = "hello_world",
|
||||
srcs = ["index.ts"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
"//packages/platform-browser-dynamic",
|
||||
@ -22,6 +26,10 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/hello_world_r2/index.js",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":hello_world",
|
||||
"//packages/core",
|
||||
@ -33,8 +41,13 @@ ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(["*_spec.ts"]),
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/core/testing",
|
||||
"//packages/private/testing",
|
||||
],
|
||||
@ -48,6 +61,10 @@ jasmine_node_test(
|
||||
":bundle.min.js.br",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
|
||||
@ -55,6 +72,10 @@ js_expected_symbol_test(
|
||||
name = "symbol_test",
|
||||
src = ":bundle.min_debug.js",
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
http_server(
|
||||
@ -64,4 +85,8 @@ http_server(
|
||||
":bundle.min.js",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import '@angular/compiler';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
|
@ -9,6 +9,10 @@ ts_library(
|
||||
"index.ts",
|
||||
"usage.ts",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
@ -23,6 +27,10 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/injection/index.js",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":injection",
|
||||
"//packages/core",
|
||||
@ -33,9 +41,14 @@ ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(["*_spec.ts"]),
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":injection",
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/core/testing",
|
||||
"//packages/private/testing",
|
||||
],
|
||||
@ -43,6 +56,10 @@ ts_library(
|
||||
|
||||
jasmine_node_test(
|
||||
name = "test",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
|
||||
@ -50,4 +67,8 @@ js_expected_symbol_test(
|
||||
name = "symbol_test",
|
||||
src = ":bundle.min_debug.js",
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
@ -6,7 +6,7 @@
|
||||
"name": "CIRCULAR$2"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$2"
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
},
|
||||
{
|
||||
"name": "EmptyErrorImpl"
|
||||
|
@ -6,15 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import '@angular/compiler';
|
||||
import {INJECTOR, ScopedService} from './usage';
|
||||
|
||||
const UTF8 = {
|
||||
encoding: 'utf-8'
|
||||
};
|
||||
const PACKAGE = 'angular/packages/core/test/bundling/hello_world';
|
||||
|
||||
describe('functional test for injection system bundling', () => {
|
||||
it('should be able to inject the scoped service',
|
||||
|
@ -8,7 +8,10 @@ load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
ng_module(
|
||||
name = "todo",
|
||||
srcs = ["index.ts"],
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
@ -25,13 +28,15 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/todo/index.js",
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":todo",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"//packages/core/test/bundling/util:reflect_metadata",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
@ -39,8 +44,13 @@ ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(["*_spec.ts"]),
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/private/testing",
|
||||
@ -57,6 +67,7 @@ jasmine_node_test(
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@ -67,6 +78,7 @@ js_expected_symbol_test(
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
@ -79,6 +91,10 @@ genrule(
|
||||
"tslib.js",
|
||||
],
|
||||
cmd = "cp $< $@",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
ts_devserver(
|
||||
@ -91,6 +107,10 @@ ts_devserver(
|
||||
"todo.css",
|
||||
"base.css",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":todo"],
|
||||
)
|
||||
|
||||
@ -103,4 +123,8 @@ http_server(
|
||||
":bundle.min.js.br",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
@ -48,7 +48,7 @@
|
||||
"name": "EMPTY$1"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
"name": "EMPTY_ARRAY"
|
||||
},
|
||||
{
|
||||
"name": "ElementRef"
|
||||
@ -228,7 +228,7 @@
|
||||
"name": "ViewContainerRef"
|
||||
},
|
||||
{
|
||||
"name": "ViewEncapsulation$1"
|
||||
"name": "ViewEncapsulation"
|
||||
},
|
||||
{
|
||||
"name": "ViewRef"
|
||||
@ -459,7 +459,7 @@
|
||||
"name": "createNodeAtIndex"
|
||||
},
|
||||
{
|
||||
"name": "createOutput$1"
|
||||
"name": "createOutput"
|
||||
},
|
||||
{
|
||||
"name": "createRootComponent"
|
||||
@ -1050,10 +1050,10 @@
|
||||
"name": "storeCleanupWithContext"
|
||||
},
|
||||
{
|
||||
"name": "stringify$1"
|
||||
"name": "stringify"
|
||||
},
|
||||
{
|
||||
"name": "stringify$2"
|
||||
"name": "stringify$1"
|
||||
},
|
||||
{
|
||||
"name": "syncViewWithBlueprint"
|
||||
|
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import '@angular/compiler';
|
||||
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||
import {withBody} from '@angular/private/testing';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const UTF8 = {
|
||||
|
@ -8,7 +8,10 @@ load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
ng_module(
|
||||
name = "todo",
|
||||
srcs = ["index.ts"],
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
@ -27,7 +30,10 @@ ng_rollup_bundle(
|
||||
# has an "external" directory for external dependencies.
|
||||
# This should probably start with "angular/" and let the rule deal with it.
|
||||
entry_point = "packages/core/test/bundling/todo_r2/index.js",
|
||||
tags = ["ivy-only"],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
":todo",
|
||||
"//packages/common",
|
||||
@ -35,7 +41,6 @@ ng_rollup_bundle(
|
||||
"//packages/core/test/bundling/util:reflect_metadata",
|
||||
"//packages/platform-browser",
|
||||
"//packages/platform-browser-dynamic",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
)
|
||||
|
||||
@ -43,8 +48,13 @@ ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(["*_spec.ts"]),
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
@ -63,6 +73,7 @@ jasmine_node_test(
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@ -73,6 +84,7 @@ js_expected_symbol_test(
|
||||
golden = ":bundle.golden_symbols.json",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
@ -85,6 +97,10 @@ genrule(
|
||||
"tslib.js",
|
||||
],
|
||||
cmd = "cp $< $@",
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
||||
ts_devserver(
|
||||
@ -97,6 +113,10 @@ ts_devserver(
|
||||
"todo.css",
|
||||
"base.css",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
deps = [":todo"],
|
||||
)
|
||||
|
||||
@ -109,4 +129,8 @@ http_server(
|
||||
":bundle.min.js.br",
|
||||
":bundle.min_debug.js",
|
||||
],
|
||||
tags = [
|
||||
"ivy-only",
|
||||
"no-ivy-jit",
|
||||
],
|
||||
)
|
||||
|
@ -102,13 +102,13 @@
|
||||
"name": "COMPONENT_REGEX"
|
||||
},
|
||||
{
|
||||
"name": "COMPONENT_VARIABLE$1"
|
||||
"name": "COMPONENT_VARIABLE"
|
||||
},
|
||||
{
|
||||
"name": "CONTAINER_INDEX"
|
||||
},
|
||||
{
|
||||
"name": "CONTENT_ATTR$1"
|
||||
"name": "CONTENT_ATTR"
|
||||
},
|
||||
{
|
||||
"name": "CONTEXT"
|
||||
@ -258,10 +258,10 @@
|
||||
"name": "EMPTY$1"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
"name": "EMPTY_ARRAY"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY$2"
|
||||
"name": "EMPTY_ARRAY$1"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_PAYLOAD"
|
||||
@ -333,7 +333,7 @@
|
||||
"name": "HOST"
|
||||
},
|
||||
{
|
||||
"name": "HOST_ATTR$1"
|
||||
"name": "HOST_ATTR"
|
||||
},
|
||||
{
|
||||
"name": "HOST_NODE"
|
||||
@ -786,7 +786,7 @@
|
||||
"name": "SanitizingHtmlSerializer"
|
||||
},
|
||||
{
|
||||
"name": "SecurityContext$1"
|
||||
"name": "SecurityContext"
|
||||
},
|
||||
{
|
||||
"name": "Self"
|
||||
@ -900,7 +900,7 @@
|
||||
"name": "URL_RE"
|
||||
},
|
||||
{
|
||||
"name": "USE_VALUE$1"
|
||||
"name": "USE_VALUE"
|
||||
},
|
||||
{
|
||||
"name": "UnsubscriptionError"
|
||||
@ -924,13 +924,13 @@
|
||||
"name": "VOID_ELEMENTS"
|
||||
},
|
||||
{
|
||||
"name": "Version$1"
|
||||
"name": "Version"
|
||||
},
|
||||
{
|
||||
"name": "ViewContainerRef"
|
||||
},
|
||||
{
|
||||
"name": "ViewEncapsulation$1"
|
||||
"name": "ViewEncapsulation"
|
||||
},
|
||||
{
|
||||
"name": "ViewRef"
|
||||
@ -1341,7 +1341,7 @@
|
||||
"name": "createNodeAtIndex"
|
||||
},
|
||||
{
|
||||
"name": "createOutput$1"
|
||||
"name": "createOutput"
|
||||
},
|
||||
{
|
||||
"name": "createPlatform"
|
||||
@ -2046,10 +2046,10 @@
|
||||
"name": "isProceduralRenderer"
|
||||
},
|
||||
{
|
||||
"name": "isPromise$1"
|
||||
"name": "isPromise"
|
||||
},
|
||||
{
|
||||
"name": "isPromise$2"
|
||||
"name": "isPromise$1"
|
||||
},
|
||||
{
|
||||
"name": "isScheduler"
|
||||
@ -2187,7 +2187,7 @@
|
||||
"name": "parseCookieValue"
|
||||
},
|
||||
{
|
||||
"name": "parseIntAutoRadix$1"
|
||||
"name": "parseIntAutoRadix"
|
||||
},
|
||||
{
|
||||
"name": "parseNumber"
|
||||
@ -2304,7 +2304,7 @@
|
||||
"name": "resolveDirective"
|
||||
},
|
||||
{
|
||||
"name": "resolveForwardRef$1"
|
||||
"name": "resolveForwardRef"
|
||||
},
|
||||
{
|
||||
"name": "resolveProvider"
|
||||
@ -2433,10 +2433,10 @@
|
||||
"name": "strToNumber"
|
||||
},
|
||||
{
|
||||
"name": "stringify$1"
|
||||
"name": "stringify"
|
||||
},
|
||||
{
|
||||
"name": "stringify$2"
|
||||
"name": "stringify$1"
|
||||
},
|
||||
{
|
||||
"name": "subscribeTo"
|
||||
|
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import '@angular/compiler';
|
||||
import {ɵwhenRendered as whenRendered} from '@angular/core';
|
||||
import {withBody} from '@angular/private/testing';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const UTF8 = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user