Merge remote-tracking branch 'en/master' into aio
# Conflicts: # aio/content/guide/releases.md # aio/content/guide/route-animations.md # aio/content/guide/template-syntax.md # aio/content/guide/testing.md # aio/content/guide/updating.md # aio/yarn.lock
This commit is contained in:
commit
afb6119ae2
@ -120,25 +120,11 @@ commands:
|
||||
- attach_workspace:
|
||||
at: *workspace_location
|
||||
|
||||
# Overwrite the yarn installed in the docker container with our own version.
|
||||
overwrite_yarn:
|
||||
description: Overwrite yarn with our own version
|
||||
steps:
|
||||
- run:
|
||||
name: Overwrite yarn
|
||||
command: |
|
||||
localYarnPath=`node ./.circleci/get-vendored-yarn-path.js`
|
||||
sudo chmod a+x $localYarnPath
|
||||
sudo ln -fs $localYarnPath /usr/local/bin/yarn
|
||||
- run: node --version
|
||||
- run: yarn --version
|
||||
|
||||
# Initializes the CI environment by setting up common environment variables.
|
||||
init_environment:
|
||||
description: Initializing environment (setting up variables, overwriting Yarn)
|
||||
description: Initializing environment (setting up variables)
|
||||
steps:
|
||||
- run: ./.circleci/env.sh
|
||||
- overwrite_yarn
|
||||
- run:
|
||||
# Configure git as the CircleCI `checkout` command does.
|
||||
# This is needed because we only checkout on the setup job.
|
||||
@ -150,6 +136,27 @@ commands:
|
||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||
git config --global gc.auto 0 || true
|
||||
|
||||
init_saucelabs_environment:
|
||||
description: Sets up a domain that resolves to the local host.
|
||||
steps:
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: |
|
||||
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
||||
# the tunnel. We do this because devices are sometimes not able to properly resolve
|
||||
# `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
|
||||
# resolve to anything on SauceLabs VMs ensures that such requests are always resolved
|
||||
# through the tunnel, and resolve to the actual tunnel host machine (i.e. the CircleCI VM).
|
||||
# More context can be found in: https://github.com/angular/angular/pull/35171.
|
||||
setPublicVar SAUCE_LOCALHOST_ALIAS_DOMAIN "angular-ci.local"
|
||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- run:
|
||||
# Sets up a local domain in the machine's host file that resolves to the local
|
||||
# host. This domain is helpful in Saucelabs tests where devices are not able to
|
||||
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
|
||||
name: Setting up alias domain for local host.
|
||||
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
|
||||
|
||||
# Normally this would be an individual job instead of a command.
|
||||
# But startup and setup time for each invidual windows job are high enough to discourage
|
||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||
@ -160,10 +167,6 @@ commands:
|
||||
- custom_attach_workspace
|
||||
# Install Bazel pre-requisites that aren't in the preconfigured CircleCI Windows VM.
|
||||
- run: ./.circleci/windows-env.ps1
|
||||
- run:
|
||||
# Overwrite the yarn installed in the docker container with our own version.
|
||||
name: Overwrite yarn with our own version
|
||||
command: ./.circleci/windows-yarn-setup.ps1
|
||||
- run: node --version
|
||||
- run: yarn --version
|
||||
- restore_cache:
|
||||
@ -313,9 +316,7 @@ jobs:
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Run Bazel tests on Saucelabs
|
||||
# See /tools/saucelabs/README.md for more info
|
||||
@ -337,9 +338,7 @@ jobs:
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Run Bazel tests on Saucelabs
|
||||
# See /tools/saucelabs/README.md for more info
|
||||
@ -621,8 +620,6 @@ jobs:
|
||||
command: |
|
||||
git fetch origin $CI_STABLE_BRANCH
|
||||
git checkout --force origin/$CI_STABLE_BRANCH -- aio/ .yarn/ .yarnrc
|
||||
# Overwrite yarn again to use the version from the checked out branch.
|
||||
- overwrite_yarn
|
||||
# Ignore yarn's engines check, because we checked out `aio/package.json` from the stable
|
||||
# branch and there could be a node version skew, which is acceptable in this monitoring job.
|
||||
- run: yarn config set ignore-engines true
|
||||
@ -659,11 +656,7 @@ jobs:
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run:
|
||||
name: Preparing environment for running tests on Saucelabs.
|
||||
command: |
|
||||
setPublicVar KARMA_JS_BROWSERS $(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||
- init_saucelabs_environment
|
||||
- run:
|
||||
name: Starting Saucelabs tunnel service
|
||||
command: ./tools/saucelabs/sauce-service.sh run
|
||||
@ -675,7 +668,11 @@ jobs:
|
||||
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
||||
name: Waiting for Saucelabs tunnel to connect
|
||||
command: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=${KARMA_JS_BROWSERS}
|
||||
- run:
|
||||
name: Running tests on Saucelabs.
|
||||
command: |
|
||||
browsers=$(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||
yarn karma start ./karma-js.conf.js --single-run --browsers=${browsers}
|
||||
- run:
|
||||
name: Stop Saucelabs tunnel service
|
||||
command: ./tools/saucelabs/sauce-service.sh stop
|
||||
|
@ -65,6 +65,7 @@ setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CI
|
||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define environment variables for the `angular/components` repo unit tests job.
|
||||
####################################################################################################
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* **Usage:**
|
||||
* ```
|
||||
* node get-vendored-yarn-path
|
||||
* ```
|
||||
*
|
||||
* Returns the path to the vendored `yarn.js` script, so that it can be used for setting up yarn
|
||||
* aliases/symlinks and use the local, vendored yarn script instead of a globally installed one.
|
||||
*
|
||||
* **Context:**
|
||||
* We keep a version of yarn in the repo, at `third_party/github.com/yarnpkg/`. All CI jobs should
|
||||
* use that version for consistency (and easier updates). The path to the actual `yarn.js` script,
|
||||
* however, changes depending on the version (e.g. `third_party/github.com/yarnpkg/v1.21.1/...`).
|
||||
*
|
||||
* This script infers the correct path, so that we don't have to update the path in several places,
|
||||
* when we update the version of yarn in `third_party/github.com/yarnpkg/`.
|
||||
*/
|
||||
|
||||
const {readdirSync} = require('fs');
|
||||
const {normalize} = require('path');
|
||||
|
||||
const yarnDownloadDir = `${__dirname}/../third_party/github.com/yarnpkg/yarn/releases/download`;
|
||||
const yarnVersionSubdirs = readdirSync(yarnDownloadDir);
|
||||
|
||||
// Based on our current process, there should be exactly one sub-directory inside
|
||||
// `vendoredYarnDownloadDir` at all times. Throw, if that is not the case.
|
||||
if (yarnVersionSubdirs.length !== 1) {
|
||||
throw new Error(
|
||||
`Expected exactly 1 yarn version in '${yarnDownloadDir}', but found ` +
|
||||
`${yarnVersionSubdirs.length}: ${yarnVersionSubdirs.join(', ')}`);
|
||||
}
|
||||
|
||||
console.log(normalize(`${yarnDownloadDir}/${yarnVersionSubdirs[0]}/bin/yarn.js`));
|
@ -1,14 +0,0 @@
|
||||
# Use our local, vendored yarn in the global `yarn` command.
|
||||
$globalYarnDir = "$HOME\AppData\Roaming\yarn"
|
||||
$localYarnPath = & ${Env:ProgramFiles}\nodejs\node.exe ".\.circleci\get-vendored-yarn-path.js"
|
||||
|
||||
# Create a directory to put the yarn PowerShell script.
|
||||
New-Item -Path "$globalYarnDir" -ItemType "directory" >$null
|
||||
|
||||
# Create the yarn PowerShell script (using the inferred path to the local yarn script).
|
||||
Get-Content -Path ".\.circleci\windows-yarn.ps1.template" |
|
||||
%{$_ -replace "{{ LOCAL_YARN_PATH_PLACEHOLDER }}", "$localYarnPath"} |
|
||||
Add-Content -Path "$globalYarnDir\yarn.ps1"
|
||||
|
||||
# Add the directory containing the yarn PowerShell script to `PATH`.
|
||||
Add-Content -Path $profile -Value ('$Env:path = "{0};" + $Env:path' -f $globalYarnDir)
|
@ -1,15 +0,0 @@
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
& "$basedir/node$exe" "{{ LOCAL_YARN_PATH_PLACEHOLDER }}" $args
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
& "node$exe" "{{ LOCAL_YARN_PATH_PLACEHOLDER }}" $args
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
@ -978,26 +978,6 @@ groups:
|
||||
- ~framework-global-approvers
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Material CI
|
||||
# =========================================================
|
||||
material-ci:
|
||||
conditions:
|
||||
- >
|
||||
contains_any_globs(files, [
|
||||
'tools/components-repo-ci/**'
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- alxhub
|
||||
- AndrewKushnir
|
||||
- kara
|
||||
- mhevery
|
||||
- pkozlowski-opensource
|
||||
teams:
|
||||
- ~framework-global-approvers
|
||||
|
||||
|
||||
# =========================================================
|
||||
# Public API
|
||||
# =========================================================
|
||||
|
1916
CHANGELOG.md
1916
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -40,9 +40,6 @@ node_repositories(
|
||||
},
|
||||
node_version = "12.14.1",
|
||||
package_json = ["//:package.json"],
|
||||
# Label needs to explicitly specify the current workspace name because otherwise Bazel does
|
||||
# not provide all needed data (like "workspace_root") to the repository context.
|
||||
vendored_yarn = "@angular//:third_party/github.com/yarnpkg/yarn/releases/download/v1.21.1",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
|
@ -25,23 +25,12 @@ describe('Attribute binding example', function () {
|
||||
});
|
||||
|
||||
it('should display a blue div with a red border', function () {
|
||||
expect(element.all(by.css('div')).get(4).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
||||
expect(element.all(by.css('div')).get(1).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
||||
});
|
||||
|
||||
it('should display a div with replaced classes', function () {
|
||||
expect(element.all(by.css('div')).get(5).getAttribute('class')).toEqual('new-class');
|
||||
});
|
||||
|
||||
it('should display four buttons', function() {
|
||||
let redButton = element.all(by.css('button')).get(1);
|
||||
let saveButton = element.all(by.css('button')).get(2);
|
||||
let bigButton = element.all(by.css('button')).get(3);
|
||||
let smallButton = element.all(by.css('button')).get(4);
|
||||
|
||||
expect(redButton.getCssValue('color')).toEqual('rgba(255, 0, 0, 1)');
|
||||
expect(saveButton.getCssValue('background-color')).toEqual('rgba(0, 255, 255, 1)');
|
||||
expect(bigButton.getText()).toBe('Big');
|
||||
expect(smallButton.getText()).toBe('Small');
|
||||
it('should display a div with many classes', function () {
|
||||
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('special');
|
||||
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('clearance');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -27,39 +27,41 @@
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Class binding</h2>
|
||||
<h2>Styling precedence</h2>
|
||||
|
||||
<!-- #docregion is-special -->
|
||||
<h3>toggle the "special" class on/off with a property:</h3>
|
||||
<div [class.special]="isSpecial">The class binding is special.</div>
|
||||
<!-- #docregion basic-specificity -->
|
||||
<h3>Basic specificity</h3>
|
||||
|
||||
<h3>binding to class.special overrides the class attribute:</h3>
|
||||
<div class="special" [class.special]="!isSpecial">This one is not so special.</div>
|
||||
<!-- The `class.special` binding will override any value for the `special` class in `classExpr`. -->
|
||||
<div [class.special]="isSpecial" [class]="classExpr">Some text.</div>
|
||||
|
||||
<h3>Using the bind- syntax:</h3>
|
||||
<div bind-class.special="isSpecial">This class binding is special too.</div>
|
||||
<!-- #enddocregion is-special -->
|
||||
<!-- The `style.color` binding will override any value for the `color` property in `styleExpr`. -->
|
||||
<div [style.color]="color" [style]="styleExpr">Some text.</div>
|
||||
<!-- #enddocregion basic-specificity -->
|
||||
|
||||
<!-- #docregion add-class -->
|
||||
<h3>Add a class:</h3>
|
||||
<div class="item clearance special" [class.item-clearance]="itemClearance">Add another class</div>
|
||||
<!-- #enddocregion add-class -->
|
||||
<!-- #docregion source-specificity -->
|
||||
<h3>Source specificity</h3>
|
||||
|
||||
<!-- #docregion class-override -->
|
||||
<h3>Overwrite all existing classes with a new class:</h3>
|
||||
<div class="item clearance special" [attr.class]="resetClasses">Reset all classes at once</div>
|
||||
<!-- #enddocregion class-override -->
|
||||
<!-- The `class.special` template binding will override any host binding to the `special` class set by `dirWithClassBinding` or `comp-with-host-binding`.-->
|
||||
<comp-with-host-binding [class.special]="isSpecial" dirWithClassBinding>Some text.</comp-with-host-binding>
|
||||
|
||||
<hr />
|
||||
<!-- The `style.color` template binding will override any host binding to the `color` property set by `dirWithStyleBinding` or `comp-with-host-binding`. -->
|
||||
<comp-with-host-binding [style.color]="color" dirWithStyleBinding>Some text.</comp-with-host-binding>
|
||||
<!-- #enddocregion source-specificity -->
|
||||
|
||||
<h2>Style binding</h2>
|
||||
<!-- #docregion dynamic-priority -->
|
||||
<h3>Dynamic vs static</h3>
|
||||
|
||||
<!-- If `classExpr` has a value for the `special` class, this value will override the `class="special"` below -->
|
||||
<div class="special" [class]="classExpr">Some text.</div>
|
||||
|
||||
<!-- If `styleExpr` has a value for the `color` property, this value will override the `style="color: blue"` below -->
|
||||
<div style="color: blue" [style]="styleExpr">Some text.</div>
|
||||
|
||||
<!-- #enddocregion dynamic-priority -->
|
||||
|
||||
<!-- #docregion style-delegation -->
|
||||
<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>
|
||||
<!-- #enddocregion style-delegation -->
|
||||
|
||||
<!-- #docregion style-binding-->
|
||||
<button [style.color]="isSpecial ? 'red': 'green'">Red</button>
|
||||
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>
|
||||
<!-- #enddocregion style-binding -->
|
||||
|
||||
<!-- #docregion style-binding-condition-->
|
||||
<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button>
|
||||
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
|
||||
<!-- #enddocregion style-binding-condition-->
|
||||
|
@ -8,8 +8,8 @@ import { Component } from '@angular/core';
|
||||
export class AppComponent {
|
||||
actionName = 'Go for it';
|
||||
isSpecial = true;
|
||||
itemClearance = true;
|
||||
resetClasses = 'new-class';
|
||||
canSave = true;
|
||||
|
||||
classExpr = 'special clearance';
|
||||
styleExpr = 'color: red';
|
||||
color = 'blue';
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ import { NgModule } from '@angular/core';
|
||||
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { CompWithHostBindingComponent } from './comp-with-host-binding.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
AppComponent,
|
||||
CompWithHostBindingComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule
|
||||
|
@ -0,0 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'comp-with-host-binding',
|
||||
template: 'I am a component!',
|
||||
host: {
|
||||
'[class.special]': 'isSpecial',
|
||||
'[style.color]': 'color',
|
||||
'[style.width]': 'width'
|
||||
}
|
||||
})
|
||||
export class CompWithHostBindingComponent {
|
||||
isSpecial = false;
|
||||
color = 'green';
|
||||
width = '200px';
|
||||
}
|
@ -17,6 +17,23 @@ If you're still seeing the errors, they are not specific to Ivy. In this case, y
|
||||
|
||||
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
|
||||
|
||||
{@a payload-size-debugging}
|
||||
### Payload size debugging
|
||||
|
||||
If you notice that the size of your application's main bundle has increased with Ivy, you may want to check the following:
|
||||
|
||||
1. Verify that the components and `NgModules` that you want to be lazy loaded are only imported in lazy modules.
|
||||
Anything that you import outside lazy modules can end up in the main bundle.
|
||||
See more details in the original issue [here](https://github.com/angular/angular-cli/issues/16146#issuecomment-557559287).
|
||||
|
||||
1. Check that imported libraries have been marked side-effect-free.
|
||||
If your app imports from shared libraries that are meant to be free from side effects, add "sideEffects": false to their `package.json`.
|
||||
This will ensure that the libraries will be properly tree-shaken if they are imported but not directly referenced.
|
||||
See more details in the original issue [here](https://github.com/angular/angular-cli/issues/16799#issuecomment-580912090).
|
||||
|
||||
1. Projects not using Angular CLI will see a significant size regression unless they update their minifier settings and set compile-time constants `ngDevMode`, `ngI18nClosureMode` and `ngJitMode` to `false` (for Terser, please set these to `false` via [`global_defs` config option](https://terser.org/docs/api-reference.html#conditional-compilation)).
|
||||
Please note that these constants are not meant to be used by 3rd party library or application code as they are not part of our public api surface and might change in the future.
|
||||
|
||||
|
||||
{@a common-changes}
|
||||
### Changes you may see
|
||||
@ -27,6 +44,8 @@ If the errors are gone, switch back to Ivy by removing the changes to the `tscon
|
||||
|
||||
* Unbound inputs for directives (e.g. name in `<my-comp name="">`) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).
|
||||
|
||||
* Static attributes set directly in the HTML of a template will override any conflicting host attributes set by directives or components (previously, static host attributes set by directives / components would override static template attributes if conflicting).
|
||||
|
||||
{@a less-common-changes}
|
||||
### Less common changes
|
||||
|
||||
|
@ -115,6 +115,14 @@ We work toward a regular schedule of releases, so that you can plan and coordina
|
||||
|
||||
我们会定期发布新版本,以便随着 Angular 的不断演进,你可以提前计划并协调这些升级工作。
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Disclaimer: Dates are offered as general guidance and will be adjusted by us when necessary to ensure delivery of a high-quality platform.
|
||||
|
||||
免责条款:这些日期仅供参考,如有必要,我们会对其进行调整,以确保提供高质量的平台。
|
||||
|
||||
</div>
|
||||
|
||||
In general, you can expect the following release cycle:
|
||||
|
||||
通常,你可以期待下列发布周期:
|
||||
@ -135,35 +143,6 @@ This cadence of releases gives you access to new features as soon as they are re
|
||||
|
||||
这种发布节奏能让你尽快用上已就绪的新特性,同时,为生产环境下的用户维护本平台的稳定性和可靠性。
|
||||
|
||||
{@a schedule}
|
||||
|
||||
## Release schedule
|
||||
|
||||
## 发布计划
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Disclaimer: The dates are offered as general guidance and may be adjusted by us when necessary to ensure delivery of a high-quality platform.
|
||||
|
||||
免责声明:这些日期只是作为一般性的指导,在必要时我们会进行调整,以确保始终提供高质量的平台。
|
||||
|
||||
</div>
|
||||
|
||||
The following table contains our current target release dates for the next two major versions of Angular:
|
||||
|
||||
下表中包含 Angular 接下来两个主版本的目标发布日期:
|
||||
|
||||
Date | Stable Release | Compatibility
|
||||
---------------------- | -------------- | -------------
|
||||
日期 | 稳定版 | 兼容性
|
||||
2019 年 10/11 月 | 9.0.0 | ^8.0.0
|
||||
2020 年 5 月 | 10.0.0 | ^9.0.0
|
||||
Compatibility note: The primary goal of the backward compatibility promise is to ensure that changes in the core framework and tooling don't break the existing ecosystem of components and applications and don't put undue upgrade/migration burden on Angular application and component authors.
|
||||
|
||||
兼容性说明:向后兼容性承诺的主要目标是确保在核心框架和核心工具中的变化不会破坏现有组件和应用的生态系统,并且不要给 Angular 应用和组件的开发者带来额外的升级/迁移负担。
|
||||
|
||||
|
||||
|
||||
{@a lts}
|
||||
{@a support}
|
||||
## Support policy and schedule
|
||||
@ -229,9 +208,9 @@ To help ensure that you have sufficient time and a clear path to update, this is
|
||||
|
||||
** 宣布弃用:** 我们会在[变更记录](https://github.com/angular/angular/blob/master/CHANGELOG.md "Angular change log")中宣布要弃用的那些 API 和特性。启用的 API 在[文档](api?status=deprecated)中会显示成带~~删除线~~的样式。当我们宣布一项弃用时,我们还会宣布一个建议的升级路径。为便于查找,我们在[弃用列表](guide/deprecations)中包含一个关于弃用 API 和特性的汇总表。
|
||||
|
||||
* **Deprecation period:** When an API or a feature is deprecated, it will still be present in the [next two major releases](#schedule). After that, deprecated APIs and features will be candidates for removal. A deprecation can be announced in any release, but the removal of a deprecated API or feature will happen only in major release. Until a deprecated API or feature is removed, it will be maintained according to the LTS support policy, meaning that only critical and security issues will be fixed.
|
||||
* **Deprecation period:** When an API or a feature is deprecated, it will still be present in the next two major releases. After that, deprecated APIs and features will be candidates for removal. A deprecation can be announced in any release, but the removal of a deprecated API or feature will happen only in major release. Until a deprecated API or feature is removed, it will be maintained according to the LTS support policy, meaning that only critical and security issues will be fixed.
|
||||
|
||||
**弃用阶段:** 当 API 或特性已弃用时,它在[接下来的两个主版本](#schedule)中仍然会存在。再往后,弃用的 API 和特性将会进入候选弃用状态。可能会在任何一次发布中宣布弃用,但是只会在主版本中移除已弃用的 API 或特性。除非已弃用的 API 或特性已被移除,否则我们仍然会根据 LTS 支持策略来维护它,也就是说,只会修复严重问题和安全问题。
|
||||
**弃用阶段:** 当 API 或特性已弃用时,它在接下来的两个主版本中仍然会存在。再往后,弃用的 API 和特性将会进入候选弃用状态。可能会在任何一次发布中宣布弃用,但是只会在主版本中移除已弃用的 API 或特性。除非已弃用的 API 或特性已被移除,否则我们仍然会根据 LTS 支持策略来维护它,也就是说,只会修复严重问题和安全问题。
|
||||
|
||||
* **npm dependencies:** We only make npm dependency updates that require changes to your apps in a major release.
|
||||
In minor releases, we update peer dependencies by expanding the supported versions, but we do not require projects to update these dependencies until a future major version. This means that during minor Angular releases, npm dependency updates within Angular applications and libraries are optional.
|
||||
|
@ -194,7 +194,7 @@ Let's assume that we are routing from the *Home => About*.
|
||||
|
||||
我们假设正在从 *Home* 转场到 *About*,`Home => About`。
|
||||
|
||||
<code-example path="animations/src/app/animations.ts" header="src/app/animations.ts" region="query" language="typescript"></code-example>
|
||||
<code-example path="animations/src/app/animations.ts" header="src/app/animations.ts (Continuation from above)" region="query" language="typescript"></code-example>
|
||||
|
||||
The animation code does the following after styling the views:
|
||||
|
||||
|
@ -1549,58 +1549,123 @@ Instead, you'd use property binding and write it like this:
|
||||
|
||||
### 类绑定
|
||||
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
|
||||
Add and remove CSS class names from an element's `class` attribute with
|
||||
a **class binding**.
|
||||
|
||||
使用**类绑定**可以从元素的 `class` 属性中添加和删除 CSS 类名称。
|
||||
|
||||
|
||||
Here's how to set the attribute without binding in plain HTML:
|
||||
|
||||
下面是在普通 HTML 中不用绑定来设置 Attribute 的方法:
|
||||
下面是在普通 HTML 中不用绑定来设置 `class` Attribute 的方法:
|
||||
|
||||
|
||||
```html
|
||||
|
||||
<!-- standard class attribute setting -->
|
||||
|
||||
<div class="item clearance special">Item clearance special</div>
|
||||
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
|
||||
Class binding syntax resembles property binding, but instead of an element property between brackets, start with the prefix `class`,
|
||||
optionally followed by a dot (`.`) and the name of a CSS class: `[class.class-name]`.
|
||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
||||
|
||||
类绑定语法类似于 Property 绑定,但其括号之间不是元素的 Property,而是由前缀 `class`、点(`.`)和 CSS 类名(点和 CSS 类名可选)组成 `[class.class-name]` : `[class.class-name]` 。
|
||||
你还可以使用**类绑定**来为一个元素添加和移除 CSS 类。
|
||||
|
||||
To create a single class binding, start with the prefix `class` followed by a dot (`.`) and the name of the CSS class (for example, `[class.foo]="hasFoo"`).
|
||||
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of `undefined`, see [styling delegation](#styling-delegation)).
|
||||
|
||||
要创建单个类的绑定,请使用 `class` 前缀,紧跟一个点(`.`),再跟上 CSS 类名,比如 `[class.foo]="hasFoo"`。
|
||||
当绑定表达式为真值的时候,Angular 就会加上这个类,为假值则会移除,但 `undefined` 是假值中的例外,参见[样式委派](#styling-delegation) 部分。
|
||||
|
||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
||||
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
|
||||
With object format, Angular will add a class only if its associated value is truthy.
|
||||
|
||||
要想创建多个类的绑定,请使用通用的 `[class]` 形式来绑定类,而不要带点,比如 `[class]="classExpr"`。
|
||||
该表达式可以是空格分隔的类名字符串,或者用一个以类名为键、真假值表达式为值的对象。
|
||||
当使用对象格式时,Angular 只会加上那些相关的值为真的类名。
|
||||
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
一定要注意,在对象型表达式中(如 `object`、`Array`、`Map`、`Set` 等),当这个类列表改变时,对象的引用也必须修改。仅仅修改其属性而不修改对象引用是无法生效的。
|
||||
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
|
||||
如果有多处绑定到了同一个类名,出现的冲突将根据[样式的优先级规则](#styling-precedence)进行解决。
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
绑定类型
|
||||
</th>
|
||||
<th>
|
||||
语法
|
||||
</th>
|
||||
<th>
|
||||
输入类型
|
||||
</th>
|
||||
<th>
|
||||
输入值范例
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single class binding</td>
|
||||
<td><code>[class.foo]="hasFoo"</code></td>
|
||||
<td><code>boolean | undefined | null</code></td>
|
||||
<td><code>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>单个类绑定</td>
|
||||
<td><code>[class.foo]="hasFoo"</code></td>
|
||||
<td><code>boolean | undefined | null</code></td>
|
||||
<td><code>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-class binding</td>
|
||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>多个类绑定</td>
|
||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: boolean | undefined | null}</code></td>
|
||||
<td><code>{foo: true, bar: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['foo', 'bar']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
You can replace that with a binding to a string of the desired class names; this is an all-or-nothing, replacement binding.
|
||||
|
||||
可以把它改写为绑定到所需 CSS 类名的绑定;这是一个或者全有或者全无的替换型绑定。
|
||||
(译注:即当 resetClasses 有值时 class 这个 attribute 设置的内容会被完全覆盖)
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="class-override" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can also add a class to an element without overwriting the classes already on the element:
|
||||
|
||||
您还可以将一个类添加到元素上,而不会覆盖该元素上已经存在的类:
|
||||
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="add-class" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Finally, you can bind to a specific class name.
|
||||
Angular adds the class when the template expression evaluates to truthy.
|
||||
It removes the class when the expression is falsy.
|
||||
|
||||
最后,可以绑定到特定的类名。
|
||||
当模板表达式的求值结果是真值时,Angular 会添加这个类,反之则移除它。
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="is-special" header="src/app/app.component.html"></code-example>
|
||||
|
||||
While this technique is suitable for toggling a single class name,
|
||||
consider the [`NgClass`](guide/template-syntax#ngClass) directive when
|
||||
managing multiple class names at the same time.
|
||||
The [NgClass](#ngclass) directive can be used as an alternative to direct `[class]` bindings.
|
||||
However, using the above class binding syntax without `NgClass` is preferred because due to improvements in class binding in Angular, `NgClass` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
尽管此技术适用于切换单个类名,但在需要同时管理多个类名时请考虑使用 [`NgClass`](guide/template-syntax#ngClass) 指令。
|
||||
|
||||
@ -1611,32 +1676,26 @@ managing multiple class names at the same time.
|
||||
|
||||
### 样式绑定
|
||||
|
||||
You can set inline styles with a **style binding**.
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
|
||||
通过**样式绑定**,可以设置内联样式。
|
||||
下面演示了如何不通过绑定在普通 HTML 中设置 `style` 属性:
|
||||
|
||||
Style binding syntax resembles property binding.
|
||||
Instead of an element property between brackets, start with the prefix `style`,
|
||||
followed by a dot (`.`) and the name of a CSS style property: `[style.style-property]`.
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
|
||||
样式绑定的语法与属性绑定类似。
|
||||
但方括号中的部分不是元素的属性名,而由**`style`**前缀,一个点 (`.`)和 CSS 样式的属性名组成。
|
||||
形如:`[style.style-property]`。
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-binding" header="src/app/app.component.html"></code-example>
|
||||
你还可以通过**样式绑定**来动态设置样式。
|
||||
|
||||
Some style binding styles have a unit extension.
|
||||
The following example conditionally sets the font size in “em” and “%” units.
|
||||
|
||||
有些样式绑定中的样式带有单位。在这里,以根据条件用 “em” 和 “%” 来设置字体大小的单位。
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-binding-condition" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This technique is suitable for setting a single style, but consider
|
||||
the [`NgStyle`](guide/template-syntax#ngStyle) directive when setting several inline styles at the same time.
|
||||
|
||||
此技术适用于设置单个样式,当需要同时设置多个内联样式时请考虑使用 [`NgStyle`](guide/template-syntax#ngStyle) 指令。
|
||||
To create a single style binding, start with the prefix `style` followed by a dot (`.`) and the name of the CSS style property (for example, `[style.width]="width"`).
|
||||
The property will be set to the value of the bound expression, which is normally a string.
|
||||
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
||||
|
||||
要想创建单个样式的绑定,请以 `style` 前缀开头,紧跟一个点(`.`),再跟着 CSS 样式的属性名,比如 `[style.width]="width"`。
|
||||
该属性将会被设置为绑定表达式的值,该值通常为字符串。
|
||||
不过你还可以添加一个单位表达式,比如 `em` 或 `%`,这时候该值就要是一个 `number` 类型。
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
@ -1649,8 +1708,270 @@ Note that a _style property_ name can be written in either
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple styles you'd like to toggle, you can bind to the `[style]` property directly without the dot (for example, `[style]="styleExpr"`).
|
||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
||||
|
||||
如果要切换多个样式,你可以直接绑定到 `[style]` 属性而不用点(比如, `[style]="styleExpr"`)。赋给 `[style]` 的绑定表达式通常是一系列样式组成的字符串,比如 `"width: 100px; height: 100px;"` 。
|
||||
|
||||
|
||||
You can also format the expression as an object with style names as the keys and style values as the values, like `{width: '100px', height: '100px'}`.
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
你也可以把该表达式格式化成一个以样式名为键、以样式值为值的对象,比如 `{width: '100px', height: '100px'}` 。一定要注意,对于任何对象型的表达式( 如 `object` , `Array` , `Map` , `Set` 等),当这个样式列表改变时,对象的引用也必须修改。仅仅修改其属性而不修改对象引用是无法生效的。。
|
||||
|
||||
|
||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
||||
|
||||
如果有多处绑定了同一个样式属性,则会使用[样式的优先级规则](#styling-precedence)来解决冲突。
|
||||
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
绑定类型
|
||||
</th>
|
||||
<th>
|
||||
语法
|
||||
</th>
|
||||
<th>
|
||||
输入类型
|
||||
</th>
|
||||
<th>
|
||||
输入值范例
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single style binding</td>
|
||||
<td><code>[style.width]="width"</code></td>
|
||||
<td><code>string | undefined | null</code></td>
|
||||
<td><code>"100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>单一样式绑定</td>
|
||||
<td><code>[style.width]="width"</code></td>
|
||||
<td><code>string | undefined | null</code></td>
|
||||
<td><code>"100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>Single style binding with units</td>
|
||||
<td><code>[style.width.px]="width"</code></td>
|
||||
<td><code>number | undefined | null</code></td>
|
||||
<td><code>100</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>带单位的单一样式绑定</td>
|
||||
<td><code>[style.width.px]="width"</code></td>
|
||||
<td><code>number | undefined | null</code></td>
|
||||
<td><code>100</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-style binding</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>多个样式绑定</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: string | undefined | null}</code></td>
|
||||
<td><code>{width: '100px', height: '100px'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['width', '100px']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The [NgStyle](#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
|
||||
However, using the above style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
[NgStyle](#ngstyle) 指令可以作为 `[style]` 绑定的替代指令。但是,应该把上面这种 `[style]` 样式绑定语法作为首选,因为随着 Angular 中样式绑定的改进,`NgStyle` 将不再提供重要的价值,并最终在未来的某个版本中删除。
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a styling-precedence}
|
||||
### Styling Precedence
|
||||
|
||||
### 样式的优先级规则
|
||||
|
||||
|
||||
A single HTML element can have its CSS class list and style values bound to a multiple sources (for example, host bindings from multiple directives).
|
||||
|
||||
一个 HTML 元素可以把它的 CSS 类列表和样式值绑定到多个来源(例如,来自多个指令的宿主 `host` 绑定)。
|
||||
|
||||
|
||||
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
|
||||
|
||||
当对同一个类名或样式属性存在多个绑定时,Angular 会使用一组优先级规则来解决冲突,并确定最终哪些类或样式会应用到该元素中。
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
<h4>Styling precedence (highest to lowest)</h4>
|
||||
|
||||
<h4>样式的优先级规则(从高到低)</h4>
|
||||
|
||||
1. Template bindings
|
||||
|
||||
模板绑定
|
||||
|
||||
|
||||
1. Property binding (for example, `<div [class.foo]="hasFoo">` or `<div [style.color]="color">`)
|
||||
|
||||
属性绑定(例如 `<div [class.foo]="hasFoo">` 或 `<div [style.color]="color">`)
|
||||
|
||||
1. Map binding (for example, `<div [class]="classExpr">` or `<div [style]="styleExpr">`)
|
||||
|
||||
Map 绑定(例如,`<div [class]="classExpr">` 或 `<div [style]="styleExpr">` )
|
||||
|
||||
1. Static value (for example, `<div class="foo">` or `<div style="color: blue">`)
|
||||
|
||||
静态值(例如 `<div class="foo">` 或 `<div style="color: blue">` )
|
||||
|
||||
1. Directive host bindings
|
||||
|
||||
指令宿主绑定
|
||||
|
||||
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
|
||||
属性绑定(例如,`host: {'[class.foo]': 'hasFoo'}` 或 `host: {'[style.color]': 'color'}` )
|
||||
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
|
||||
Map 绑定(例如, `host: {'[class]': 'classExpr'}` 或者 `host: {'[style]': 'styleExpr'}` )
|
||||
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
|
||||
静态值(例如, `host: {'class': 'foo'}` 或 `host: {'style': 'color: blue'}` )
|
||||
|
||||
1. Component host bindings
|
||||
|
||||
组件宿主绑定
|
||||
|
||||
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
|
||||
属性绑定(例如, `host: {'[class.foo]': 'hasFoo'}` 或 `host: {'[style.color]': 'color'}` )
|
||||
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
|
||||
Map 绑定(例如, `host: {'[class]': 'classExpr'}` 或者 `host: {'[style]': 'styleExpr'}` )
|
||||
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
|
||||
静态值(例如, `host: {'class': 'foo'}` 或 `host: {'style': 'color: blue'}` )
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
The more specific a class or style binding is, the higher its precedence.
|
||||
|
||||
某个类或样式绑定越具体,它的优先级就越高。
|
||||
|
||||
|
||||
A binding to a specific class (for example, `[class.foo]`) will take precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) will take precedence over a generic `[style]` binding.
|
||||
|
||||
对具体类(例如 `[class.foo]` )的绑定优先于一般化的 `[class]` 绑定,对具体样式(例如 `[style.bar]` )的绑定优先于一般化的 `[style]` 绑定。
|
||||
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Specificity rules also apply when it comes to bindings that originate from different sources.
|
||||
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
|
||||
|
||||
当处理不同来源的绑定时,也适用这种基于具体度的规则。
|
||||
某个元素可能在声明它的模板中有一些绑定、在所匹配的指令中有一些宿主绑定、在所匹配的组件中有一些宿主绑定。
|
||||
|
||||
|
||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
|
||||
模板中的绑定是最具体的,因为它们直接并且唯一地应用于该元素,所以它们具有最高的优先级。
|
||||
|
||||
|
||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
||||
|
||||
指令的宿主绑定被认为不太具体,因为指令可以在多个位置使用,所以它们的优先级低于模板绑定。
|
||||
|
||||
|
||||
Directives often augment component behavior, so host bindings from components have the lowest precedence.
|
||||
|
||||
指令经常会增强组件的行为,所以组件的宿主绑定优先级最低。
|
||||
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In addition, bindings take precedence over static attributes.
|
||||
|
||||
另外,绑定总是优先于静态属性。
|
||||
|
||||
|
||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding will take precedence because it is dynamic.
|
||||
|
||||
在下面的例子中, `class` 和 `[class]` 具有相似的具体度,但 `[class]` 绑定优先,因为它是动态的。
|
||||
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a styling-delegation}
|
||||
### Delegating to styles with lower precedence
|
||||
|
||||
### 委托优先级较低的样式
|
||||
|
||||
|
||||
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
|
||||
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` will cause Angular to fall back to the next-highest precedence binding to that style.
|
||||
|
||||
更高优先级的样式可以使用 `undefined` 值“委托”给低级的优先级样式。虽然把 style 属性设置为 `null` 可以确保该样式被移除,但把它设置为 `undefined` 会导致 Angular 回退到该样式的次高优先级。
|
||||
|
||||
|
||||
For example, consider the following template:
|
||||
|
||||
例如,考虑以下模板:
|
||||
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property will fall back to the value of the `comp-with-host-binding` host binding.
|
||||
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
|
||||
|
||||
想象一下, `dirWithHostBinding` 指令和 `comp-with-host-binding` 组件都有 `[style.width]` 宿主绑定。在这种情况下,如果 `dirWithHostBinding` 把它的绑定设置为 `undefined` ,则 `width` 属性将回退到 `comp-with-host-binding` 主机绑定的值。但是,如果 `dirWithHostBinding` 把它的绑定设置为 `null` ,那么 `width` 属性就会被完全删除。
|
||||
|
||||
|
||||
{@a event-binding}
|
||||
|
||||
## Event binding `(event)`
|
||||
|
@ -951,8 +951,12 @@ Because `compileComponents` is asynchronous, it uses
|
||||
the [`async`](api/core/testing/async) utility
|
||||
function imported from `@angular/core/testing`.
|
||||
|
||||
由于 `compileComponents` 是异步的,所以它要使用从 `@angular/core/testing` 中导入的工具函数 [`async`](api/core/testing/async)。
|
||||
|
||||
Please refer to the [async](#async) section for more details.
|
||||
|
||||
欲知详情,请参见 [async](#async) 部分。
|
||||
|
||||
</div>
|
||||
|
||||
#### Reduce the setup
|
||||
@ -1904,17 +1908,17 @@ XHR calls within a test are rare, but if you need to call XHR, see [`async()`](#
|
||||
|
||||
#### `tick()` 函数
|
||||
|
||||
You do have to call `tick()` to advance the (virtual) clock.
|
||||
You do have to call [tick()](api/core/testing/tick) to advance the (virtual) clock.
|
||||
|
||||
你必须调用 `tick()` 函数来向前推动(虚拟)时钟。
|
||||
|
||||
Calling `tick()` simulates the passage of time until all pending asynchronous activities finish.
|
||||
Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish.
|
||||
In this case, it waits for the error handler's `setTimeout()`.
|
||||
|
||||
调用 `tick()` 会模拟时光的流逝,直到所有未决的异步活动都结束为止。
|
||||
在这个例子中,它会等待错误处理器中的 `setTimeout()`。
|
||||
|
||||
The `tick()` function accepts milliseconds as a parameter (defaults to 0 if not provided). The parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback.
|
||||
The [tick()](api/core/testing/tick) function accepts milliseconds as a parameter (defaults to 0 if not provided). The parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback.
|
||||
|
||||
`tick()` 函数接受一个毫秒值作为参数(如果没有提供则默认为 0)。该参数表示虚拟时钟要前进多少。
|
||||
比如,如果你的 `fakeAsync()` 测试中有一个 `setTimeout(fn, 100)` 函数,你就需要用 `tick(100)` 来触发它的 fn 回调。
|
||||
@ -1924,7 +1928,7 @@ The `tick()` function accepts milliseconds as a parameter (defaults to 0 if not
|
||||
region="fake-async-test-tick">
|
||||
</code-example>
|
||||
|
||||
The `tick()` function is one of the Angular testing utilities that you import with `TestBed`.
|
||||
The [tick()](api/core/testing/tick) function is one of the Angular testing utilities that you import with `TestBed`.
|
||||
It's a companion to `fakeAsync()` and you can only call it within a `fakeAsync()` body.
|
||||
|
||||
`tick()` 函数是你从 `TestBed` 中导入的 Angular 测试实用工具之一。
|
||||
@ -2137,7 +2141,7 @@ The first quote hasn't arrived yet.
|
||||
注意,这个 `<quote>` 元素应该在 `ngOnInit()` 之后显示占位值(`'...'`),
|
||||
但第一个引文却没有出现。
|
||||
|
||||
To flush the first quote from the observable, you call `tick()`.
|
||||
To flush the first quote from the observable, you call [tick()](api/core/testing/tick).
|
||||
Then call `detectChanges()` to tell Angular to update the screen.
|
||||
|
||||
要刷出可观察对象中的第一个引文,你就要先调用 `tick()`,然后调用 `detectChanges()` 来要求 Angular 刷新屏幕。
|
||||
@ -2209,7 +2213,7 @@ When using an `intervalTimer()` such as `setInterval()` in `async()`, remember t
|
||||
#### _whenStable_
|
||||
|
||||
The test must wait for the `getQuote()` observable to emit the next quote.
|
||||
Instead of calling `tick()`, it calls `fixture.whenStable()`.
|
||||
Instead of calling [tick()](api/core/testing/tick), it calls `fixture.whenStable()`.
|
||||
|
||||
该测试必须等待 `getQuote()` 的可观察对象发出下一条引言。
|
||||
它不再调用 `tick()`,而是调用 `fixture.whenStable()`。
|
||||
@ -2378,7 +2382,7 @@ you tell the `TestScheduler` to _flush_ its queue of prepared tasks like this.
|
||||
path="testing/src/app/twain/twain.component.marbles.spec.ts"
|
||||
region="test-scheduler-flush"></code-example>
|
||||
|
||||
This step serves a purpose analogous to `tick()` and `whenStable()` in the
|
||||
This step serves a purpose analogous to [tick()](api/core/testing/tick) and `whenStable()` in the
|
||||
earlier `fakeAsync()` and `async()` examples.
|
||||
The balance of the test is the same as those examples.
|
||||
|
||||
@ -2397,7 +2401,7 @@ Here's the marble testing version of the `getQuote()` error test.
|
||||
path="testing/src/app/twain/twain.component.marbles.spec.ts"
|
||||
region="error-test"></code-example>
|
||||
|
||||
It's still an async test, calling `fakeAsync()` and `tick()`, because the component itself
|
||||
It's still an async test, calling `fakeAsync()` and [tick()](api/core/testing/tick), because the component itself
|
||||
calls `setTimeout()` when processing errors.
|
||||
|
||||
它仍然是异步测试,要调用 `fakeAsync()` 和 `tick()`,这是因为组件自身在处理错误的时候调用 `setTimeout()`。
|
||||
|
@ -122,7 +122,3 @@ For simple updates, the CLI command [`ng update`](cli/update) is all you need. W
|
||||
* Versioning, release, support, and deprecation practices: [Angular versioning and releases](guide/releases "Angular versioning and releases")
|
||||
|
||||
版本、发布、支持与废弃的实践:[Angular 的版本与发布](guide/releases "Angular versioning and releases")
|
||||
|
||||
* Release schedule: [Angular versioning and releases](guide/releases#schedule "Angular versioning and releases")
|
||||
|
||||
发布计划:[Angular 的版本与发布](guide/releases#schedule "Angular versioning and releases")
|
||||
|
@ -906,6 +906,10 @@
|
||||
}
|
||||
],
|
||||
"docVersions": [
|
||||
{
|
||||
"title": "v8",
|
||||
"url": "https://v8.angular.io/"
|
||||
},
|
||||
{
|
||||
"title": "v7",
|
||||
"url": "https://v7.angular.io/"
|
||||
|
@ -24,7 +24,7 @@
|
||||
"build-local-with-viewengine": "yarn ~~build",
|
||||
"prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci",
|
||||
"build-local-with-viewengine-ci": "yarn ~~build --progress=false",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 94d07909c",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js d452f0873",
|
||||
"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",
|
||||
@ -107,8 +107,8 @@
|
||||
"zone.js": "~0.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "0.900.0-rc.11",
|
||||
"@angular/cli": "9.0.0-rc.11",
|
||||
"@angular-devkit/build-angular": "0.900.0-rc.14",
|
||||
"@angular/cli": "9.0.0-rc.14",
|
||||
"@angular/compiler-cli": "9.0.0-rc.11",
|
||||
"@angular/language-service": "9.0.0-rc.11",
|
||||
"@types/html-minifier": "^3.5.3",
|
||||
|
118
aio/yarn.lock
118
aio/yarn.lock
@ -2,27 +2,27 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular-devkit/architect@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.11.tgz#e9f3e5e372d467a220027cf53231b88e8e857fbc"
|
||||
integrity sha512-rRbq4ipppnY4FvVo89Cv+yC7rlt1/VFE/jaB77Ra2tI6zVlFWCTjnMzuc9TYz/3jK1ssThzgEA2sebPDmjH47w==
|
||||
"@angular-devkit/architect@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.14.tgz#cfdbee7899b9addfd9d43c638b0dbc21188f0a79"
|
||||
integrity sha512-dgEc/zYE0uzv+m8JTdv3FDc7bViJKbxs8FY3zdkArc6MXIXpoMzgvveEEHvhrpO0iu6njW/xRSZYtYnTIY4xlw==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/build-angular@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.900.0-rc.11.tgz#0bdec73d3ba631b3550527c54a35cf4145b0ed6d"
|
||||
integrity sha512-lp0f5lRsiTYSPjIgiWtX2N0NgV7dUZ/ifXYqqAEURKZ5O0jFF2gt2x9R29TmyFzTQ3ZP8O5AojO7POh1OfJ6iA==
|
||||
"@angular-devkit/build-angular@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.900.0-rc.14.tgz#2146316c0aca5311bfe139f7f7597ac025d792b2"
|
||||
integrity sha512-KnSni3kCvJbiBj43wRoY2OYsOKVDfqWGhBZsX4IPrv6OVMfCsWH9b62pcvJ0n63Qw/AwEaE6HUvCQB3IBR3lVg==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/build-optimizer" "0.900.0-rc.11"
|
||||
"@angular-devkit/build-webpack" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/build-optimizer" "0.900.0-rc.14"
|
||||
"@angular-devkit/build-webpack" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@babel/core" "7.7.7"
|
||||
"@babel/generator" "7.7.7"
|
||||
"@babel/preset-env" "7.7.7"
|
||||
"@ngtools/webpack" "9.0.0-rc.11"
|
||||
"@ngtools/webpack" "9.0.0-rc.14"
|
||||
ajv "6.10.2"
|
||||
autoprefixer "9.7.1"
|
||||
babel-loader "8.0.6"
|
||||
@ -77,10 +77,10 @@
|
||||
webpack-subresource-integrity "1.3.4"
|
||||
worker-plugin "3.2.0"
|
||||
|
||||
"@angular-devkit/build-optimizer@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.11.tgz#96c2446fa9cd2e90700ab8a68312b28b3907f6d9"
|
||||
integrity sha512-GJC+7H7ER6bxDC2UdAGwW357EYHpv8ISKKmS19wdJV5gZPMPANcpbg9FIpl27SDhUyZX9C2DOrcATvYYFoYgDQ==
|
||||
"@angular-devkit/build-optimizer@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.14.tgz#e90e955e1daf5689ad198a5253134187c99b7b5a"
|
||||
integrity sha512-MA2g8N9/cvzMvudEEjeaNV6STwSr8NI/znpv+nU6sQa4PdegIotBbqxGUmHMKtLH5cOwDy9hI47ANN+XADbIbQ==
|
||||
dependencies:
|
||||
loader-utils "1.2.3"
|
||||
source-map "0.7.3"
|
||||
@ -88,19 +88,19 @@
|
||||
typescript "3.6.4"
|
||||
webpack-sources "1.4.3"
|
||||
|
||||
"@angular-devkit/build-webpack@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.0-rc.11.tgz#d9a91c2b67a629f6adfe87980d26e495f2e30e0a"
|
||||
integrity sha512-utBAnkO6WLi323Rto1s7TJpaDRqDNR8jkD0C0PG5Zm3y1U9ARbAjTkugkrB/7bc4gEIqWZD+1dLYaaJCidye2Q==
|
||||
"@angular-devkit/build-webpack@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.0-rc.14.tgz#b932148f14ed0056f1885c98c330411a80d31331"
|
||||
integrity sha512-HvrDapIKr4k2a7Tf7MdW0miGOUUzHxRkGyDIWJBDXLbfOIt9BnhKfFGxP/SyDlwJnLyat9yYZjcDu1AI0E1Dmw==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/core@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.11.tgz#9e69545eb21284a573ad78e4c33003f2ea25afd5"
|
||||
integrity sha512-ki7Sln+mQdCctJNBalzy70tiFn2hOCY2Yyte8B0xKWVHnofZySvG+ANzoLgodnKFOBH18AQy35FhgzZM++N9tQ==
|
||||
"@angular-devkit/core@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.14.tgz#5cff058750c0b063a6f5fa1a2e830f1f48ffa56b"
|
||||
integrity sha512-hFiKoAPtnOqqYv97Y22OgyeTFxjNU/6WDhmuXkfbZDKychvuBLDOdgUhL43heEzavSfCCl23E0JmilwCUcepmw==
|
||||
dependencies:
|
||||
ajv "6.10.2"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
@ -108,12 +108,12 @@
|
||||
rxjs "6.5.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.11.tgz#e0d4d271d8d783ebf05eced576262f20e6c3562c"
|
||||
integrity sha512-aJqOLzsoAkVj3AVTf1ehH2hA9wHHz1+7TTtfqI+Yx+S3jFyvGmnKrNBCKtMuIV5JdEHiXmhhuGbNBHwRFWpOow==
|
||||
"@angular-devkit/schematics@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.14.tgz#4605b1ee9f18b772094697f9b35258fdac76d4b3"
|
||||
integrity sha512-i/XTxo7hTXTFKus51Qry3rRGHL2uS4SgufGqdvOcy2qZbjyh/wt0UDOGJu/w8dcA9pJm+vFBLAbnro5oFyIsVw==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
ora "4.0.2"
|
||||
rxjs "6.5.3"
|
||||
|
||||
@ -129,16 +129,16 @@
|
||||
optionalDependencies:
|
||||
parse5 "^5.0.0"
|
||||
|
||||
"@angular/cli@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.0.0-rc.11.tgz#5d830045bb95f4a38a1d0df02212207731061a57"
|
||||
integrity sha512-Du0y6rpOfGkH7h6ukZf5SKgpTv0uAZ5McNFrPAH2KFs7PgM4fyj9VmJ1lSns9WsVcEHdPlIPh8WGResUzvePdA==
|
||||
"@angular/cli@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.0.0-rc.14.tgz#4f43bb0eb9a18b8f5e9001ec0a9de01a20c31870"
|
||||
integrity sha512-qdktJY0swHMfAgx2+b7jbguNsONQLRLt2X910kRY8KdiCJDXAc2dPgk8lN4K1jzpPnyzWx/0cNcDhsIzsyLDrw==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@schematics/angular" "9.0.0-rc.11"
|
||||
"@schematics/update" "0.900.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
"@schematics/angular" "9.0.0-rc.14"
|
||||
"@schematics/update" "0.900.0-rc.14"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ansi-colors "4.1.1"
|
||||
debug "^4.1.1"
|
||||
@ -1101,12 +1101,12 @@
|
||||
call-me-maybe "^1.0.1"
|
||||
glob-to-regexp "^0.3.0"
|
||||
|
||||
"@ngtools/webpack@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.0-rc.11.tgz#10b5997bec7cf48d1b144c8b4d46ffd0039c522a"
|
||||
integrity sha512-qeW81ISiO8GVEndOaCYv0k6fzRIxzZs6jrXGl1pcLH1H6qv2mxhA5DA0vC/9TN6wenrS43RGjDIQpp+RvkiLwA==
|
||||
"@ngtools/webpack@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.0-rc.14.tgz#6a764138347d2ff3846753a141eaacdab3b0658c"
|
||||
integrity sha512-G98u14exE36kR4LflWB20ClJ6ql9B0qMcyokepjwpVAgaoDfpJRR7mKAZliMPd0KFXktdnct2QEyF6pbLevO7w==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
enhanced-resolve "4.1.1"
|
||||
rxjs "6.5.3"
|
||||
webpack-sources "1.4.3"
|
||||
@ -1169,21 +1169,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||
|
||||
"@schematics/angular@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.0-rc.11.tgz#d544c0d4e7b3dd59ed56be5183e038ebe06a165e"
|
||||
integrity sha512-9InC+F71KiPXE0jl7Ow4iPFJ2AZZDbfTM6yWZoYLk3hzTCohAZZciBl00Tfyu2uerGshx8akbJMLySjXtf+q0g==
|
||||
"@schematics/angular@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.0-rc.14.tgz#4112aeb6c76144893d65cab9f53ca8422adc3bbb"
|
||||
integrity sha512-NWxDLym2Sst5lTvV7QYkVUjy3N0CfCohhdWC4DGRtjUyTD2eUepAg1PZCQcq8U2iRtd78Lm1n4obDWO1tW3pXQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
|
||||
"@schematics/update@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.0-rc.11.tgz#d22df30f13a6f38970b759db61ad84d3f9b03a78"
|
||||
integrity sha512-nV0oCPzzd0vi2Exo1910rWXwz/RnMc4zF9FxSOCZzsIv+AkwIehhL815OKyjUSCzU9+IM0/o1LKkPPrSWK7QEA==
|
||||
"@schematics/update@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.0-rc.14.tgz#1debea3eb90559d25838e7b256b48bac216e19d9"
|
||||
integrity sha512-ZlsneHwpvrtpt0D10g4S8JftLaSFQtSO+kOD1uP26OxNMg9w54jrlr7xWSwAmT69/ETjNy8BFKXdcU9yvYixPA==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ini "1.3.5"
|
||||
npm-package-arg "^7.0.0"
|
||||
|
@ -167,6 +167,16 @@ module.exports = function(config) {
|
||||
conf.browserStack.tunnelIdentifier = tunnelIdentifier;
|
||||
}
|
||||
|
||||
// For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
||||
// the tunnel. We do this because devices are sometimes not able to properly resolve
|
||||
// `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
|
||||
// resolve to anything on SauceLabs VMs ensures that such requests are always resolved through
|
||||
// the tunnel, and resolve to the actual tunnel host machine (commonly the CircleCI VMs).
|
||||
// More context can be found in: https://github.com/angular/angular/pull/35171.
|
||||
if (process.env.SAUCE_LOCALHOST_ALIAS_DOMAIN) {
|
||||
conf.hostname = process.env.SAUCE_LOCALHOST_ALIAS_DOMAIN;
|
||||
}
|
||||
|
||||
if (process.env.KARMA_WEB_TEST_MODE) {
|
||||
// KARMA_WEB_TEST_MODE is used to setup karma to run in
|
||||
// SauceLabs or Browserstack
|
||||
|
12
package.json
12
package.json
@ -35,10 +35,10 @@
|
||||
},
|
||||
"// 1": "dependencies are used locally and by bazel",
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": "0.900.0-rc.10",
|
||||
"@angular-devkit/build-optimizer": "0.900.0-rc.10",
|
||||
"@angular-devkit/core": "9.0.0-rc.10",
|
||||
"@angular-devkit/schematics": "9.0.0-rc.10",
|
||||
"@angular-devkit/architect": "0.900.0-rc.14",
|
||||
"@angular-devkit/build-optimizer": "0.900.0-rc.14",
|
||||
"@angular-devkit/core": "9.0.0-rc.14",
|
||||
"@angular-devkit/schematics": "9.0.0-rc.14",
|
||||
"@angular/bazel": "file:./tools/npm/@angular_bazel",
|
||||
"@babel/core": "7.8.3",
|
||||
"@babel/generator": "7.8.3",
|
||||
@ -132,8 +132,8 @@
|
||||
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
|
||||
"// 3": "when updating @bazel/bazel version you also need to update the RBE settings in .bazelrc (see https://github.com/angular/angular/pull/27935)",
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "0.900.0-rc.11",
|
||||
"@angular/cli": "9.0.0-rc.11",
|
||||
"@angular-devkit/build-angular": "0.900.0-rc.14",
|
||||
"@angular/cli": "9.0.0-rc.14",
|
||||
"@bazel/bazel": "2.0.0",
|
||||
"@bazel/buildifier": "^0.29.0",
|
||||
"@bazel/ibazel": "^0.11.1",
|
||||
|
@ -102,6 +102,10 @@ pkg_web(
|
||||
history_server(
|
||||
name = "prodserver",
|
||||
data = [":prodapp"],
|
||||
args = [
|
||||
"--port",
|
||||
"4200",
|
||||
],
|
||||
templated_args = ["src/prodapp"],
|
||||
)
|
||||
|
||||
@ -116,7 +120,7 @@ filegroup(
|
||||
|
||||
ts_devserver(
|
||||
name = "devserver",
|
||||
additional_root_paths = ["src/_"],
|
||||
additional_root_paths = ["project/src/_"],
|
||||
port = 4200,
|
||||
entry_module = "project/src/main.dev",
|
||||
serving_path = "/bundle.min.js",
|
||||
|
@ -39,7 +39,7 @@ function addDevDependenciesToPackageJson(options: Schema) {
|
||||
const devDependencies: [string, string][] = [
|
||||
['@angular/bazel', angularCore.version],
|
||||
['@bazel/bazel', '2.0.0'],
|
||||
['@bazel/ibazel', '0.10.3'],
|
||||
['@bazel/ibazel', '0.11.1'],
|
||||
['@bazel/karma', '1.2.2'],
|
||||
['@bazel/protractor', '1.2.2'],
|
||||
['@bazel/rollup', '1.2.2'],
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This package contains the core functionality of the Angular compiler. It provides APIs for the implementor of a TypeScript compiler to provide Angular compilation as well.
|
||||
|
||||
It supports the 'ngc' command-line tool and the Angular CLI (via the `NgtscProgram`).
|
||||
It supports the 'ngc' command-line tool and the Angular CLI (via the `NgtscProgram`), as well as an experimental integration with `tsc_wrapped` and the `ts_library` Bazel rule via `NgTscPlugin`.
|
||||
|
||||
# Angular compilation
|
||||
|
||||
|
@ -97,6 +97,8 @@ export class NgCompiler {
|
||||
private resourceManager: HostResourceLoader;
|
||||
private cycleAnalyzer: CycleAnalyzer;
|
||||
readonly incrementalDriver: IncrementalDriver;
|
||||
readonly ignoreForDiagnostics: Set<ts.SourceFile>;
|
||||
readonly ignoreForEmit: Set<ts.SourceFile>;
|
||||
|
||||
constructor(
|
||||
private host: NgCompilerHost, private options: NgCompilerOptions,
|
||||
@ -142,6 +144,14 @@ export class NgCompiler {
|
||||
}
|
||||
}
|
||||
setIncrementalDriver(tsProgram, this.incrementalDriver);
|
||||
|
||||
this.ignoreForDiagnostics = new Set([
|
||||
this.typeCheckFile,
|
||||
...host.factoryFiles.map(fileName => getSourceFileOrError(tsProgram, fileName)),
|
||||
...host.summaryFiles.map(fileName => getSourceFileOrError(tsProgram, fileName)),
|
||||
]);
|
||||
|
||||
this.ignoreForEmit = new Set([this.typeCheckFile]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,7 +295,6 @@ export class NgCompiler {
|
||||
*/
|
||||
prepareEmit(): {
|
||||
transformers: ts.CustomTransformers,
|
||||
ignoreFiles: Set<ts.SourceFile>,
|
||||
} {
|
||||
const compilation = this.ensureAnalyzed();
|
||||
|
||||
@ -321,9 +330,7 @@ export class NgCompiler {
|
||||
}
|
||||
before.push(ivySwitchTransform);
|
||||
|
||||
const ignoreFiles = new Set<ts.SourceFile>([this.typeCheckFile]);
|
||||
|
||||
return {transformers: {before, afterDeclarations} as ts.CustomTransformers, ignoreFiles};
|
||||
return {transformers: {before, afterDeclarations} as ts.CustomTransformers};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,17 +97,22 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
|
||||
readonly inputFiles: ReadonlyArray<string>;
|
||||
readonly rootDirs: ReadonlyArray<AbsoluteFsPath>;
|
||||
readonly typeCheckFile: AbsoluteFsPath;
|
||||
readonly factoryFiles: AbsoluteFsPath[];
|
||||
readonly summaryFiles: AbsoluteFsPath[];
|
||||
|
||||
constructor(
|
||||
delegate: ExtendedTsCompilerHost, inputFiles: ReadonlyArray<string>,
|
||||
rootDirs: ReadonlyArray<AbsoluteFsPath>, private shims: ShimGenerator[],
|
||||
entryPoint: AbsoluteFsPath|null, typeCheckFile: AbsoluteFsPath,
|
||||
factoryFiles: AbsoluteFsPath[], summaryFiles: AbsoluteFsPath[],
|
||||
factoryTracker: FactoryTracker|null, diagnostics: ts.Diagnostic[]) {
|
||||
super(delegate);
|
||||
|
||||
this.factoryTracker = factoryTracker;
|
||||
this.entryPoint = entryPoint;
|
||||
this.typeCheckFile = typeCheckFile;
|
||||
this.factoryFiles = factoryFiles;
|
||||
this.summaryFiles = summaryFiles;
|
||||
this.diagnostics = diagnostics;
|
||||
this.inputFiles = inputFiles;
|
||||
this.rootDirs = rootDirs;
|
||||
@ -136,31 +141,36 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
|
||||
|
||||
const generators: ShimGenerator[] = [];
|
||||
let summaryGenerator: SummaryGenerator|null = null;
|
||||
let summaryFiles: AbsoluteFsPath[];
|
||||
|
||||
if (shouldGenerateSummaryShims) {
|
||||
// Summary generation.
|
||||
summaryGenerator = SummaryGenerator.forRootFiles(normalizedInputFiles);
|
||||
generators.push(summaryGenerator);
|
||||
summaryFiles = summaryGenerator.getSummaryFileNames();
|
||||
} else {
|
||||
summaryFiles = [];
|
||||
}
|
||||
|
||||
let factoryTracker: FactoryTracker|null = null;
|
||||
let factoryFiles: AbsoluteFsPath[];
|
||||
if (shouldGenerateFactoryShims) {
|
||||
// Factory generation.
|
||||
const factoryGenerator = FactoryGenerator.forRootFiles(normalizedInputFiles);
|
||||
const factoryFileMap = factoryGenerator.factoryFileMap;
|
||||
|
||||
const factoryFileNames = Array.from(factoryFileMap.keys());
|
||||
rootFiles.push(...factoryFileNames);
|
||||
factoryFiles = Array.from(factoryFileMap.keys());
|
||||
rootFiles.push(...factoryFiles);
|
||||
generators.push(factoryGenerator);
|
||||
|
||||
factoryTracker = new FactoryTracker(factoryGenerator);
|
||||
} else {
|
||||
factoryFiles = [];
|
||||
}
|
||||
|
||||
// Done separately to preserve the order of factory files before summary files in rootFiles.
|
||||
// TODO(alxhub): validate that this is necessary.
|
||||
if (summaryGenerator !== null) {
|
||||
rootFiles.push(...summaryGenerator.getSummaryFileNames());
|
||||
}
|
||||
rootFiles.push(...summaryFiles);
|
||||
|
||||
|
||||
const rootDirs = getRootDirs(delegate, options as ts.CompilerOptions);
|
||||
@ -203,8 +213,8 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
|
||||
}
|
||||
|
||||
return new NgCompilerHost(
|
||||
delegate, rootFiles, rootDirs, generators, entryPoint, typeCheckFile, factoryTracker,
|
||||
diagnostics);
|
||||
delegate, rootFiles, rootDirs, generators, entryPoint, typeCheckFile, factoryFiles,
|
||||
summaryFiles, factoryTracker, diagnostics);
|
||||
}
|
||||
|
||||
getSourceFile(
|
||||
|
@ -88,13 +88,43 @@ export class NgtscProgram implements api.Program {
|
||||
getTsSyntacticDiagnostics(
|
||||
sourceFile?: ts.SourceFile|undefined,
|
||||
cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] {
|
||||
const ignoredFiles = this.compiler.ignoreForDiagnostics;
|
||||
if (sourceFile !== undefined) {
|
||||
if (ignoredFiles.has(sourceFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.tsProgram.getSyntacticDiagnostics(sourceFile, cancellationToken);
|
||||
} else {
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
for (const sf of this.tsProgram.getSourceFiles()) {
|
||||
if (!ignoredFiles.has(sf)) {
|
||||
diagnostics.push(...this.tsProgram.getSyntacticDiagnostics(sf, cancellationToken));
|
||||
}
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
getTsSemanticDiagnostics(
|
||||
sourceFile?: ts.SourceFile|undefined,
|
||||
cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] {
|
||||
const ignoredFiles = this.compiler.ignoreForDiagnostics;
|
||||
if (sourceFile !== undefined) {
|
||||
if (ignoredFiles.has(sourceFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.tsProgram.getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
} else {
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
for (const sf of this.tsProgram.getSourceFiles()) {
|
||||
if (!ignoredFiles.has(sf)) {
|
||||
diagnostics.push(...this.tsProgram.getSemanticDiagnostics(sf, cancellationToken));
|
||||
}
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
getNgOptionDiagnostics(cancellationToken?: ts.CancellationToken|
|
||||
@ -144,7 +174,8 @@ export class NgtscProgram implements api.Program {
|
||||
emitCallback?: api.TsEmitCallback | undefined;
|
||||
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined;
|
||||
}|undefined): ts.EmitResult {
|
||||
const {transformers, ignoreFiles} = this.compiler.prepareEmit();
|
||||
const {transformers} = this.compiler.prepareEmit();
|
||||
const ignoreFiles = this.compiler.ignoreForEmit;
|
||||
const emitCallback = opts && opts.emitCallback || defaultEmitCallback;
|
||||
|
||||
const writeFile: ts.WriteFileCallback =
|
||||
|
@ -22,9 +22,11 @@ const STRIP_NG_FACTORY = /(.*)NgFactory$/;
|
||||
* class of an input ts.SourceFile.
|
||||
*/
|
||||
export class FactoryGenerator implements ShimGenerator {
|
||||
private constructor(private map: Map<string, string>) {}
|
||||
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
||||
|
||||
get factoryFileMap(): Map<string, string> { return this.map; }
|
||||
get factoryFileMap(): Map<AbsoluteFsPath, AbsoluteFsPath> { return this.map; }
|
||||
|
||||
get factoryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
|
||||
|
||||
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
|
||||
|
||||
@ -101,7 +103,7 @@ export class FactoryGenerator implements ShimGenerator {
|
||||
}
|
||||
|
||||
static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): FactoryGenerator {
|
||||
const map = new Map<AbsoluteFsPath, string>();
|
||||
const map = new Map<AbsoluteFsPath, AbsoluteFsPath>();
|
||||
files.filter(sourceFile => isNonDeclarationTsPath(sourceFile))
|
||||
.forEach(
|
||||
sourceFile =>
|
||||
|
@ -15,9 +15,9 @@ import {ShimGenerator} from './api';
|
||||
import {generatedModuleName} from './util';
|
||||
|
||||
export class SummaryGenerator implements ShimGenerator {
|
||||
private constructor(private map: Map<AbsoluteFsPath, string>) {}
|
||||
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
||||
|
||||
getSummaryFileNames(): string[] { return Array.from(this.map.keys()); }
|
||||
getSummaryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
|
||||
|
||||
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
|
||||
|
||||
@ -78,7 +78,7 @@ export class SummaryGenerator implements ShimGenerator {
|
||||
}
|
||||
|
||||
static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): SummaryGenerator {
|
||||
const map = new Map<AbsoluteFsPath, string>();
|
||||
const map = new Map<AbsoluteFsPath, AbsoluteFsPath>();
|
||||
files.filter(sourceFile => isNonDeclarationTsPath(sourceFile))
|
||||
.forEach(
|
||||
sourceFile =>
|
||||
|
@ -1,99 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {PluginCompilerHost} from '@bazel/typescript/internal/tsc_wrapped/plugin_api';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
/**
|
||||
* Extension of the TypeScript compiler host that supports files added to the Program which
|
||||
* were never on disk.
|
||||
*
|
||||
* This is used for backwards-compatibility with the ViewEngine compiler, which used ngsummary
|
||||
* and ngfactory files as inputs to the program. We call these inputs "synthetic".
|
||||
*
|
||||
* They need to be program inputs because user code may import from these generated files.
|
||||
*
|
||||
* TODO(alxhub): remove this after all ng_module users have migrated to Ivy
|
||||
*/
|
||||
export class SyntheticFilesCompilerHost implements PluginCompilerHost {
|
||||
/**
|
||||
* SourceFiles which are added to the program but which never existed on disk.
|
||||
*/
|
||||
syntheticFiles = new Map<string, ts.SourceFile>();
|
||||
|
||||
constructor(
|
||||
private rootFiles: string[], private delegate: ts.CompilerHost,
|
||||
generatedFiles: (rootFiles: string[]) => {
|
||||
[fileName: string]: (host: ts.CompilerHost) => ts.SourceFile | undefined
|
||||
}) {
|
||||
// Allow ngtsc to contribute in-memory synthetic files, which will be loaded
|
||||
// as if they existed on disk as action inputs.
|
||||
const angularGeneratedFiles = generatedFiles !(rootFiles);
|
||||
for (const f of Object.keys(angularGeneratedFiles)) {
|
||||
const generator = angularGeneratedFiles[f];
|
||||
const generated = generator(delegate);
|
||||
if (generated) {
|
||||
this.syntheticFiles.set(generated.fileName, generated);
|
||||
}
|
||||
}
|
||||
if (delegate.getDirectories !== undefined) {
|
||||
this.getDirectories = (path: string) => delegate.getDirectories !(path);
|
||||
}
|
||||
}
|
||||
|
||||
fileExists(filePath: string): boolean {
|
||||
if (this.syntheticFiles.has(filePath)) {
|
||||
return true;
|
||||
}
|
||||
return this.delegate.fileExists(filePath);
|
||||
}
|
||||
|
||||
/** Loads a source file from in-memory map, or delegates. */
|
||||
getSourceFile(
|
||||
fileName: string, languageVersion: ts.ScriptTarget,
|
||||
onError?: (message: string) => void): ts.SourceFile|undefined {
|
||||
const syntheticFile = this.syntheticFiles.get(fileName);
|
||||
if (syntheticFile) {
|
||||
return syntheticFile !;
|
||||
}
|
||||
return this.delegate.getSourceFile(fileName, languageVersion, onError);
|
||||
}
|
||||
|
||||
get inputFiles() { return [...this.rootFiles, ...Array.from(this.syntheticFiles.keys())]; }
|
||||
|
||||
fileNameToModuleId(fileName: string) {
|
||||
return fileName; // TODO: Ivy logic. don't forget that the delegate has the google3 logic
|
||||
}
|
||||
|
||||
// Delegate everything else to the original compiler host.
|
||||
|
||||
getDefaultLibFileName(options: ts.CompilerOptions): string {
|
||||
return this.delegate.getDefaultLibFileName(options);
|
||||
}
|
||||
|
||||
writeFile(
|
||||
fileName: string, content: string, writeByteOrderMark: boolean,
|
||||
onError: ((message: string) => void)|undefined,
|
||||
sourceFiles: ReadonlyArray<ts.SourceFile>|undefined): void {
|
||||
this.delegate.writeFile(fileName, content, writeByteOrderMark, onError, sourceFiles);
|
||||
}
|
||||
|
||||
getCanonicalFileName(path: string) { return this.delegate.getCanonicalFileName(path); }
|
||||
|
||||
getCurrentDirectory(): string { return this.delegate.getCurrentDirectory(); }
|
||||
|
||||
useCaseSensitiveFileNames(): boolean { return this.delegate.useCaseSensitiveFileNames(); }
|
||||
|
||||
getNewLine(): string { return this.delegate.getNewLine(); }
|
||||
|
||||
getDirectories?: (path: string) => string[];
|
||||
|
||||
readFile(fileName: string): string|undefined { return this.delegate.readFile(fileName); }
|
||||
|
||||
trace(s: string): void { console.error(s); }
|
||||
}
|
@ -6,77 +6,105 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {PluginCompilerHost, TscPlugin} from '@bazel/typescript/internal/tsc_wrapped/plugin_api';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {SyntheticFilesCompilerHost} from './synthetic_files_compiler_host';
|
||||
import {NgCompiler, NgCompilerHost} from './core';
|
||||
import {NgCompilerOptions, UnifiedModulesHost} from './core/api';
|
||||
import {NodeJSFileSystem, setFileSystem} from './file_system';
|
||||
import {NOOP_PERF_RECORDER} from './perf';
|
||||
|
||||
// Copied from tsc_wrapped/plugin_api.ts to avoid a runtime dependency on the
|
||||
// @bazel/typescript package - it would be strange for non-Bazel users of
|
||||
// Angular to fetch that package.
|
||||
function createProxy<T>(delegate: T): T {
|
||||
const proxy = Object.create(null);
|
||||
for (const k of Object.keys(delegate)) {
|
||||
proxy[k] = function() { return (delegate as any)[k].apply(delegate, arguments); };
|
||||
}
|
||||
return proxy;
|
||||
// The following is needed to fix a the chicken-and-egg issue where the sync (into g3) script will
|
||||
// refuse to accept this file unless the following string appears:
|
||||
// import * as plugin from '@bazel/typescript/internal/tsc_wrapped/plugin_api';
|
||||
|
||||
/**
|
||||
* A `ts.CompilerHost` which also returns a list of input files, out of which the `ts.Program`
|
||||
* should be created.
|
||||
*
|
||||
* Currently mirrored from @bazel/typescript/internal/tsc_wrapped/plugin_api (with the naming of
|
||||
* `fileNameToModuleName` corrected).
|
||||
*/
|
||||
interface PluginCompilerHost extends ts.CompilerHost, Partial<UnifiedModulesHost> {
|
||||
readonly inputFiles: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the plugin interface from tsc_wrapped which is currently under active development. To
|
||||
* enable progress to be made in parallel, the upstream interface isn't implemented directly.
|
||||
* Instead, `TscPlugin` here is structurally assignable to what tsc_wrapped expects.
|
||||
*/
|
||||
interface TscPlugin {
|
||||
readonly name: string;
|
||||
|
||||
wrapHost(
|
||||
host: ts.CompilerHost&Partial<UnifiedModulesHost>, inputFiles: ReadonlyArray<string>,
|
||||
options: ts.CompilerOptions): PluginCompilerHost;
|
||||
|
||||
setupCompilation(program: ts.Program, oldProgram?: ts.Program): {
|
||||
ignoreForDiagnostics: Set<ts.SourceFile>,
|
||||
ignoreForEmit: Set<ts.SourceFile>,
|
||||
};
|
||||
|
||||
getDiagnostics(file?: ts.SourceFile): ts.Diagnostic[];
|
||||
|
||||
getOptionDiagnostics(): ts.Diagnostic[];
|
||||
|
||||
getNextProgram(): ts.Program;
|
||||
|
||||
prepareEmit(): {
|
||||
transformers: ts.CustomTransformers,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A plugin for `tsc_wrapped` which allows Angular compilation from a plain `ts_library`.
|
||||
*/
|
||||
export class NgTscPlugin implements TscPlugin {
|
||||
constructor(private angularCompilerOptions: unknown) {}
|
||||
name = 'ngtsc';
|
||||
|
||||
wrapHost(inputFiles: string[], compilerHost: ts.CompilerHost) {
|
||||
return new SyntheticFilesCompilerHost(inputFiles, compilerHost, (rootFiles: string[]) => {
|
||||
// For demo purposes, assume that the first .ts rootFile is the only
|
||||
// one that needs ngfactory.js/d.ts back-compat files produced.
|
||||
const tsInputs = rootFiles.filter(f => f.endsWith('.ts') && !f.endsWith('.d.ts'));
|
||||
const factoryPath: string = tsInputs[0].replace(/\.ts/, '.ngfactory.ts');
|
||||
private options: NgCompilerOptions|null = null;
|
||||
private host: NgCompilerHost|null = null;
|
||||
private _compiler: NgCompiler|null = null;
|
||||
|
||||
get compiler(): NgCompiler {
|
||||
if (this._compiler === null) {
|
||||
throw new Error('Lifecycle error: setupCompilation() must be called first.');
|
||||
}
|
||||
return this._compiler;
|
||||
}
|
||||
|
||||
constructor(private ngOptions: {}) { setFileSystem(new NodeJSFileSystem()); }
|
||||
|
||||
wrapHost(
|
||||
host: ts.CompilerHost&UnifiedModulesHost, inputFiles: readonly string[],
|
||||
options: ts.CompilerOptions): PluginCompilerHost {
|
||||
this.options = {...this.ngOptions, ...options } as NgCompilerOptions;
|
||||
this.host = NgCompilerHost.wrap(host, inputFiles, this.options);
|
||||
return this.host;
|
||||
}
|
||||
|
||||
setupCompilation(program: ts.Program, oldProgram?: ts.Program): {
|
||||
ignoreForDiagnostics: Set<ts.SourceFile>,
|
||||
ignoreForEmit: Set<ts.SourceFile>,
|
||||
} {
|
||||
if (this.host === null || this.options === null) {
|
||||
throw new Error('Lifecycle error: setupCompilation() before wrapHost().');
|
||||
}
|
||||
this._compiler =
|
||||
new NgCompiler(this.host, this.options, program, oldProgram, NOOP_PERF_RECORDER);
|
||||
return {
|
||||
factoryPath: (host: ts.CompilerHost) =>
|
||||
ts.createSourceFile(factoryPath, 'contents', ts.ScriptTarget.ES5),
|
||||
ignoreForDiagnostics: this._compiler.ignoreForDiagnostics,
|
||||
ignoreForEmit: this._compiler.ignoreForEmit,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
wrap(program: ts.Program, config: {}, host: ts.CompilerHost) {
|
||||
const proxy = createProxy(program);
|
||||
proxy.getSemanticDiagnostics = (sourceFile: ts.SourceFile) => {
|
||||
const result: ts.Diagnostic[] = [...program.getSemanticDiagnostics(sourceFile)];
|
||||
|
||||
// For demo purposes, trigger a diagnostic when the sourcefile has a magic string
|
||||
if (sourceFile.text.indexOf('diag') >= 0) {
|
||||
const fake: ts.Diagnostic = {
|
||||
file: sourceFile,
|
||||
start: 0,
|
||||
length: 3,
|
||||
messageText: 'Example Angular Compiler Diagnostic',
|
||||
category: ts.DiagnosticCategory.Error,
|
||||
code: 12345,
|
||||
// source is the name of the plugin.
|
||||
source: 'ngtsc',
|
||||
};
|
||||
result.push(fake);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
return proxy;
|
||||
getDiagnostics(file?: ts.SourceFile): ts.Diagnostic[] {
|
||||
return this.compiler.getDiagnostics(file);
|
||||
}
|
||||
|
||||
createTransformers(host: PluginCompilerHost) {
|
||||
const afterDeclarations: Array<ts.TransformerFactory<ts.SourceFile|ts.Bundle>> =
|
||||
[(context: ts.TransformationContext) => (sf: ts.SourceFile | ts.Bundle) => {
|
||||
const visitor = (node: ts.Node): ts.Node => {
|
||||
if (ts.isClassDeclaration(node)) {
|
||||
// For demo purposes, transform the class name in the .d.ts output
|
||||
return ts.updateClassDeclaration(
|
||||
node, node.decorators, node.modifiers, ts.createIdentifier('NEWNAME'),
|
||||
node.typeParameters, node.heritageClauses, node.members);
|
||||
}
|
||||
return ts.visitEachChild(node, visitor, context);
|
||||
};
|
||||
return visitor(sf) as ts.SourceFile;
|
||||
}];
|
||||
return {afterDeclarations};
|
||||
}
|
||||
getOptionDiagnostics(): ts.Diagnostic[] { return this.compiler.getOptionDiagnostics(); }
|
||||
|
||||
getNextProgram(): ts.Program { return this.compiler.getNextProgram(); }
|
||||
|
||||
prepareEmit(): {transformers: ts.CustomTransformers;} { return this.compiler.prepareEmit(); }
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -e -o pipefail
|
||||
|
||||
# Script that runs all unit tests of the `angular/components` repository. The script also
|
||||
# sets up the test blocklist from `tools/components-repo-ci`.
|
||||
# Script that runs all unit tests of the `angular/components` repository.
|
||||
|
||||
# Path to the Angular project.
|
||||
angular_dir=$(pwd)
|
||||
@ -11,10 +10,6 @@ angular_dir=$(pwd)
|
||||
# repository has been cloned into.
|
||||
cd ${COMPONENTS_REPO_TMP_DIR}
|
||||
|
||||
# Copy the test blocklist into the `angular/components` repository. The unit tests will
|
||||
# automatically pick up the blocklist and disable the specified tests.
|
||||
cp ${angular_dir}/tools/components-repo-ci/test-blocklist.ts ${COMPONENTS_REPO_TMP_DIR}/test/
|
||||
|
||||
# Create a symlink for the Bazel binary installed through NPM, as running through Yarn introduces OOM errors.
|
||||
./scripts/circleci/setup_bazel_binary.sh
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
mkdir tmp
|
||||
cd tmp
|
||||
npm init -y
|
||||
npm install typescript@~2.7.0 rxjs@^6.0.0 zone.js@~0.8.26 @angular/{animations,core,common,forms,router,platform-browser,platform-browser-dynamic,platform-webworker,platform-webworker-dynamic,platform-server,service-worker,compiler,compiler-cli,upgrade,language-service,elements} --save
|
||||
npm install typescript@~3.7.4 rxjs@^6.5.3 zone.js@~0.10.2 @bazel/typescript@^1.0.0 rollup@^1.20.0 rollup-plugin-commonjs@^9.0.0 rollup-plugin-node-resolve@^4.2.0 rollup-plugin-sourcemaps@0.4.0 @angular/{animations,bazel,common,compiler,compiler-cli,core,elements,forms,language-service,localize,platform-browser,platform-browser-dynamic,platform-server,platform-webworker,platform-webworker-dynamic,router,service-worker,upgrade} --save
|
||||
cd ..
|
||||
rm -rf tmp
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
mkdir tmp
|
||||
cd tmp
|
||||
npm init -y
|
||||
npm install typescript@~3.1.1 rxjs@^6.0.0-beta.4 zone.js@~0.8.20 @angular/{animations,core,common,forms,http,router,platform-browser,platform-browser-dynamic,platform-webworker,platform-webworker-dynamic,platform-server,compiler,compiler-cli,language-service,service-worker,upgrade}@next --save
|
||||
npm install typescript@~3.7.4 rxjs@^6.5.3 zone.js@~0.10.2 @bazel/typescript@^1.0.0 rollup@^1.20.0 rollup-plugin-commonjs@^9.0.0 rollup-plugin-node-resolve@^4.2.0 rollup-plugin-sourcemaps@0.4.0 @angular/{animations,bazel,common,compiler,compiler-cli,core,elements,forms,language-service,localize,platform-browser,platform-browser-dynamic,platform-server,platform-webworker,platform-webworker-dynamic,router,service-worker,upgrade}@next --save
|
||||
cd ..
|
||||
rm -rf tmp
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
# Fetched from https://github.com/yarnpkg/yarn/releases/download/v1.21.1/yarn-v1.21.1.tar.gz
|
||||
licenses(["notice"])
|
@ -1,26 +0,0 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
For Yarn software
|
||||
|
||||
Copyright (c) 2016-present, Yarn Contributors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,60 +0,0 @@
|
||||
<p align="center">
|
||||
<a href="https://yarnpkg.com/">
|
||||
<img alt="Yarn" src="https://github.com/yarnpkg/assets/blob/master/yarn-kitten-full.png?raw=true" width="546">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Fast, reliable, and secure dependency management.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/yarnpkg/yarn"><img alt="Circle Status" src="https://circleci.com/gh/yarnpkg/yarn.svg?style=shield&circle-token=5f0a78473b0f440afb218bf2b82323cc6b3cb43f"></a>
|
||||
<a href="https://ci.appveyor.com/project/kittens/yarn/branch/master"><img alt="Appveyor Status" src="https://ci.appveyor.com/api/projects/status/0xdv8chwe2kmk463?svg=true"></a>
|
||||
<a href="https://dev.azure.com/yarnpkg/yarn/_build"><img alt="Azure Pipelines status" src="https://dev.azure.com/yarnpkg/yarn/_apis/build/status/Yarn%20Acceptance%20Tests"></a>
|
||||
<a href="https://discord.gg/yarnpkg"><img alt="Discord Chat" src="https://img.shields.io/discord/226791405589233664.svg"></a>
|
||||
<a href="http://commitizen.github.io/cz-cli/"><img alt="Commitizen friendly" src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg"></a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Fast:** Yarn caches every package it has downloaded, so it never needs to download the same package again. It also does almost everything concurrently to maximize resource utilization. This means even faster installs.
|
||||
|
||||
**Reliable:** Using a detailed but concise lockfile format and a deterministic algorithm for install operations, Yarn is able to guarantee that any installation that works on one system will work exactly the same on another system.
|
||||
|
||||
**Secure:** Yarn uses checksums to verify the integrity of every installed package before its code is executed.
|
||||
|
||||
## Features
|
||||
|
||||
* **Offline Mode.** If you've installed a package before, then you can install it again without an internet connection.
|
||||
* **Deterministic.** The same dependencies will be installed in the same exact way on any machine, regardless of installation order.
|
||||
* **Network Performance.** Yarn efficiently queues requests and avoids request waterfalls in order to maximize network utilization.
|
||||
* **Network Resilience.** A single request that fails will not cause the entire installation to fail. Requests are automatically retried upon failure.
|
||||
* **Flat Mode.** Yarn resolves mismatched versions of dependencies to a single version to avoid creating duplicates.
|
||||
* **More emojis.** 🐈
|
||||
|
||||
## Installing Yarn
|
||||
|
||||
Read the [Installation Guide](https://yarnpkg.com/en/docs/install) on our website for detailed instructions on how to install Yarn.
|
||||
|
||||
## Using Yarn
|
||||
|
||||
Read the [Usage Guide](https://yarnpkg.com/en/docs/usage) on our website for detailed instructions on how to use Yarn.
|
||||
|
||||
## Contributing to Yarn
|
||||
|
||||
Contributions are always welcome, no matter how large or small. Substantial feature requests should be proposed as an [RFC](https://github.com/yarnpkg/rfcs). Before contributing, please read the [code of conduct](CODE_OF_CONDUCT.md).
|
||||
|
||||
See [Contributing](https://yarnpkg.com/org/contributing/).
|
||||
|
||||
## Prior art
|
||||
|
||||
Yarn wouldn't exist if it wasn't for excellent prior art. Yarn has been inspired by the following projects:
|
||||
|
||||
- [Bundler](https://github.com/bundler/bundler)
|
||||
- [Cargo](https://github.com/rust-lang/cargo)
|
||||
- [npm](https://github.com/npm/cli)
|
||||
|
||||
## Credits
|
||||
|
||||
Thanks to [Sam Holmes](https://github.com/samholmes) for donating the npm package name!
|
@ -1,35 +0,0 @@
|
||||
#!/bin/sh
|
||||
argv0=$(echo "$0" | sed -e 's,\\,/,g')
|
||||
basedir=$(dirname "$(readlink "$0" || echo "$argv0")")
|
||||
|
||||
case "$(uname -s)" in
|
||||
Darwin) basedir="$( cd "$( dirname "$argv0" )" && pwd )";;
|
||||
Linux) basedir=$(dirname "$(readlink -f "$0" || echo "$argv0")");;
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1;
|
||||
}
|
||||
|
||||
if command_exists node; then
|
||||
if [ "$YARN_FORCE_WINPTY" = 1 ] || command_exists winpty && test -t 1; then
|
||||
winpty node "$basedir/yarn.js" "$@"
|
||||
else
|
||||
exec node "$basedir/yarn.js" "$@"
|
||||
fi
|
||||
ret=$?
|
||||
# Debian and Ubuntu use "nodejs" as the name of the binary, not "node", so we
|
||||
# search for that too. See:
|
||||
# https://lists.debian.org/debian-devel-announce/2012/07/msg00002.html
|
||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=614907
|
||||
elif command_exists nodejs; then
|
||||
exec nodejs "$basedir/yarn.js" "$@"
|
||||
ret=$?
|
||||
else
|
||||
>&2 echo 'Yarn requires Node.js 4.0 or higher to be installed.'
|
||||
ret=1
|
||||
fi
|
||||
|
||||
exit $ret
|
@ -1,2 +0,0 @@
|
||||
@echo off
|
||||
node "%~dp0\yarn.js" %*
|
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable no-var */
|
||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||
'use strict';
|
||||
|
||||
var ver = process.versions.node;
|
||||
var majorVer = parseInt(ver.split('.')[0], 10);
|
||||
|
||||
if (majorVer < 4) {
|
||||
console.error('Node version ' + ver + ' is not supported, please use Node.js 4.0 or higher.');
|
||||
process.exit(1); // eslint-disable-line no-process-exit
|
||||
} else {
|
||||
try {
|
||||
require(__dirname + '/../lib/v8-compile-cache.js');
|
||||
} catch (err) {
|
||||
// We don't have/need this on legacy builds and dev builds
|
||||
}
|
||||
|
||||
// Just requiring this package will trigger a yarn run since the
|
||||
// `require.main === module` check inside `cli/index.js` will always
|
||||
// be truthy when built with webpack :(
|
||||
// `lib/cli` may be `lib/cli/index.js` or `lib/cli.js` depending on the build.
|
||||
var cli = require(__dirname + '/../lib/cli');
|
||||
if (!cli.autoRun) {
|
||||
cli.default().catch(function(error) {
|
||||
console.error(error.stack || error.message || error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
require('./yarn.js');
|
@ -1,2 +0,0 @@
|
||||
@echo off
|
||||
"%~dp0\yarn.cmd" %*
|
File diff suppressed because one or more lines are too long
@ -1,351 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const Module = require('module');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const vm = require('vm');
|
||||
const os = require('os');
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FileSystemBlobStore
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class FileSystemBlobStore {
|
||||
constructor(directory, prefix) {
|
||||
const name = prefix ? slashEscape(prefix + '.') : '';
|
||||
this._blobFilename = path.join(directory, name + 'BLOB');
|
||||
this._mapFilename = path.join(directory, name + 'MAP');
|
||||
this._lockFilename = path.join(directory, name + 'LOCK');
|
||||
this._directory = directory;
|
||||
this._load();
|
||||
}
|
||||
|
||||
has(key, invalidationKey) {
|
||||
if (hasOwnProperty.call(this._memoryBlobs, key)) {
|
||||
return this._invalidationKeys[key] === invalidationKey;
|
||||
} else if (hasOwnProperty.call(this._storedMap, key)) {
|
||||
return this._storedMap[key][0] === invalidationKey;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get(key, invalidationKey) {
|
||||
if (hasOwnProperty.call(this._memoryBlobs, key)) {
|
||||
if (this._invalidationKeys[key] === invalidationKey) {
|
||||
return this._memoryBlobs[key];
|
||||
}
|
||||
} else if (hasOwnProperty.call(this._storedMap, key)) {
|
||||
const mapping = this._storedMap[key];
|
||||
if (mapping[0] === invalidationKey) {
|
||||
return this._storedBlob.slice(mapping[1], mapping[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set(key, invalidationKey, buffer) {
|
||||
this._invalidationKeys[key] = invalidationKey;
|
||||
this._memoryBlobs[key] = buffer;
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
if (hasOwnProperty.call(this._memoryBlobs, key)) {
|
||||
this._dirty = true;
|
||||
delete this._memoryBlobs[key];
|
||||
}
|
||||
if (hasOwnProperty.call(this._invalidationKeys, key)) {
|
||||
this._dirty = true;
|
||||
delete this._invalidationKeys[key];
|
||||
}
|
||||
if (hasOwnProperty.call(this._storedMap, key)) {
|
||||
this._dirty = true;
|
||||
delete this._storedMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
isDirty() {
|
||||
return this._dirty;
|
||||
}
|
||||
|
||||
save() {
|
||||
const dump = this._getDump();
|
||||
const blobToStore = Buffer.concat(dump[0]);
|
||||
const mapToStore = JSON.stringify(dump[1]);
|
||||
|
||||
try {
|
||||
mkdirpSync(this._directory);
|
||||
fs.writeFileSync(this._lockFilename, 'LOCK', {flag: 'wx'});
|
||||
} catch (error) {
|
||||
// Swallow the exception if we fail to acquire the lock.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
fs.writeFileSync(this._blobFilename, blobToStore);
|
||||
fs.writeFileSync(this._mapFilename, mapToStore);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
} finally {
|
||||
fs.unlinkSync(this._lockFilename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_load() {
|
||||
try {
|
||||
this._storedBlob = fs.readFileSync(this._blobFilename);
|
||||
this._storedMap = JSON.parse(fs.readFileSync(this._mapFilename));
|
||||
} catch (e) {
|
||||
this._storedBlob = Buffer.alloc(0);
|
||||
this._storedMap = {};
|
||||
}
|
||||
this._dirty = false;
|
||||
this._memoryBlobs = {};
|
||||
this._invalidationKeys = {};
|
||||
}
|
||||
|
||||
_getDump() {
|
||||
const buffers = [];
|
||||
const newMap = {};
|
||||
let offset = 0;
|
||||
|
||||
function push(key, invalidationKey, buffer) {
|
||||
buffers.push(buffer);
|
||||
newMap[key] = [invalidationKey, offset, offset + buffer.length];
|
||||
offset += buffer.length;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this._memoryBlobs)) {
|
||||
const buffer = this._memoryBlobs[key];
|
||||
const invalidationKey = this._invalidationKeys[key];
|
||||
push(key, invalidationKey, buffer);
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this._storedMap)) {
|
||||
if (hasOwnProperty.call(newMap, key)) continue;
|
||||
const mapping = this._storedMap[key];
|
||||
const buffer = this._storedBlob.slice(mapping[1], mapping[2]);
|
||||
push(key, mapping[0], buffer);
|
||||
}
|
||||
|
||||
return [buffers, newMap];
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// NativeCompileCache
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class NativeCompileCache {
|
||||
constructor() {
|
||||
this._cacheStore = null;
|
||||
this._previousModuleCompile = null;
|
||||
}
|
||||
|
||||
setCacheStore(cacheStore) {
|
||||
this._cacheStore = cacheStore;
|
||||
}
|
||||
|
||||
install() {
|
||||
const self = this;
|
||||
this._previousModuleCompile = Module.prototype._compile;
|
||||
Module.prototype._compile = function(content, filename) {
|
||||
const mod = this;
|
||||
function require(id) {
|
||||
return mod.require(id);
|
||||
}
|
||||
require.resolve = function(request) {
|
||||
return Module._resolveFilename(request, mod);
|
||||
};
|
||||
require.main = process.mainModule;
|
||||
|
||||
// Enable support to add extra extension types
|
||||
require.extensions = Module._extensions;
|
||||
require.cache = Module._cache;
|
||||
|
||||
const dirname = path.dirname(filename);
|
||||
|
||||
const compiledWrapper = self._moduleCompile(filename, content);
|
||||
|
||||
// We skip the debugger setup because by the time we run, node has already
|
||||
// done that itself.
|
||||
|
||||
const args = [mod.exports, require, mod, filename, dirname, process, global];
|
||||
return compiledWrapper.apply(mod.exports, args);
|
||||
};
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
Module.prototype._compile = this._previousModuleCompile;
|
||||
}
|
||||
|
||||
_moduleCompile(filename, content) {
|
||||
// https://github.com/nodejs/node/blob/v7.5.0/lib/module.js#L511
|
||||
|
||||
// Remove shebang
|
||||
var contLen = content.length;
|
||||
if (contLen >= 2) {
|
||||
if (content.charCodeAt(0) === 35/*#*/ &&
|
||||
content.charCodeAt(1) === 33/*!*/) {
|
||||
if (contLen === 2) {
|
||||
// Exact match
|
||||
content = '';
|
||||
} else {
|
||||
// Find end of shebang line and slice it off
|
||||
var i = 2;
|
||||
for (; i < contLen; ++i) {
|
||||
var code = content.charCodeAt(i);
|
||||
if (code === 10/*\n*/ || code === 13/*\r*/) break;
|
||||
}
|
||||
if (i === contLen) {
|
||||
content = '';
|
||||
} else {
|
||||
// Note that this actually includes the newline character(s) in the
|
||||
// new output. This duplicates the behavior of the regular
|
||||
// expression that was previously used to replace the shebang line
|
||||
content = content.slice(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create wrapper function
|
||||
var wrapper = Module.wrap(content);
|
||||
|
||||
var invalidationKey = crypto
|
||||
.createHash('sha1')
|
||||
.update(content, 'utf8')
|
||||
.digest('hex');
|
||||
|
||||
var buffer = this._cacheStore.get(filename, invalidationKey);
|
||||
|
||||
var script = new vm.Script(wrapper, {
|
||||
filename: filename,
|
||||
lineOffset: 0,
|
||||
displayErrors: true,
|
||||
cachedData: buffer,
|
||||
produceCachedData: true,
|
||||
});
|
||||
|
||||
if (script.cachedDataProduced) {
|
||||
this._cacheStore.set(filename, invalidationKey, script.cachedData);
|
||||
} else if (script.cachedDataRejected) {
|
||||
this._cacheStore.delete(filename);
|
||||
}
|
||||
|
||||
var compiledWrapper = script.runInThisContext({
|
||||
filename: filename,
|
||||
lineOffset: 0,
|
||||
columnOffset: 0,
|
||||
displayErrors: true,
|
||||
});
|
||||
|
||||
return compiledWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// utilities
|
||||
//
|
||||
// https://github.com/substack/node-mkdirp/blob/f2003bb/index.js#L55-L98
|
||||
// https://github.com/zertosh/slash-escape/blob/e7ebb99/slash-escape.js
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
function mkdirpSync(p_) {
|
||||
_mkdirpSync(path.resolve(p_), parseInt('0777', 8) & ~process.umask());
|
||||
}
|
||||
|
||||
function _mkdirpSync(p, mode) {
|
||||
try {
|
||||
fs.mkdirSync(p, mode);
|
||||
} catch (err0) {
|
||||
if (err0.code === 'ENOENT') {
|
||||
_mkdirpSync(path.dirname(p));
|
||||
_mkdirpSync(p);
|
||||
} else {
|
||||
try {
|
||||
const stat = fs.statSync(p);
|
||||
if (!stat.isDirectory()) { throw err0; }
|
||||
} catch (err1) {
|
||||
throw err0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function slashEscape(str) {
|
||||
const ESCAPE_LOOKUP = {
|
||||
'\\': 'zB',
|
||||
':': 'zC',
|
||||
'/': 'zS',
|
||||
'\x00': 'z0',
|
||||
'z': 'zZ',
|
||||
};
|
||||
return str.replace(/[\\:\/\x00z]/g, match => (ESCAPE_LOOKUP[match]));
|
||||
}
|
||||
|
||||
function supportsCachedData() {
|
||||
const script = new vm.Script('""', {produceCachedData: true});
|
||||
// chakracore, as of v1.7.1.0, returns `false`.
|
||||
return script.cachedDataProduced === true;
|
||||
}
|
||||
|
||||
function getCacheDir() {
|
||||
// Avoid cache ownership issues on POSIX systems.
|
||||
const dirname = typeof process.getuid === 'function'
|
||||
? 'v8-compile-cache-' + process.getuid()
|
||||
: 'v8-compile-cache';
|
||||
const version = typeof process.versions.v8 === 'string'
|
||||
? process.versions.v8
|
||||
: typeof process.versions.chakracore === 'string'
|
||||
? 'chakracore-' + process.versions.chakracore
|
||||
: 'node-' + process.version;
|
||||
const cacheDir = path.join(os.tmpdir(), dirname, version);
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
function getParentName() {
|
||||
// `module.parent.filename` is undefined or null when:
|
||||
// * node -e 'require("v8-compile-cache")'
|
||||
// * node -r 'v8-compile-cache'
|
||||
// * Or, requiring from the REPL.
|
||||
const parentName = module.parent && typeof module.parent.filename === 'string'
|
||||
? module.parent.filename
|
||||
: process.cwd();
|
||||
return parentName;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// main
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
if (!process.env.DISABLE_V8_COMPILE_CACHE && supportsCachedData()) {
|
||||
const cacheDir = getCacheDir();
|
||||
const prefix = getParentName();
|
||||
const blobStore = new FileSystemBlobStore(cacheDir, prefix);
|
||||
|
||||
const nativeCompileCache = new NativeCompileCache();
|
||||
nativeCompileCache.setCacheStore(blobStore);
|
||||
nativeCompileCache.install();
|
||||
|
||||
process.once('exit', code => {
|
||||
if (blobStore.isDirty()) {
|
||||
blobStore.save();
|
||||
}
|
||||
nativeCompileCache.uninstall();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.__TEST__ = {
|
||||
FileSystemBlobStore,
|
||||
NativeCompileCache,
|
||||
mkdirpSync,
|
||||
slashEscape,
|
||||
supportsCachedData,
|
||||
getCacheDir,
|
||||
getParentName,
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "yarn",
|
||||
"installationMethod": "tar",
|
||||
"version": "1.21.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"preferGlobal": true,
|
||||
"description": "📦🐈 Fast, reliable, and secure dependency management.",
|
||||
"resolutions": {
|
||||
"sshpk": "^1.14.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
},
|
||||
"repository": "yarnpkg/yarn",
|
||||
"bin": {
|
||||
"yarn": "./bin/yarn.js",
|
||||
"yarnpkg": "./bin/yarn.js"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
### Unit tests for `angular/components`
|
||||
|
||||
Currently, all changes to Ivy are validated against the test suite of the
|
||||
`angular/components` repository. Known failing tests are skipped based on
|
||||
the blocklist in `tools/components-repo-ci/test-blocklist.ts`.
|
||||
|
||||
Whenever the root cause of a known failure is identified, the `notes` field
|
||||
for the corresponding tests should be updated. Whenever a failure is resolved,
|
||||
the corresponding tests should be removed from the blocklist.
|
||||
|
||||
### Debugging
|
||||
|
||||
Information on debugging can be found [here](../../docs/DEBUG_COMPONENTS_REPO_IVY.md).
|
||||
|
||||
### Excluding new tests
|
||||
|
||||
In case there are any tests in the components test suite that fail due to
|
||||
recent changes in the framework and you want to exclude the tests temporarily,
|
||||
a new entry can be added to the `test-blocklist.ts` file.
|
||||
|
||||
Each property in the blocklist object corresponds to a test in the components
|
||||
repository. The name of the property **must** match the exact test name. Additionally
|
||||
it's **recommended** that every entry has a field with a note on why the test is disabled.
|
||||
|
||||
```ts
|
||||
export const testBlocklist: any = {
|
||||
'MatSlider should be able to drag thumb': {
|
||||
error: 'Cannot register event "dragstart".',
|
||||
notes: 'Breaking change where HammerJS module needs to be imported.'
|
||||
}
|
||||
}
|
||||
```
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
// tslint:disable
|
||||
|
||||
interface BlocklistEntry {
|
||||
/** Description on why the given test is disabled. */
|
||||
notes: string;
|
||||
/** Optional error that has been thrown in the test. */
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of tests that should not run in the Angular component test suites. This should
|
||||
* be empty in the components repository, but the file will be overwritten if the framework
|
||||
* repository runs the Angular component test suites against the latest snapshots. This is
|
||||
* helpful because sometimes breaking changes that break individual tests land in the framework
|
||||
* repository. It should be possible to disable these tests until the component repository
|
||||
* migrated the broken tests.
|
||||
*/
|
||||
export const testBlocklist: {[testName: string]: BlocklistEntry} = {};
|
||||
|
||||
// clang-format on
|
@ -21,22 +21,18 @@ try {
|
||||
// KARMA_WEB_TEST_MODE is set which informs /karma-js.conf.js that it should
|
||||
// run the test with the karma saucelabs launcher
|
||||
process.env['KARMA_WEB_TEST_MODE'] = 'SL_REQUIRED';
|
||||
// Saucelabs parameters read from a temporary file that is created by the `sauce-service`. This
|
||||
// will be `null` if the test runs locally without the `sauce-service` being started.
|
||||
const saucelabsParams = readLocalSauceConnectParams();
|
||||
// Setup required SAUCE_* env if they are not already set
|
||||
if (!process.env['SAUCE_USERNAME'] || !process.env['SAUCE_ACCESS_KEY'] ||
|
||||
!process.env['SAUCE_TUNNEL_IDENTIFIER']) {
|
||||
try {
|
||||
// The following path comes from /tools/saucelabs/sauce-service.sh.
|
||||
// We setup the required saucelabs environment variables here for the karma test
|
||||
// from a json file under /tmp/angular/sauce-service so that we don't break the
|
||||
// test cache with a changing SAUCE_TUNNEL_IDENTIFIER provided through --test_env
|
||||
const scParams = require('/tmp/angular/sauce-service/sauce-connect-params.json');
|
||||
process.env['SAUCE_USERNAME'] = scParams.SAUCE_USERNAME;
|
||||
process.env['SAUCE_ACCESS_KEY'] = scParams.SAUCE_ACCESS_KEY;
|
||||
process.env['SAUCE_TUNNEL_IDENTIFIER'] = scParams.SAUCE_TUNNEL_IDENTIFIER;
|
||||
} catch (e) {
|
||||
console.error(e.stack || e);
|
||||
console.error(
|
||||
`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// We print a helpful error message below if the required Saucelabs parameters have not
|
||||
// been specified in test environment, and the `sauce-service` params file has not been
|
||||
// created either.
|
||||
if (saucelabsParams === null) {
|
||||
console.error(`
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!! Make sure that you have run "yarn bazel run //tools/saucelabs:sauce_service_setup"
|
||||
!!! (or "./tools/saucelabs/sauce-service.sh setup") before the test target. Alternately
|
||||
!!! you can provide the required SAUCE_* environment variables (SAUCE_USERNAME, SAUCE_ACCESS_KEY &
|
||||
@ -45,6 +41,16 @@ try {
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
|
||||
process.exit(1);
|
||||
}
|
||||
process.env['SAUCE_USERNAME'] = saucelabsParams.SAUCE_USERNAME;
|
||||
process.env['SAUCE_ACCESS_KEY'] = saucelabsParams.SAUCE_ACCESS_KEY;
|
||||
process.env['SAUCE_TUNNEL_IDENTIFIER'] = saucelabsParams.SAUCE_TUNNEL_IDENTIFIER;
|
||||
process.env['SAUCE_LOCALHOST_ALIAS_DOMAIN'] = saucelabsParams.SAUCE_LOCALHOST_ALIAS_DOMAIN;
|
||||
}
|
||||
|
||||
// Pass through the optional `SAUCE_LOCALHOST_ALIAS_DOMAIN` environment variable. The
|
||||
// variable is usually specified on CI, but is not required for testing with Saucelabs.
|
||||
if (!process.env['SAUCE_LOCALHOST_ALIAS_DOMAIN'] && saucelabsParams !== null) {
|
||||
process.env['SAUCE_LOCALHOST_ALIAS_DOMAIN'] = saucelabsParams.SAUCE_LOCALHOST_ALIAS_DOMAIN;
|
||||
}
|
||||
|
||||
const scStart = `${sauceService} start-ready-wait`;
|
||||
@ -60,3 +66,15 @@ try {
|
||||
console.error(e.stack || e);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function readLocalSauceConnectParams() {
|
||||
try {
|
||||
// The following path comes from /tools/saucelabs/sauce-service.sh.
|
||||
// We setup the required saucelabs environment variables here for the karma test
|
||||
// from a json file under /tmp/angular/sauce-service so that we don't break the
|
||||
// test cache with a changing SAUCE_TUNNEL_IDENTIFIER provided through --test_env
|
||||
return require('/tmp/angular/sauce-service/sauce-connect-params.json');
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ service-setup-command() {
|
||||
@fail "sc binary not found at ${SAUCE_CONNECT}"
|
||||
fi
|
||||
|
||||
echo "{ \"SAUCE_USERNAME\": \"${SAUCE_USERNAME}\", \"SAUCE_ACCESS_KEY\": \"${SAUCE_ACCESS_KEY}\", \"SAUCE_TUNNEL_IDENTIFIER\": \"${SAUCE_TUNNEL_IDENTIFIER}\" }" > ${SAUCE_PARAMS_JSON_FILE}
|
||||
echo "{ \"SAUCE_USERNAME\": \"${SAUCE_USERNAME}\", \"SAUCE_ACCESS_KEY\": \"${SAUCE_ACCESS_KEY}\", \"SAUCE_TUNNEL_IDENTIFIER\": \"${SAUCE_TUNNEL_IDENTIFIER}\", \"SAUCE_LOCALHOST_ALIAS_DOMAIN\": \"${SAUCE_LOCALHOST_ALIAS_DOMAIN}\" }" > ${SAUCE_PARAMS_JSON_FILE}
|
||||
|
||||
# Command arguments that will be passed to sauce-connect.
|
||||
# By default we disable SSL bumping for all requests. This is because SSL bumping is
|
||||
@ -147,6 +147,16 @@ service-setup-command() {
|
||||
"--user ${SAUCE_USERNAME}"
|
||||
# Don't add the --api-key here so we don't echo it out in service-pre-start
|
||||
)
|
||||
|
||||
if [[ -n "${SAUCE_LOCALHOST_ALIAS_DOMAIN}" ]]; then
|
||||
# Ensures that requests to the localhost alias domain are always resolved through the tunnel.
|
||||
# This environment variable is usually configured on CI, and refers to a domain that has been
|
||||
# locally configured in the current machine's hosts file (e.g. `/etc/hosts`). The domain should
|
||||
# resolve to the current machine in Saucelabs VMs, so we need to ensure that it is resolved
|
||||
# through the tunnel we going to create.
|
||||
sauce_args+=("--tunnel-domains ${SAUCE_LOCALHOST_ALIAS_DOMAIN}")
|
||||
fi
|
||||
|
||||
@echo "Sauce connect will be started with:"
|
||||
echo " ${SAUCE_CONNECT} ${sauce_args[@]}"
|
||||
SERVICE_COMMAND="${SAUCE_CONNECT} ${sauce_args[@]} --api-key ${SAUCE_ACCESS_KEY}"
|
||||
|
157
yarn.lock
157
yarn.lock
@ -2,35 +2,27 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular-devkit/architect@0.900.0-rc.10":
|
||||
version "0.900.0-rc.10"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.10.tgz#5fee2dd12de787d02c4c78d6d5dd53364bcaae25"
|
||||
integrity sha512-85bHmwBOJ9nkQ4Ict4rPNF6ON/zHkxGWNST9gy3BgwBcNUO3Y/udywxO0j2/UE/dQ8wtIvqKZfUD7GgVEnLXdQ==
|
||||
"@angular-devkit/architect@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.14.tgz#cfdbee7899b9addfd9d43c638b0dbc21188f0a79"
|
||||
integrity sha512-dgEc/zYE0uzv+m8JTdv3FDc7bViJKbxs8FY3zdkArc6MXIXpoMzgvveEEHvhrpO0iu6njW/xRSZYtYnTIY4xlw==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.10"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/architect@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.0-rc.11.tgz#e9f3e5e372d467a220027cf53231b88e8e857fbc"
|
||||
integrity sha512-rRbq4ipppnY4FvVo89Cv+yC7rlt1/VFE/jaB77Ra2tI6zVlFWCTjnMzuc9TYz/3jK1ssThzgEA2sebPDmjH47w==
|
||||
"@angular-devkit/build-angular@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.900.0-rc.14.tgz#2146316c0aca5311bfe139f7f7597ac025d792b2"
|
||||
integrity sha512-KnSni3kCvJbiBj43wRoY2OYsOKVDfqWGhBZsX4IPrv6OVMfCsWH9b62pcvJ0n63Qw/AwEaE6HUvCQB3IBR3lVg==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/build-angular@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.900.0-rc.11.tgz#0bdec73d3ba631b3550527c54a35cf4145b0ed6d"
|
||||
integrity sha512-lp0f5lRsiTYSPjIgiWtX2N0NgV7dUZ/ifXYqqAEURKZ5O0jFF2gt2x9R29TmyFzTQ3ZP8O5AojO7POh1OfJ6iA==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/build-optimizer" "0.900.0-rc.11"
|
||||
"@angular-devkit/build-webpack" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/build-optimizer" "0.900.0-rc.14"
|
||||
"@angular-devkit/build-webpack" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@babel/core" "7.7.7"
|
||||
"@babel/generator" "7.7.7"
|
||||
"@babel/preset-env" "7.7.7"
|
||||
"@ngtools/webpack" "9.0.0-rc.11"
|
||||
"@ngtools/webpack" "9.0.0-rc.14"
|
||||
ajv "6.10.2"
|
||||
autoprefixer "9.7.1"
|
||||
babel-loader "8.0.6"
|
||||
@ -95,10 +87,10 @@
|
||||
typescript "3.2.4"
|
||||
webpack-sources "1.3.0"
|
||||
|
||||
"@angular-devkit/build-optimizer@0.900.0-rc.10":
|
||||
version "0.900.0-rc.10"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.10.tgz#e2351297689185ed71b07d0537fc1d3c73e9b2b7"
|
||||
integrity sha512-cQkOLwzIdhZgAzkpea2Pi1oS8C8BDo+aB06JchMpdRudi1+ArbTbsaH/2FYhHMD4jkK2XCfKT8yFx20J8t2lVg==
|
||||
"@angular-devkit/build-optimizer@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.14.tgz#e90e955e1daf5689ad198a5253134187c99b7b5a"
|
||||
integrity sha512-MA2g8N9/cvzMvudEEjeaNV6STwSr8NI/znpv+nU6sQa4PdegIotBbqxGUmHMKtLH5cOwDy9hI47ANN+XADbIbQ==
|
||||
dependencies:
|
||||
loader-utils "1.2.3"
|
||||
source-map "0.7.3"
|
||||
@ -106,41 +98,19 @@
|
||||
typescript "3.6.4"
|
||||
webpack-sources "1.4.3"
|
||||
|
||||
"@angular-devkit/build-optimizer@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.900.0-rc.11.tgz#96c2446fa9cd2e90700ab8a68312b28b3907f6d9"
|
||||
integrity sha512-GJC+7H7ER6bxDC2UdAGwW357EYHpv8ISKKmS19wdJV5gZPMPANcpbg9FIpl27SDhUyZX9C2DOrcATvYYFoYgDQ==
|
||||
"@angular-devkit/build-webpack@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.0-rc.14.tgz#b932148f14ed0056f1885c98c330411a80d31331"
|
||||
integrity sha512-HvrDapIKr4k2a7Tf7MdW0miGOUUzHxRkGyDIWJBDXLbfOIt9BnhKfFGxP/SyDlwJnLyat9yYZjcDu1AI0E1Dmw==
|
||||
dependencies:
|
||||
loader-utils "1.2.3"
|
||||
source-map "0.7.3"
|
||||
tslib "1.10.0"
|
||||
typescript "3.6.4"
|
||||
webpack-sources "1.4.3"
|
||||
|
||||
"@angular-devkit/build-webpack@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.900.0-rc.11.tgz#d9a91c2b67a629f6adfe87980d26e495f2e30e0a"
|
||||
integrity sha512-utBAnkO6WLi323Rto1s7TJpaDRqDNR8jkD0C0PG5Zm3y1U9ARbAjTkugkrB/7bc4gEIqWZD+1dLYaaJCidye2Q==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/core@9.0.0-rc.10":
|
||||
version "9.0.0-rc.10"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.10.tgz#e751cedf6483026bbb3f9a5a6ab9c6e9833e1c3a"
|
||||
integrity sha512-aEdHb9M1rwAsyJSkmQ8J4BRiRLK4zWQL/CXxK15c056H04ncwU8OntBChpnSIf5iGsBM9UQRtiFbRubLfrpxgQ==
|
||||
dependencies:
|
||||
ajv "6.10.2"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
magic-string "0.25.4"
|
||||
rxjs "6.5.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/core@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.11.tgz#9e69545eb21284a573ad78e4c33003f2ea25afd5"
|
||||
integrity sha512-ki7Sln+mQdCctJNBalzy70tiFn2hOCY2Yyte8B0xKWVHnofZySvG+ANzoLgodnKFOBH18AQy35FhgzZM++N9tQ==
|
||||
"@angular-devkit/core@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.0-rc.14.tgz#5cff058750c0b063a6f5fa1a2e830f1f48ffa56b"
|
||||
integrity sha512-hFiKoAPtnOqqYv97Y22OgyeTFxjNU/6WDhmuXkfbZDKychvuBLDOdgUhL43heEzavSfCCl23E0JmilwCUcepmw==
|
||||
dependencies:
|
||||
ajv "6.10.2"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
@ -159,21 +129,12 @@
|
||||
rxjs "6.5.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@9.0.0-rc.10":
|
||||
version "9.0.0-rc.10"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.10.tgz#65d5e3fbf6a0c7c0689f3ac27cc1b629ca6c8570"
|
||||
integrity sha512-cuy+gDOhzf04vhJHsR21HnkEcOZqyfFabNs90Q5H77iGWl7GUO/RhwV7tXADdKZ4ee14rfFQi3TA0SrcOMXQlA==
|
||||
"@angular-devkit/schematics@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.14.tgz#4605b1ee9f18b772094697f9b35258fdac76d4b3"
|
||||
integrity sha512-i/XTxo7hTXTFKus51Qry3rRGHL2uS4SgufGqdvOcy2qZbjyh/wt0UDOGJu/w8dcA9pJm+vFBLAbnro5oFyIsVw==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.10"
|
||||
ora "4.0.2"
|
||||
rxjs "6.5.3"
|
||||
|
||||
"@angular-devkit/schematics@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.0.0-rc.11.tgz#e0d4d271d8d783ebf05eced576262f20e6c3562c"
|
||||
integrity sha512-aJqOLzsoAkVj3AVTf1ehH2hA9wHHz1+7TTtfqI+Yx+S3jFyvGmnKrNBCKtMuIV5JdEHiXmhhuGbNBHwRFWpOow==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
ora "4.0.2"
|
||||
rxjs "6.5.3"
|
||||
|
||||
@ -189,16 +150,16 @@
|
||||
"@angular/bazel@file:./tools/npm/@angular_bazel":
|
||||
version "0.0.0"
|
||||
|
||||
"@angular/cli@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.0.0-rc.11.tgz#5d830045bb95f4a38a1d0df02212207731061a57"
|
||||
integrity sha512-Du0y6rpOfGkH7h6ukZf5SKgpTv0uAZ5McNFrPAH2KFs7PgM4fyj9VmJ1lSns9WsVcEHdPlIPh8WGResUzvePdA==
|
||||
"@angular/cli@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.0.0-rc.14.tgz#4f43bb0eb9a18b8f5e9001ec0a9de01a20c31870"
|
||||
integrity sha512-qdktJY0swHMfAgx2+b7jbguNsONQLRLt2X910kRY8KdiCJDXAc2dPgk8lN4K1jzpPnyzWx/0cNcDhsIzsyLDrw==
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.900.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@schematics/angular" "9.0.0-rc.11"
|
||||
"@schematics/update" "0.900.0-rc.11"
|
||||
"@angular-devkit/architect" "0.900.0-rc.14"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
"@schematics/angular" "9.0.0-rc.14"
|
||||
"@schematics/update" "0.900.0-rc.14"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ansi-colors "4.1.1"
|
||||
debug "^4.1.1"
|
||||
@ -1269,12 +1230,12 @@
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.12.tgz#6692f1cbca664f68abbc62f9a26459fba8b9ff28"
|
||||
integrity sha512-5EzH1gHIonvvgA/xWRmVAJmRkTQj/yayUXyr66hFwNZiFE4j7lP8is9YQeXhwxGZEjO1PVMblAmFF0CyjNtPGw==
|
||||
|
||||
"@ngtools/webpack@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.0-rc.11.tgz#10b5997bec7cf48d1b144c8b4d46ffd0039c522a"
|
||||
integrity sha512-qeW81ISiO8GVEndOaCYv0k6fzRIxzZs6jrXGl1pcLH1H6qv2mxhA5DA0vC/9TN6wenrS43RGjDIQpp+RvkiLwA==
|
||||
"@ngtools/webpack@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.0-rc.14.tgz#6a764138347d2ff3846753a141eaacdab3b0658c"
|
||||
integrity sha512-G98u14exE36kR4LflWB20ClJ6ql9B0qMcyokepjwpVAgaoDfpJRR7mKAZliMPd0KFXktdnct2QEyF6pbLevO7w==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
enhanced-resolve "4.1.1"
|
||||
rxjs "6.5.3"
|
||||
webpack-sources "1.4.3"
|
||||
@ -1332,13 +1293,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||
|
||||
"@schematics/angular@9.0.0-rc.11":
|
||||
version "9.0.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.0-rc.11.tgz#d544c0d4e7b3dd59ed56be5183e038ebe06a165e"
|
||||
integrity sha512-9InC+F71KiPXE0jl7Ow4iPFJ2AZZDbfTM6yWZoYLk3hzTCohAZZciBl00Tfyu2uerGshx8akbJMLySjXtf+q0g==
|
||||
"@schematics/angular@9.0.0-rc.14":
|
||||
version "9.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.0.0-rc.14.tgz#4112aeb6c76144893d65cab9f53ca8422adc3bbb"
|
||||
integrity sha512-NWxDLym2Sst5lTvV7QYkVUjy3N0CfCohhdWC4DGRtjUyTD2eUepAg1PZCQcq8U2iRtd78Lm1n4obDWO1tW3pXQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
|
||||
"@schematics/angular@9.0.0-rc.8":
|
||||
version "9.0.0-rc.8"
|
||||
@ -1348,13 +1309,13 @@
|
||||
"@angular-devkit/core" "9.0.0-rc.8"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.8"
|
||||
|
||||
"@schematics/update@0.900.0-rc.11":
|
||||
version "0.900.0-rc.11"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.0-rc.11.tgz#d22df30f13a6f38970b759db61ad84d3f9b03a78"
|
||||
integrity sha512-nV0oCPzzd0vi2Exo1910rWXwz/RnMc4zF9FxSOCZzsIv+AkwIehhL815OKyjUSCzU9+IM0/o1LKkPPrSWK7QEA==
|
||||
"@schematics/update@0.900.0-rc.14":
|
||||
version "0.900.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.900.0-rc.14.tgz#1debea3eb90559d25838e7b256b48bac216e19d9"
|
||||
integrity sha512-ZlsneHwpvrtpt0D10g4S8JftLaSFQtSO+kOD1uP26OxNMg9w54jrlr7xWSwAmT69/ETjNy8BFKXdcU9yvYixPA==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "9.0.0-rc.11"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.11"
|
||||
"@angular-devkit/core" "9.0.0-rc.14"
|
||||
"@angular-devkit/schematics" "9.0.0-rc.14"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ini "1.3.5"
|
||||
npm-package-arg "^7.0.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user