Compare commits
20 Commits
11.0.0-nex
...
10.1.0
Author | SHA1 | Date | |
---|---|---|---|
c01bd0fe8e | |||
5588324802 | |||
437ecc8090 | |||
0dda97ea66 | |||
5e4aeaa348 | |||
cbbf8b542f | |||
91dfb18840 | |||
e44ddf5baa | |||
6b1a505566 | |||
659705ad78 | |||
8864b0ed69 | |||
4e596b672f | |||
83866827c3 | |||
7006cac50a | |||
dd82f2fefd | |||
bf003340ab | |||
5e35edd724 | |||
c132dcd0ae | |||
bbe331569b | |||
21e9a0032c |
28
.github/angular-robot.yml
vendored
28
.github/angular-robot.yml
vendored
@ -73,15 +73,14 @@ merge:
|
||||
- "packages/zone.js/scripts/**"
|
||||
|
||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
||||
\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||
|
||||
# label to monitor
|
||||
mergeLabel: "PR action: merge"
|
||||
mergeLabel: "action: merge"
|
||||
|
||||
# adding any of these labels will also add the merge label
|
||||
mergeLinkedLabels:
|
||||
- "PR action: merge-assistance"
|
||||
- "action: merge-assistance"
|
||||
|
||||
# list of checks that will determine if the merge label can be added
|
||||
checks:
|
||||
@ -94,17 +93,17 @@ merge:
|
||||
|
||||
# whether the PR shouldn't have a conflict with the base branch
|
||||
noConflict: true
|
||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
|
||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
||||
requiredLabels:
|
||||
- "PR target: *"
|
||||
- "target: *"
|
||||
- "cla: yes"
|
||||
|
||||
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
||||
forbiddenLabels:
|
||||
- "PR target: TBD"
|
||||
- "PR action: cleanup"
|
||||
- "PR action: review"
|
||||
- "PR state: blocked"
|
||||
- "target: TBD"
|
||||
- "action: cleanup"
|
||||
- "action: review"
|
||||
- "state: blocked"
|
||||
- "cla: no"
|
||||
|
||||
# list of PR statuses that need to be successful
|
||||
@ -121,12 +120,7 @@ merge:
|
||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
|
||||
\n{{PLACEHOLDER}}
|
||||
\n
|
||||
\n**If you want your PR to be merged, it has to pass all the CI checks.**
|
||||
\n
|
||||
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
|
||||
# options for the triage plugin
|
||||
triage:
|
||||
@ -186,4 +180,4 @@ rerunCircleCI:
|
||||
# set to true to disable
|
||||
disabled: false
|
||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
||||
triggerRerunLabel: "action: rerun CI at HEAD"
|
||||
|
19
.ng-dev/caretaker.ts
Normal file
19
.ng-dev/caretaker.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {CaretakerConfig} from '../dev-infra/caretaker/config';
|
||||
|
||||
/** The configuration for `ng-dev caretaker` commands. */
|
||||
export const caretaker: CaretakerConfig = {
|
||||
githubQueries: [
|
||||
{
|
||||
name: 'Merge Queue',
|
||||
query: `is:pr is:open status:success label:"action: merge"`,
|
||||
},
|
||||
{
|
||||
name: 'Merge Assistance Queue',
|
||||
query: `is:pr is:open status:success label:"action: merge-assistance"`,
|
||||
},
|
||||
{
|
||||
name: 'Primary Triage Queue',
|
||||
query: `is:open is:issue no:milestone`,
|
||||
}
|
||||
]
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import {caretaker} from './caretaker';
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
@ -8,4 +9,5 @@ module.exports = {
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
caretaker,
|
||||
};
|
||||
|
@ -1,38 +1,25 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
|
||||
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
|
||||
import {github} from './github';
|
||||
|
||||
/**
|
||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||
* are respected by the merge script (e.g. the target labels).
|
||||
*/
|
||||
export const merge = (): MergeConfig => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
export const merge: DevInfraMergeConfig['merge'] = async api => {
|
||||
return {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||
mergeReadyLabel: /^action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: 'action: merge-assistance',
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
labels: await getDefaultTargetLabelConfiguration(api, github, '@angular/core'),
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
// These SHAs are the commits that update the required license text in the header.
|
||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
252
CHANGELOG.md
252
CHANGELOG.md
@ -1,11 +1,74 @@
|
||||
<a name="10.1.0-rc.0"></a>
|
||||
# 10.1.0-rc.0 (2020-08-26)
|
||||
<a name="10.1.0"></a>
|
||||
# 10.1.0 (2020-09-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
||||
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
|
||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
||||
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
|
||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
|
||||
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
||||
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
||||
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
|
||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
||||
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([7ad3264](https://github.com/angular/angular/commit/7ad3264)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||
|
||||
### Code Refactoring
|
||||
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
||||
|
||||
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
||||
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
||||
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||
|
||||
|
||||
|
||||
@ -13,29 +76,6 @@
|
||||
## 10.0.14 (2020-08-26)
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.8"></a>
|
||||
# 10.1.0-next.8 (2020-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
||||
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([7ad3264](https://github.com/angular/angular/commit/7ad3264)), closes [#12842](https://github.com/angular/angular/issues/12842)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
||||
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.12"></a>
|
||||
## 10.0.12 (2020-08-24)
|
||||
|
||||
@ -53,13 +93,6 @@
|
||||
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.7"></a>
|
||||
# 10.1.0-next.7 (2020-08-19)
|
||||
|
||||
This release contains various API docs improvements.
|
||||
|
||||
|
||||
<a name="10.0.11"></a>
|
||||
## 10.0.11 (2020-08-19)
|
||||
|
||||
@ -70,29 +103,6 @@ This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.6"></a>
|
||||
# 10.1.0-next.6 (2020-08-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
||||
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
||||
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
||||
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
||||
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
||||
|
||||
### Code Refactoring
|
||||
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.10"></a>
|
||||
## 10.0.10 (2020-08-17)
|
||||
|
||||
@ -108,25 +118,6 @@ This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.5"></a>
|
||||
# 10.1.0-next.5 (2020-08-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
||||
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
||||
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
||||
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
||||
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.9"></a>
|
||||
## 10.0.9 (2020-08-12)
|
||||
|
||||
@ -148,24 +139,6 @@ This release contains various API docs improvements.
|
||||
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.4"></a>
|
||||
# 10.1.0-next.4 (2020-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.8"></a>
|
||||
## 10.0.8 (2020-08-04)
|
||||
|
||||
@ -187,16 +160,6 @@ This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.3"></a>
|
||||
# 10.1.0-next.3 (2020-07-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.6"></a>
|
||||
## 10.0.6 (2020-07-28)
|
||||
|
||||
@ -210,23 +173,6 @@ This release contains various API docs improvements.
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.2"></a>
|
||||
# 10.1.0-next.2 (2020-07-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
||||
|
||||
|
||||
|
||||
<a name="10.0.5"></a>
|
||||
## 10.0.5 (2020-07-22)
|
||||
|
||||
@ -261,62 +207,6 @@ This release contains various API docs improvements.
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||
|
||||
|
||||
<a name="10.1.0-next.1"></a>
|
||||
# 10.1.0-next.1 (2020-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663))
|
||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
||||
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15))
|
||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
||||
* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710)
|
||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
||||
|
||||
|
||||
|
||||
<a name="10.1.0-next.0"></a>
|
||||
# 10.1.0-next.0 (2020-07-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
||||
|
||||
|
||||
|
||||
<a name="10.0.3"></a>
|
||||
## 10.0.3 (2020-07-08)
|
||||
|
||||
@ -598,12 +488,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more
|
||||
information and updates.
|
||||
|
||||
If you used Closure Compiler with Angular in the past, you will likely
|
||||
be better off consuming Angular packages built from sources directly
|
||||
be better off consuming Angular packages built from sources directly
|
||||
rather than consuming the version we publish on npm,
|
||||
which is primarily optimized for Webpack/Rollup + Terser build pipeline.
|
||||
|
||||
As a temporary workaround, you might consider using your current build
|
||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||
pipeline with Closure flag `--compilation_level=SIMPLE`. This flag
|
||||
will ensure that your build pipeline produces buildable and
|
||||
runnable artifacts, at the cost of increased payload size due to
|
||||
advanced optimizations being disabled.
|
||||
@ -611,17 +501,17 @@ advanced optimizations being disabled.
|
||||
If you were affected by this change, please help us understand your
|
||||
needs by leaving a comment on https://github.com/angular/angular/issues/37234.
|
||||
|
||||
* **core:** make generic mandatory for ModuleWithProviders
|
||||
* **core:** make generic mandatory for ModuleWithProviders
|
||||
|
||||
A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated).
|
||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||
If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you.
|
||||
|
||||
However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to:
|
||||
|
||||
```
|
||||
error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
|
||||
```
|
||||
|
||||
|
||||
In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code.
|
||||
You should contact the library author to fix their library to provide a type parameter when they use this class.
|
||||
|
||||
@ -1949,7 +1839,7 @@ API surface going forward.
|
||||
* **core:** Injector.get now accepts abstract classes to return
|
||||
type-safe values. Previous implementation returned `any` through the
|
||||
deprecated implementation.
|
||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||
* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)).
|
||||
|
||||
If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview).
|
||||
|
||||
|
@ -230,7 +230,6 @@ Must be one of the following:
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
|
||||
|
@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model';
|
||||
template: `
|
||||
<section>
|
||||
Our list of heroes:
|
||||
<hero-profile *ngFor="let hero of heroes" [hero]="hero">
|
||||
</hero-profile>
|
||||
<toh-hero *ngFor="let hero of heroes" [hero]="hero">
|
||||
</toh-hero>
|
||||
Total powers: {{totalPowers}}<br>
|
||||
Average power: {{totalPowers / heroes.length}}
|
||||
</section>
|
||||
|
@ -87,7 +87,7 @@ To make one, enter the following command in the terminal, where `customers` is t
|
||||
ng generate module customers --route customers --module app.module
|
||||
</code-example>
|
||||
|
||||
This creates a `customers` folder with the new lazy-loadable module `CustomersModule` defined in the `customers.module.ts` file. The command automatically declares the `CustomersComponent` inside the new feature module.
|
||||
This creates a `customers` folder having the new lazy-loadable feature module `CustomersModule` defined in the `customers.module.ts` file and the routing module `CustomersRoutingModule` defined in the `customers-routing.module.ts` file. The command automatically declares the `CustomersComponent` and imports `CustomersRoutingModule` inside the new feature module.
|
||||
|
||||
Because the new module is meant to be lazy-loaded, the command does NOT add a reference to the new feature module in the application's root module file, `app.module.ts`.
|
||||
Instead, it adds the declared route, `customers` to the `routes` array declared in the module provided as the `--module` option.
|
||||
|
@ -217,7 +217,7 @@ script:
|
||||
- npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js
|
||||
```
|
||||
|
||||
This does the same things as the Circle CI configuration, except that Travis doesn't come with Chrome, so we use Chromium instead.
|
||||
This does the same things as the CircleCI configuration, except that Travis doesn't come with Chrome, so use Chromium instead.
|
||||
|
||||
Step 2: Commit your changes and push them to your repository.
|
||||
|
||||
|
@ -40,7 +40,7 @@ A later part of this tutorial, [Use forms for user input](start/start-forms "Try
|
||||
|
||||
<code-example header="src/app/cart.service.ts" path="getting-started/src/app/cart.service.1.ts"></code-example>
|
||||
|
||||
<div class="alert is-helpful>
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The StackBlitz generator might provide the cart service in `app.module.ts` by default. That differs from the example, which uses a bundle-optimization technique, an `@Injectable()` decorator with the `{ providedIn: 'root' }` statement.
|
||||
For more information about services, see [Introduction to Services and Dependency Injection](guide/architecture-services "Concepts > Intro to Services and DI").
|
||||
@ -236,7 +236,7 @@ For more information about services, see [Introduction to Services and Dependenc
|
||||
<!-- Accessing data with the HTTP client -->
|
||||
|
||||
Servers often return data in the form of a stream.
|
||||
Streams are useful because they make it easy to transform the returned data and make modifications to the way you request that data.
|
||||
Streams are useful because they make it easy to transform the returned data and make modifications to the way you request that data.
|
||||
The Angular HTTP client, `HttpClient`, is a built-in way to fetch data from external APIs and provide them to your app as a stream.
|
||||
|
||||
This section shows you how to use the HTTP client to retrieve shipping prices from an external file.
|
||||
|
@ -8,6 +8,7 @@ ts_library(
|
||||
],
|
||||
module_name = "@angular/dev-infra-private",
|
||||
deps = [
|
||||
"//dev-infra/caretaker",
|
||||
"//dev-infra/commit-message",
|
||||
"//dev-infra/format",
|
||||
"//dev-infra/pr",
|
||||
|
26
dev-infra/caretaker/BUILD.bazel
Normal file
26
dev-infra/caretaker/BUILD.bazel
Normal file
@ -0,0 +1,26 @@
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "caretaker",
|
||||
srcs = [
|
||||
"cli.ts",
|
||||
],
|
||||
module_name = "@angular/dev-infra-private/caretaker",
|
||||
visibility = ["//dev-infra:__subpackages__"],
|
||||
deps = [
|
||||
"//dev-infra/caretaker/check",
|
||||
"@npm//@types/yargs",
|
||||
"@npm//yargs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "config",
|
||||
srcs = [
|
||||
"config.ts",
|
||||
],
|
||||
visibility = ["//dev-infra:__subpackages__"],
|
||||
deps = [
|
||||
"//dev-infra/utils",
|
||||
],
|
||||
)
|
21
dev-infra/caretaker/check/BUILD.bazel
Normal file
21
dev-infra/caretaker/check/BUILD.bazel
Normal file
@ -0,0 +1,21 @@
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "check",
|
||||
srcs = glob(["*.ts"]),
|
||||
module_name = "@angular/dev-infra-private/caretaker/service-statuses",
|
||||
visibility = ["//dev-infra:__subpackages__"],
|
||||
deps = [
|
||||
"//dev-infra/caretaker:config",
|
||||
"//dev-infra/utils",
|
||||
"@npm//@types/fs-extra",
|
||||
"@npm//@types/node",
|
||||
"@npm//@types/node-fetch",
|
||||
"@npm//@types/yargs",
|
||||
"@npm//multimatch",
|
||||
"@npm//node-fetch",
|
||||
"@npm//typed-graphqlify",
|
||||
"@npm//yaml",
|
||||
"@npm//yargs",
|
||||
],
|
||||
)
|
27
dev-infra/caretaker/check/check.ts
Normal file
27
dev-infra/caretaker/check/check.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {GitClient} from '../../utils/git';
|
||||
import {getCaretakerConfig} from '../config';
|
||||
|
||||
import {printG3Comparison} from './g3';
|
||||
import {printGithubTasks} from './github';
|
||||
import {printServiceStatuses} from './services';
|
||||
|
||||
|
||||
/** Check the status of services which Angular caretakers need to monitor. */
|
||||
export async function checkServiceStatuses(githubToken: string) {
|
||||
/** The configuration for the caretaker commands. */
|
||||
const config = getCaretakerConfig();
|
||||
/** The GitClient for interacting with git and Github. */
|
||||
const git = new GitClient(githubToken, config);
|
||||
|
||||
await printServiceStatuses();
|
||||
await printGithubTasks(git, config.caretaker);
|
||||
await printG3Comparison(git);
|
||||
}
|
39
dev-infra/caretaker/check/cli.ts
Normal file
39
dev-infra/caretaker/check/cli.ts
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {Arguments, Argv, CommandModule} from 'yargs';
|
||||
|
||||
import {addGithubTokenFlag} from '../../utils/yargs';
|
||||
|
||||
import {checkServiceStatuses} from './check';
|
||||
|
||||
|
||||
export interface CaretakerCheckOptions {
|
||||
githubToken: string;
|
||||
}
|
||||
|
||||
/** URL to the Github page where personal access tokens can be generated. */
|
||||
export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`;
|
||||
|
||||
/** Builds the command. */
|
||||
function builder(yargs: Argv) {
|
||||
return addGithubTokenFlag(yargs);
|
||||
}
|
||||
|
||||
/** Handles the command. */
|
||||
async function handler({githubToken}: Arguments<CaretakerCheckOptions>) {
|
||||
await checkServiceStatuses(githubToken);
|
||||
}
|
||||
|
||||
/** yargs command module for checking status information for the repository */
|
||||
export const CheckModule: CommandModule<{}, CaretakerCheckOptions> = {
|
||||
handler,
|
||||
builder,
|
||||
command: 'check',
|
||||
describe: 'Check the status of information the caretaker manages for the repository',
|
||||
};
|
123
dev-infra/caretaker/check/g3.ts
Normal file
123
dev-infra/caretaker/check/g3.ts
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {existsSync, readFileSync} from 'fs-extra';
|
||||
import * as multimatch from 'multimatch';
|
||||
import {join} from 'path';
|
||||
import {parse as parseYaml} from 'yaml';
|
||||
|
||||
import {getRepoBaseDir} from '../../utils/config';
|
||||
import {bold, debug, info} from '../../utils/console';
|
||||
import {GitClient} from '../../utils/git';
|
||||
|
||||
/** Compare the upstream master to the upstream g3 branch, if it exists. */
|
||||
export async function printG3Comparison(git: GitClient) {
|
||||
const angularRobotFilePath = join(getRepoBaseDir(), '.github/angular-robot.yml');
|
||||
if (!existsSync(angularRobotFilePath)) {
|
||||
return debug('No angular robot configuration file exists, skipping.');
|
||||
}
|
||||
|
||||
/** The configuration defined for the angular robot. */
|
||||
const robotConfig = parseYaml(readFileSync(angularRobotFilePath).toString());
|
||||
/** The files to be included in the g3 sync. */
|
||||
const includeFiles = robotConfig?.merge?.g3Status?.include || [];
|
||||
/** The files to be expected in the g3 sync. */
|
||||
const excludeFiles = robotConfig?.merge?.g3Status?.exclude || [];
|
||||
|
||||
if (includeFiles.length === 0 && excludeFiles.length === 0) {
|
||||
debug('No g3Status include or exclude lists are defined in the angular robot configuration,');
|
||||
debug('skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
/** Random prefix to create unique branch names. */
|
||||
const randomPrefix = `prefix${Math.floor(Math.random() * 1000000)}`;
|
||||
/** Ref name of the temporary master branch. */
|
||||
const masterRef = `${randomPrefix}-master`;
|
||||
/** Ref name of the temporary g3 branch. */
|
||||
const g3Ref = `${randomPrefix}-g3`;
|
||||
/** Url of the ref for fetching master and g3 branches. */
|
||||
const refUrl = `https://github.com/${git.remoteConfig.owner}/${git.remoteConfig.name}.git`;
|
||||
/** The result fo the fetch command. */
|
||||
const fetchResult = git.runGraceful(['fetch', refUrl, `master:${masterRef}`, `g3:${g3Ref}`]);
|
||||
|
||||
// If the upstream repository does not have a g3 branch to compare to, skip the comparison.
|
||||
if (fetchResult.status !== 0) {
|
||||
if (fetchResult.stderr.includes(`couldn't find remote ref g3`)) {
|
||||
return debug('No g3 branch exists on upstream, skipping.');
|
||||
}
|
||||
throw Error('Fetch of master and g3 branches for comparison failed.');
|
||||
}
|
||||
|
||||
/** The statistical information about the git diff between master and g3. */
|
||||
const stats = getDiffStats(git);
|
||||
|
||||
// Delete the temporarily created mater and g3 branches.
|
||||
git.runGraceful(['branch', '-D', masterRef, g3Ref]);
|
||||
|
||||
info.group(bold('g3 branch check'));
|
||||
info(`${stats.commits} commits between g3 and master`);
|
||||
if (stats.files === 0) {
|
||||
info('✅ No sync is needed at this time');
|
||||
} else {
|
||||
info(`${stats.files} files changed, ${stats.insertions} insertions(+), ${
|
||||
stats.deletions} deletions(-) will be included in the next sync`);
|
||||
}
|
||||
info.groupEnd();
|
||||
info();
|
||||
|
||||
|
||||
/**
|
||||
* Get git diff stats between master and g3, for all files and filtered to only g3 affecting
|
||||
* files.
|
||||
*/
|
||||
function getDiffStats(git: GitClient) {
|
||||
/** The diff stats to be returned. */
|
||||
const stats = {
|
||||
insertions: 0,
|
||||
deletions: 0,
|
||||
files: 0,
|
||||
commits: 0,
|
||||
};
|
||||
|
||||
|
||||
// Determine the number of commits between master and g3 refs. */
|
||||
stats.commits = parseInt(git.run(['rev-list', '--count', `${g3Ref}..${masterRef}`]).stdout, 10);
|
||||
|
||||
// Get the numstat information between master and g3
|
||||
git.run(['diff', `${g3Ref}...${masterRef}`, '--numstat'])
|
||||
.stdout
|
||||
// Remove the extra space after git's output.
|
||||
.trim()
|
||||
// Split each line of git output into array
|
||||
.split('\n')
|
||||
// Split each line from the git output into components parts: insertions,
|
||||
// deletions and file name respectively
|
||||
.map(line => line.split('\t'))
|
||||
// Parse number value from the insertions and deletions values
|
||||
// Example raw line input:
|
||||
// 10\t5\tsrc/file/name.ts
|
||||
.map(line => [Number(line[0]), Number(line[1]), line[2]] as [number, number, string])
|
||||
// Add each line's value to the diff stats, and conditionally to the g3
|
||||
// stats as well if the file name is included in the files synced to g3.
|
||||
.forEach(([insertions, deletions, fileName]) => {
|
||||
if (checkMatchAgainstIncludeAndExclude(fileName, includeFiles, excludeFiles)) {
|
||||
stats.insertions += insertions;
|
||||
stats.deletions += deletions;
|
||||
stats.files += 1;
|
||||
}
|
||||
});
|
||||
return stats;
|
||||
}
|
||||
|
||||
/** Determine whether the file name passes both include and exclude checks. */
|
||||
function checkMatchAgainstIncludeAndExclude(
|
||||
file: string, includes: string[], excludes: string[]) {
|
||||
return multimatch(multimatch(file, includes), excludes, {flipNegate: true}).length !== 0;
|
||||
}
|
||||
}
|
56
dev-infra/caretaker/check/github.ts
Normal file
56
dev-infra/caretaker/check/github.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {alias, params, types} from 'typed-graphqlify';
|
||||
|
||||
import {bold, debug, info} from '../../utils/console';
|
||||
import {GitClient} from '../../utils/git';
|
||||
import {CaretakerConfig} from '../config';
|
||||
|
||||
|
||||
interface GithubInfoQuery {
|
||||
[key: string]: {
|
||||
issueCount: number,
|
||||
};
|
||||
}
|
||||
|
||||
/** Retrieve the number of matching issues for each github query. */
|
||||
export async function printGithubTasks(git: GitClient, config: CaretakerConfig) {
|
||||
if (!config.githubQueries?.length) {
|
||||
debug('No github queries defined in the configuration, skipping.');
|
||||
return;
|
||||
}
|
||||
info.group(bold('Github Tasks'));
|
||||
await getGithubInfo(git, config);
|
||||
info.groupEnd();
|
||||
info();
|
||||
}
|
||||
|
||||
/** Retrieve query match counts and log discovered counts to the console. */
|
||||
async function getGithubInfo(git: GitClient, {githubQueries: queries = []}: CaretakerConfig) {
|
||||
/** The query object for graphql. */
|
||||
const graphQlQuery: {[key: string]: {issueCount: number}} = {};
|
||||
/** The Github search filter for the configured repository. */
|
||||
const repoFilter = `repo:${git.remoteConfig.owner}/${git.remoteConfig.name}`;
|
||||
queries.forEach(({name, query}) => {
|
||||
/** The name of the query, with spaces removed to match GraphQL requirements. */
|
||||
const queryKey = alias(name.replace(/ /g, ''), 'search');
|
||||
graphQlQuery[queryKey] = params(
|
||||
{
|
||||
type: 'ISSUE',
|
||||
query: `"${repoFilter} ${query.replace(/"/g, '\\"')}"`,
|
||||
},
|
||||
{issueCount: types.number},
|
||||
);
|
||||
});
|
||||
/** The results of the generated github query. */
|
||||
const results = await git.github.graphql.query(graphQlQuery);
|
||||
Object.values(results).forEach((result, i) => {
|
||||
info(`${queries[i]?.name.padEnd(25)} ${result.issueCount}`);
|
||||
});
|
||||
}
|
79
dev-infra/caretaker/check/services.ts
Normal file
79
dev-infra/caretaker/check/services.ts
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 fetch from 'node-fetch';
|
||||
|
||||
import {bold, green, info, red} from '../../utils/console';
|
||||
|
||||
/** The status levels for services. */
|
||||
enum ServiceStatus {
|
||||
GREEN,
|
||||
RED
|
||||
}
|
||||
|
||||
/** The results of checking the status of a service */
|
||||
interface StatusCheckResult {
|
||||
status: ServiceStatus;
|
||||
description: string;
|
||||
lastUpdated: Date;
|
||||
}
|
||||
|
||||
/** Retrieve and log stasuses for all of the services of concern. */
|
||||
export async function printServiceStatuses() {
|
||||
info.group(bold(`Service Statuses (checked: ${new Date().toLocaleString()})`));
|
||||
logStatus('CircleCI', await getCircleCiStatus());
|
||||
logStatus('Github', await getGithubStatus());
|
||||
logStatus('NPM', await getNpmStatus());
|
||||
logStatus('Saucelabs', await getSaucelabsStatus());
|
||||
info.groupEnd();
|
||||
info();
|
||||
}
|
||||
|
||||
|
||||
/** Log the status of the service to the console. */
|
||||
function logStatus(serviceName: string, status: StatusCheckResult) {
|
||||
serviceName = serviceName.padEnd(15);
|
||||
if (status.status === ServiceStatus.GREEN) {
|
||||
info(`${serviceName} ${green('✅')}`);
|
||||
} else if (status.status === ServiceStatus.RED) {
|
||||
info.group(`${serviceName} ${red('❌')} (Updated: ${status.lastUpdated.toLocaleString()})`);
|
||||
info(` Details: ${status.description}`);
|
||||
info.groupEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the service status information for Saucelabs. */
|
||||
async function getSaucelabsStatus(): Promise<StatusCheckResult> {
|
||||
return getStatusFromStandardApi('https://status.us-west-1.saucelabs.com/api/v2/status.json');
|
||||
}
|
||||
|
||||
/** Gets the service status information for NPM. */
|
||||
async function getNpmStatus(): Promise<StatusCheckResult> {
|
||||
return getStatusFromStandardApi('https://status.npmjs.org/api/v2/status.json');
|
||||
}
|
||||
|
||||
/** Gets the service status information for CircleCI. */
|
||||
async function getCircleCiStatus(): Promise<StatusCheckResult> {
|
||||
return getStatusFromStandardApi('https://status.circleci.com/api/v2/status.json');
|
||||
}
|
||||
|
||||
/** Gets the service status information for Github. */
|
||||
async function getGithubStatus(): Promise<StatusCheckResult> {
|
||||
return getStatusFromStandardApi('https://www.githubstatus.com/api/v2/status.json');
|
||||
}
|
||||
|
||||
/** Retrieve the status information for a service which uses a standard API response. */
|
||||
async function getStatusFromStandardApi(url: string) {
|
||||
const result = await fetch(url).then(result => result.json());
|
||||
const status = result.status.indicator === 'none' ? ServiceStatus.GREEN : ServiceStatus.RED;
|
||||
return {
|
||||
status,
|
||||
description: result.status.description,
|
||||
lastUpdated: new Date(result.page.updated_at)
|
||||
};
|
||||
}
|
16
dev-infra/caretaker/cli.ts
Normal file
16
dev-infra/caretaker/cli.ts
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {Argv} from 'yargs';
|
||||
import {CheckModule} from './check/cli';
|
||||
|
||||
|
||||
/** Build the parser for the caretaker commands. */
|
||||
export function buildCaretakerParser(yargs: Argv) {
|
||||
return yargs.command(CheckModule);
|
||||
}
|
24
dev-infra/caretaker/config.ts
Normal file
24
dev-infra/caretaker/config.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {assertNoErrors, getConfig, NgDevConfig} from '../utils/config';
|
||||
|
||||
export interface CaretakerConfig {
|
||||
githubQueries?: {name: string; query: string;}[];
|
||||
}
|
||||
|
||||
/** Retrieve and validate the config as `CaretakerConfig`. */
|
||||
export function getCaretakerConfig() {
|
||||
// List of errors encountered validating the config.
|
||||
const errors: string[] = [];
|
||||
// The non-validated config object.
|
||||
const config: Partial<NgDevConfig<{caretaker: CaretakerConfig}>> = getConfig();
|
||||
|
||||
assertNoErrors(errors);
|
||||
return config as Required<typeof config>;
|
||||
}
|
@ -13,8 +13,11 @@ import {buildCommitMessageParser} from './commit-message/cli';
|
||||
import {buildFormatParser} from './format/cli';
|
||||
import {buildReleaseParser} from './release/cli';
|
||||
import {buildPrParser} from './pr/cli';
|
||||
import {captureLogOutputForCommand} from './utils/console';
|
||||
import {buildCaretakerParser} from './caretaker/cli';
|
||||
|
||||
yargs.scriptName('ng-dev')
|
||||
.middleware(captureLogOutputForCommand)
|
||||
.demandCommand()
|
||||
.recommendCommands()
|
||||
.command('commit-message <command>', '', buildCommitMessageParser)
|
||||
@ -23,6 +26,7 @@ yargs.scriptName('ng-dev')
|
||||
.command('pullapprove <command>', '', buildPullapproveParser)
|
||||
.command('release <command>', '', buildReleaseParser)
|
||||
.command('ts-circular-deps <command>', '', tsCircularDependenciesBuilder)
|
||||
.command('caretaker <command>', '', buildCaretakerParser)
|
||||
.wrap(120)
|
||||
.strict()
|
||||
.parse();
|
||||
|
@ -8,35 +8,21 @@
|
||||
|
||||
import {Arguments, Argv, CommandModule} from 'yargs';
|
||||
|
||||
import {error} from '../../utils/console';
|
||||
import {addGithubTokenFlag} from '../../utils/yargs';
|
||||
import {checkOutPullRequestLocally} from '../common/checkout-pr';
|
||||
|
||||
export interface CheckoutOptions {
|
||||
prNumber: number;
|
||||
'github-token'?: string;
|
||||
githubToken: string;
|
||||
}
|
||||
|
||||
/** URL to the Github page where personal access tokens can be generated. */
|
||||
export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`;
|
||||
|
||||
/** Builds the checkout pull request command. */
|
||||
function builder(yargs: Argv) {
|
||||
return yargs.positional('prNumber', {type: 'number', demandOption: true}).option('github-token', {
|
||||
type: 'string',
|
||||
description: 'Github token. If not set, token is retrieved from the environment variables.'
|
||||
});
|
||||
return addGithubTokenFlag(yargs).positional('prNumber', {type: 'number', demandOption: true});
|
||||
}
|
||||
|
||||
/** Handles the checkout pull request command. */
|
||||
async function handler({prNumber, 'github-token': token}: Arguments<CheckoutOptions>) {
|
||||
const githubToken = token || process.env.GITHUB_TOKEN || process.env.TOKEN;
|
||||
if (!githubToken) {
|
||||
error('No Github token set. Please set the `GITHUB_TOKEN` environment variable.');
|
||||
error('Alternatively, pass the `--github-token` command line flag.');
|
||||
error(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
async function handler({prNumber, githubToken}: Arguments<CheckoutOptions>) {
|
||||
const prCheckoutOptions = {allowIfMaintainerCannotModify: true, branchName: `pr-${prNumber}`};
|
||||
await checkOutPullRequestLocally(prNumber, githubToken, prCheckoutOptions);
|
||||
}
|
||||
|
@ -8,36 +8,24 @@
|
||||
|
||||
import {Arguments, Argv} from 'yargs';
|
||||
|
||||
import {error, red, yellow} from '../../utils/console';
|
||||
import {addGithubTokenFlag} from '../../utils/yargs';
|
||||
|
||||
import {GITHUB_TOKEN_GENERATE_URL, mergePullRequest} from './index';
|
||||
import {mergePullRequest} from './index';
|
||||
|
||||
/** The options available to the merge command via CLI. */
|
||||
export interface MergeCommandOptions {
|
||||
'github-token'?: string;
|
||||
githubToken: string;
|
||||
'pr-number': number;
|
||||
}
|
||||
|
||||
/** Builds the options for the merge command. */
|
||||
export function buildMergeCommand(yargs: Argv): Argv<MergeCommandOptions> {
|
||||
return yargs.help()
|
||||
.strict()
|
||||
.positional('pr-number', {demandOption: true, type: 'number'})
|
||||
.option('github-token', {
|
||||
type: 'string',
|
||||
description: 'Github token. If not set, token is retrieved from the environment variables.'
|
||||
});
|
||||
return addGithubTokenFlag(yargs).help().strict().positional(
|
||||
'pr-number', {demandOption: true, type: 'number'});
|
||||
}
|
||||
|
||||
/** Handles the merge command. i.e. performs the merge of a specified pull request. */
|
||||
export async function handleMergeCommand(args: Arguments<MergeCommandOptions>) {
|
||||
const githubToken = args['github-token'] || process.env.GITHUB_TOKEN || process.env.TOKEN;
|
||||
if (!githubToken) {
|
||||
error(red('No Github token set. Please set the `GITHUB_TOKEN` environment variable.'));
|
||||
error(red('Alternatively, pass the `--github-token` command line flag.'));
|
||||
error(yellow(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await mergePullRequest(args['pr-number'], githubToken);
|
||||
export async function handleMergeCommand(
|
||||
{'pr-number': pr, githubToken}: Arguments<MergeCommandOptions>) {
|
||||
await mergePullRequest(pr, githubToken);
|
||||
}
|
||||
|
@ -165,6 +165,11 @@ export async function findActiveVersionBranches(
|
||||
latestVersionBranch: string | null,
|
||||
releaseCandidateBranch: string | null,
|
||||
}> {
|
||||
// Version representing the release-train currently in the next phase. Note that we ignore
|
||||
// patch and pre-release segments in order to be able to compare the next release train to
|
||||
// other release trains from version branches (which follow the `N.N.x` pattern).
|
||||
const nextReleaseTrainVersion = semver.parse(`${nextVersion.major}.${nextVersion.minor}.0`)!;
|
||||
|
||||
let latestVersionBranch: string|null = null;
|
||||
let releaseCandidateBranch: string|null = null;
|
||||
|
||||
@ -177,15 +182,21 @@ export async function findActiveVersionBranches(
|
||||
// next version-branch as that one is supposed to be the latest active version-branch. If it
|
||||
// is not, then an error will be thrown due to two FF/RC branches existing at the same time.
|
||||
for (const {name, parsed} of branches) {
|
||||
// It can happen that version branches that are more recent than the version in the next
|
||||
// branch (i.e. `master`) have been created. We could ignore such branches silently, but
|
||||
// it might actually be symptomatic for an outdated version in the `next` branch, or an
|
||||
// It can happen that version branches have been accidentally created which are more recent
|
||||
// than the release-train in the next branch (i.e. `master`). We could ignore such branches
|
||||
// silently, but it might be symptomatic for an outdated version in the `next` branch, or an
|
||||
// accidentally created branch by the caretaker. In either way we want to raise awareness.
|
||||
if (semver.gte(parsed, nextVersion)) {
|
||||
if (semver.gt(parsed, nextReleaseTrainVersion)) {
|
||||
throw Error(
|
||||
`Discovered unexpected version-branch that is representing a minor ` +
|
||||
`version more recent than the one in the "${nextBranchName}" branch. Consider ` +
|
||||
`deleting the branch, or check if the version in "${nextBranchName}" is outdated.`);
|
||||
`Discovered unexpected version-branch "${name}" for a release-train that is ` +
|
||||
`more recent than the release-train currently in the "${nextBranchName}" branch. ` +
|
||||
`Please either delete the branch if created by accident, or update the outdated ` +
|
||||
`version in the next branch (${nextBranchName}).`);
|
||||
} else if (semver.eq(parsed, nextReleaseTrainVersion)) {
|
||||
throw Error(
|
||||
`Discovered unexpected version-branch "${name}" for a release-train that is already ` +
|
||||
`active in the "${nextBranchName}" branch. Please either delete the branch if ` +
|
||||
`created by accident, or update the version in the next branch (${nextBranchName}).`);
|
||||
}
|
||||
|
||||
const version = await getVersionOfBranch(repo, name);
|
||||
|
@ -280,7 +280,21 @@ describe('default target labels', () => {
|
||||
.toBeRejectedWithError('Invalid version detected in following branch: 11.1.x.');
|
||||
});
|
||||
|
||||
it('should error if branch more recent than version in "next" branch is found', async () => {
|
||||
it('should error if version-branch more recent than "next" is discovered', async () => {
|
||||
interceptBranchVersionRequest('master', '11.2.0-next.0');
|
||||
interceptBranchVersionRequest('11.3.x', '11.3.0-next.0');
|
||||
interceptBranchVersionRequest('11.1.x', '11.1.5');
|
||||
interceptBranchesListRequest(['11.1.x', '11.3.x']);
|
||||
|
||||
await expectAsync(getBranchesForLabel('target: lts', '10.2.x'))
|
||||
.toBeRejectedWithError(
|
||||
'Discovered unexpected version-branch "11.3.x" for a release-train that is ' +
|
||||
'more recent than the release-train currently in the "master" branch. Please ' +
|
||||
'either delete the branch if created by accident, or update the outdated version ' +
|
||||
'in the next branch (master).');
|
||||
});
|
||||
|
||||
it('should error if branch is matching with release-train in the "next" branch', async () => {
|
||||
interceptBranchVersionRequest('master', '11.2.0-next.0');
|
||||
interceptBranchVersionRequest('11.2.x', '11.2.0-next.0');
|
||||
interceptBranchVersionRequest('11.1.x', '11.1.5');
|
||||
@ -288,9 +302,9 @@ describe('default target labels', () => {
|
||||
|
||||
await expectAsync(getBranchesForLabel('target: lts', '10.2.x'))
|
||||
.toBeRejectedWithError(
|
||||
'Discovered unexpected version-branch that is representing a minor version more ' +
|
||||
'recent than the one in the "master" branch. Consider deleting the branch, or check ' +
|
||||
'if the version in "master" is outdated.');
|
||||
'Discovered unexpected version-branch "11.2.x" for a release-train that is already ' +
|
||||
'active in the "master" branch. Please either delete the branch if created by ' +
|
||||
'accident, or update the version in the next branch (master).');
|
||||
});
|
||||
|
||||
it('should allow merging PR only into patch branch with "target: patch"', async () => {
|
||||
|
@ -11,13 +11,11 @@ import {getConfig, getRepoBaseDir} from '../../utils/config';
|
||||
import {error, green, info, promptConfirm, red, yellow} from '../../utils/console';
|
||||
import {GitClient} from '../../utils/git';
|
||||
import {GithubApiRequestError} from '../../utils/git/github';
|
||||
import {GITHUB_TOKEN_GENERATE_URL} from '../../utils/yargs';
|
||||
|
||||
import {loadAndValidateConfig, MergeConfig, MergeConfigWithRemote} from './config';
|
||||
import {loadAndValidateConfig, MergeConfigWithRemote} from './config';
|
||||
import {MergeResult, MergeStatus, PullRequestMergeTask} from './task';
|
||||
|
||||
/** URL to the Github page where personal access tokens can be generated. */
|
||||
export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`;
|
||||
|
||||
|
||||
/**
|
||||
* Merges a given pull request based on labels configured in the given merge configuration.
|
||||
|
@ -8,39 +8,23 @@
|
||||
|
||||
import {Arguments, Argv} from 'yargs';
|
||||
|
||||
import {error} from '../../utils/console';
|
||||
import {addGithubTokenFlag} from '../../utils/yargs';
|
||||
|
||||
import {rebasePr} from './index';
|
||||
|
||||
/** URL to the Github page where personal access tokens can be generated. */
|
||||
export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`;
|
||||
|
||||
/** The options available to the rebase command via CLI. */
|
||||
export interface RebaseCommandOptions {
|
||||
'github-token'?: string;
|
||||
githubToken: string;
|
||||
prNumber: number;
|
||||
}
|
||||
|
||||
/** Builds the rebase pull request command. */
|
||||
export function buildRebaseCommand(yargs: Argv): Argv<RebaseCommandOptions> {
|
||||
return yargs
|
||||
.option('github-token', {
|
||||
type: 'string',
|
||||
description: 'Github token. If not set, token is retrieved from the environment variables.'
|
||||
})
|
||||
.positional('prNumber', {type: 'number', demandOption: true});
|
||||
return addGithubTokenFlag(yargs).positional('prNumber', {type: 'number', demandOption: true});
|
||||
}
|
||||
|
||||
|
||||
/** Handles the rebase pull request command. */
|
||||
export async function handleRebaseCommand(args: Arguments<RebaseCommandOptions>) {
|
||||
const githubToken = args['github-token'] || process.env.GITHUB_TOKEN || process.env.TOKEN;
|
||||
if (!githubToken) {
|
||||
error('No Github token set. Please set the `GITHUB_TOKEN` environment variable.');
|
||||
error('Alternatively, pass the `--github-token` command line flag.');
|
||||
error(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await rebasePr(args.prNumber, githubToken);
|
||||
export async function handleRebaseCommand(
|
||||
{prNumber, githubToken}: Arguments<RebaseCommandOptions>) {
|
||||
await rebasePr(prNumber, githubToken);
|
||||
}
|
||||
|
@ -12,14 +12,18 @@ ts_library(
|
||||
"@npm//@octokit/graphql",
|
||||
"@npm//@octokit/rest",
|
||||
"@npm//@octokit/types",
|
||||
"@npm//@types/fs-extra",
|
||||
"@npm//@types/inquirer",
|
||||
"@npm//@types/node",
|
||||
"@npm//@types/shelljs",
|
||||
"@npm//@types/yargs",
|
||||
"@npm//chalk",
|
||||
"@npm//fs-extra",
|
||||
"@npm//inquirer",
|
||||
"@npm//inquirer-autocomplete-prompt",
|
||||
"@npm//shelljs",
|
||||
"@npm//tslib",
|
||||
"@npm//typed-graphqlify",
|
||||
"@npm//yargs",
|
||||
],
|
||||
)
|
||||
|
@ -7,14 +7,19 @@
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import {writeFileSync} from 'fs-extra';
|
||||
import {createPromptModule, ListChoiceOptions, prompt} from 'inquirer';
|
||||
import * as inquirerAutocomplete from 'inquirer-autocomplete-prompt';
|
||||
import {join} from 'path';
|
||||
import {Arguments} from 'yargs';
|
||||
|
||||
import {getRepoBaseDir} from './config';
|
||||
|
||||
/** Reexport of chalk colors for convenient access. */
|
||||
export const red: typeof chalk = chalk.red;
|
||||
export const green: typeof chalk = chalk.green;
|
||||
export const yellow: typeof chalk = chalk.yellow;
|
||||
export const bold: typeof chalk = chalk.bold;
|
||||
|
||||
/** Prompts the user with a confirmation question and a specified message. */
|
||||
export async function promptConfirm(message: string, defaultValue = false): Promise<boolean> {
|
||||
@ -140,6 +145,7 @@ function runConsoleCommand(loadCommand: () => Function, logLevel: LOG_LEVELS, ..
|
||||
if (getLogLevel() >= logLevel) {
|
||||
loadCommand()(...text);
|
||||
}
|
||||
printToLogFile(logLevel, ...text);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,3 +161,56 @@ function getLogLevel() {
|
||||
}
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
/** All text to write to the log file. */
|
||||
let LOGGED_TEXT = '';
|
||||
/** Whether file logging as been enabled. */
|
||||
let FILE_LOGGING_ENABLED = false;
|
||||
/**
|
||||
* The number of columns used in the prepended log level information on each line of the logging
|
||||
* output file.
|
||||
*/
|
||||
const LOG_LEVEL_COLUMNS = 7;
|
||||
|
||||
/**
|
||||
* Enable writing the logged outputs to the log file on process exit, sets initial lines from the
|
||||
* command execution, containing information about the timing and command parameters.
|
||||
*
|
||||
* This is expected to be called only once during a command run, and should be called by the
|
||||
* middleware of yargs to enable the file logging before the rest of the command parsing and
|
||||
* response is executed.
|
||||
*/
|
||||
export function captureLogOutputForCommand(argv: Arguments) {
|
||||
if (FILE_LOGGING_ENABLED) {
|
||||
throw Error('`captureLogOutputForCommand` cannot be called multiple times');
|
||||
}
|
||||
/** The date time used for timestamping when the command was invoked. */
|
||||
const now = new Date();
|
||||
/** Header line to separate command runs in log files. */
|
||||
const headerLine = Array(100).fill('#').join('');
|
||||
LOGGED_TEXT += `${headerLine}\nCommand: ${argv.$0} ${argv._.join(' ')}\nRan at: ${now}\n`;
|
||||
|
||||
// On process exit, write the logged output to the appropriate log files
|
||||
process.on('exit', (code: number) => {
|
||||
LOGGED_TEXT += `Command ran in ${new Date().getTime() - now.getTime()}ms`;
|
||||
/** Path to the log file location. */
|
||||
const logFilePath = join(getRepoBaseDir(), '.ng-dev.log');
|
||||
|
||||
writeFileSync(logFilePath, LOGGED_TEXT);
|
||||
|
||||
// For failure codes greater than 1, the new logged lines should be written to a specific log
|
||||
// file for the command run failure.
|
||||
if (code > 1) {
|
||||
writeFileSync(join(getRepoBaseDir(), `.ng-dev.err-${now.getTime()}.log`), LOGGED_TEXT);
|
||||
}
|
||||
});
|
||||
|
||||
// Mark file logging as enabled to prevent the function from executing multiple times.
|
||||
FILE_LOGGING_ENABLED = true;
|
||||
}
|
||||
|
||||
/** Write the provided text to the log file, prepending each line with the log level. */
|
||||
function printToLogFile(logLevel: LOG_LEVELS, ...text: string[]) {
|
||||
const logLevelText = `${LOG_LEVELS[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS);
|
||||
LOGGED_TEXT += text.join(' ').split('\n').map(l => `${logLevelText} ${l}\n`).join('');
|
||||
}
|
||||
|
@ -86,10 +86,10 @@ export class GitClient {
|
||||
/**
|
||||
* Spawns a given Git command process. Does not throw if the command fails. Additionally,
|
||||
* if there is any stderr output, the output will be printed. This makes it easier to
|
||||
* debug failed commands.
|
||||
* info failed commands.
|
||||
*/
|
||||
runGraceful(args: string[], options: SpawnSyncOptions = {}): SpawnSyncReturns<string> {
|
||||
// To improve the debugging experience in case something fails, we print all executed
|
||||
// To improve the infoging experience in case something fails, we print all executed
|
||||
// Git commands. Note that we do not want to print the token if is contained in the
|
||||
// command. It's common to share errors with others if the tool failed.
|
||||
info('Executing: git', this.omitGithubTokenFromMessage(args.join(' ')));
|
||||
|
37
dev-infra/utils/yargs.ts
Normal file
37
dev-infra/utils/yargs.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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 {Argv} from 'yargs';
|
||||
import {error, red, yellow} from './console';
|
||||
|
||||
export type ArgvWithGithubToken = Argv<{githubToken: string}>;
|
||||
|
||||
export function addGithubTokenFlag(yargs: Argv): ArgvWithGithubToken {
|
||||
return yargs
|
||||
// 'github-token' is casted to 'githubToken' to properly set up typings to reflect the key in
|
||||
// the Argv object being camelCase rather than kebob case due to the `camel-case-expansion`
|
||||
// config: https://github.com/yargs/yargs-parser#camel-case-expansion
|
||||
.option('github-token' as 'githubToken', {
|
||||
type: 'string',
|
||||
description: 'Github token. If not set, token is retrieved from the environment variables.',
|
||||
coerce: (token: string) => {
|
||||
const githubToken = token || process.env.GITHUB_TOKEN || process.env.TOKEN;
|
||||
if (!githubToken) {
|
||||
error(red('No Github token set. Please set the `GITHUB_TOKEN` environment variable.'));
|
||||
error(red('Alternatively, pass the `--github-token` command line flag.'));
|
||||
error(yellow(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`));
|
||||
process.exit(1);
|
||||
}
|
||||
return githubToken;
|
||||
},
|
||||
})
|
||||
.default('github-token' as 'githubToken', '', '<LOCAL TOKEN>');
|
||||
}
|
||||
|
||||
/** URL to the Github page where personal access tokens can be generated. */
|
||||
export const GITHUB_TOKEN_GENERATE_URL = 'https://github.com/settings/tokens/new';
|
@ -15,6 +15,6 @@ export class AppComponent {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
time$: Observable<string> =
|
||||
this.http.get('http://worldclockapi.com/api/json/pst/now')
|
||||
.pipe(map((result: any) => result.currentDateTime), startWith(['...']));
|
||||
this.http.get('http://worldtimeapi.org/api/timezone/America/Los_Angeles.json')
|
||||
.pipe(map((result: any) => result.datetime), startWith(['...']));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "10.1.0-rc.0",
|
||||
"version": "10.1.0",
|
||||
"private": true,
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
"homepage": "https://github.com/angular/angular",
|
||||
@ -81,13 +81,14 @@
|
||||
"@types/jasmine-ajax": "^3.3.1",
|
||||
"@types/jasminewd2": "^2.0.8",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/multimatch": "^4.0.0",
|
||||
"@types/node": "^12.11.1",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/selenium-webdriver": "3.0.7",
|
||||
"@types/semver": "^6.0.2",
|
||||
"@types/shelljs": "^0.8.6",
|
||||
"@types/systemjs": "0.19.32",
|
||||
"@types/yaml": "^1.2.0",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"@types/yargs": "^15.0.5",
|
||||
"@webcomponents/custom-elements": "^1.1.0",
|
||||
"angular": "npm:angular@1.7",
|
||||
@ -152,7 +153,7 @@
|
||||
"tslint": "6.1.3",
|
||||
"typescript": "~4.0.2",
|
||||
"xhr2": "0.2.0",
|
||||
"yaml": "^1.7.2",
|
||||
"yaml": "^1.10.0",
|
||||
"yargs": "^15.4.1"
|
||||
},
|
||||
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
|
||||
|
@ -2017,6 +2017,28 @@ export declare class AnimationEvent {
|
||||
expect(diags.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should allow HTML elements without explicit namespace inside SVG foreignObject', () => {
|
||||
env.write('test.ts', `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
@Component({
|
||||
template: \`
|
||||
<svg>
|
||||
<foreignObject>
|
||||
<div>Hello</div>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
\`,
|
||||
})
|
||||
export class FooCmp {}
|
||||
@NgModule({
|
||||
declarations: [FooCmp],
|
||||
})
|
||||
export class FooModule {}
|
||||
`);
|
||||
const diags = env.driveDiagnostics();
|
||||
expect(diags.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should check for unknown elements inside an SVG foreignObject', () => {
|
||||
env.write('test.ts', `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
@ -2042,6 +2064,33 @@ export declare class AnimationEvent {
|
||||
1. If 'foo' is an Angular component, then verify that it is part of this module.
|
||||
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`);
|
||||
});
|
||||
|
||||
it('should check for unknown elements without explicit namespace inside an SVG foreignObject',
|
||||
() => {
|
||||
env.write('test.ts', `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
@Component({
|
||||
selector: 'blah',
|
||||
template: \`
|
||||
<svg>
|
||||
<foreignObject>
|
||||
<foo>Hello</foo>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
\`,
|
||||
})
|
||||
export class FooCmp {}
|
||||
@NgModule({
|
||||
declarations: [FooCmp],
|
||||
})
|
||||
export class FooModule {}
|
||||
`);
|
||||
const diags = env.driveDiagnostics();
|
||||
expect(diags.length).toBe(1);
|
||||
expect(diags[0].messageText).toBe(`'foo' is not a known element:
|
||||
1. If 'foo' is an Angular component, then verify that it is part of this module.
|
||||
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`);
|
||||
});
|
||||
});
|
||||
|
||||
// Test both sync and async compilations, see https://github.com/angular/angular/issues/32538
|
||||
|
@ -17,6 +17,7 @@ export class HtmlTagDefinition implements TagDefinition {
|
||||
isVoid: boolean;
|
||||
ignoreFirstLf: boolean;
|
||||
canSelfClose: boolean = false;
|
||||
preventNamespaceInheritance: boolean;
|
||||
|
||||
constructor({
|
||||
closedByChildren,
|
||||
@ -24,14 +25,16 @@ export class HtmlTagDefinition implements TagDefinition {
|
||||
contentType = TagContentType.PARSABLE_DATA,
|
||||
closedByParent = false,
|
||||
isVoid = false,
|
||||
ignoreFirstLf = false
|
||||
ignoreFirstLf = false,
|
||||
preventNamespaceInheritance = false
|
||||
}: {
|
||||
closedByChildren?: string[],
|
||||
closedByParent?: boolean,
|
||||
implicitNamespacePrefix?: string,
|
||||
contentType?: TagContentType,
|
||||
isVoid?: boolean,
|
||||
ignoreFirstLf?: boolean
|
||||
ignoreFirstLf?: boolean,
|
||||
preventNamespaceInheritance?: boolean
|
||||
} = {}) {
|
||||
if (closedByChildren && closedByChildren.length > 0) {
|
||||
closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true);
|
||||
@ -41,6 +44,7 @@ export class HtmlTagDefinition implements TagDefinition {
|
||||
this.implicitNamespacePrefix = implicitNamespacePrefix || null;
|
||||
this.contentType = contentType;
|
||||
this.ignoreFirstLf = ignoreFirstLf;
|
||||
this.preventNamespaceInheritance = preventNamespaceInheritance;
|
||||
}
|
||||
|
||||
isClosedByChild(name: string): boolean {
|
||||
@ -88,6 +92,17 @@ export function getHtmlTagDefinition(tagName: string): HtmlTagDefinition {
|
||||
'th': new HtmlTagDefinition({closedByChildren: ['td', 'th'], closedByParent: true}),
|
||||
'col': new HtmlTagDefinition({isVoid: true}),
|
||||
'svg': new HtmlTagDefinition({implicitNamespacePrefix: 'svg'}),
|
||||
'foreignObject': new HtmlTagDefinition({
|
||||
// Usually the implicit namespace here would be redundant since it will be inherited from
|
||||
// the parent `svg`, but we have to do it for `foreignObject`, because the way the parser
|
||||
// works is that the parent node of an end tag is its own start tag which means that
|
||||
// the `preventNamespaceInheritance` on `foreignObject` would have it default to the
|
||||
// implicit namespace which is `html`, unless specified otherwise.
|
||||
implicitNamespacePrefix: 'svg',
|
||||
// We want to prevent children of foreignObject from inheriting its namespace, because
|
||||
// the point of the element is to allow nodes from other namespaces to be inserted.
|
||||
preventNamespaceInheritance: true,
|
||||
}),
|
||||
'math': new HtmlTagDefinition({implicitNamespacePrefix: 'math'}),
|
||||
'li': new HtmlTagDefinition({closedByChildren: ['li'], closedByParent: true}),
|
||||
'dt': new HtmlTagDefinition({closedByChildren: ['dt', 'dd']}),
|
||||
@ -111,5 +126,8 @@ export function getHtmlTagDefinition(tagName: string): HtmlTagDefinition {
|
||||
{contentType: TagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true}),
|
||||
};
|
||||
}
|
||||
return TAG_DEFINITIONS[tagName.toLowerCase()] || _DEFAULT_TAG_DEFINITION;
|
||||
// We have to make both a case-sensitive and a case-insesitive lookup, because
|
||||
// HTML tag names are case insensitive, whereas some SVG tags are case sensitive.
|
||||
return TAG_DEFINITIONS[tagName] ?? TAG_DEFINITIONS[tagName.toLowerCase()] ??
|
||||
_DEFAULT_TAG_DEFINITION;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {ParseError, ParseSourceSpan} from '../parse_util';
|
||||
|
||||
import * as html from './ast';
|
||||
import * as lex from './lexer';
|
||||
import {getNsPrefix, isNgContainer, mergeNsAndName, TagDefinition} from './tags';
|
||||
import {getNsPrefix, mergeNsAndName, splitNsName, TagDefinition} from './tags';
|
||||
|
||||
export class TreeError extends ParseError {
|
||||
static create(elementName: string|null, span: ParseSourceSpan, msg: string): TreeError {
|
||||
@ -353,7 +353,11 @@ class _TreeBuilder {
|
||||
if (prefix === '') {
|
||||
prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
|
||||
if (prefix === '' && parentElement != null) {
|
||||
prefix = getNsPrefix(parentElement.name);
|
||||
const parentTagName = splitNsName(parentElement.name)[1];
|
||||
const parentTagDefinition = this.getTagDefinition(parentTagName);
|
||||
if (!parentTagDefinition.preventNamespaceInheritance) {
|
||||
prefix = getNsPrefix(parentElement.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ export interface TagDefinition {
|
||||
isVoid: boolean;
|
||||
ignoreFirstLf: boolean;
|
||||
canSelfClose: boolean;
|
||||
preventNamespaceInheritance: boolean;
|
||||
|
||||
isClosedByChild(name: string): boolean;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ export class XmlTagDefinition implements TagDefinition {
|
||||
isVoid: boolean = false;
|
||||
ignoreFirstLf: boolean = false;
|
||||
canSelfClose: boolean = true;
|
||||
preventNamespaceInheritance: boolean = false;
|
||||
|
||||
requireExtraParent(currentParent: string): boolean {
|
||||
return false;
|
||||
|
@ -52,23 +52,17 @@ export class AbstractFormGroupDirective extends ControlContainer implements OnIn
|
||||
// TODO(issue/24571): remove '!'.
|
||||
_asyncValidators!: any[];
|
||||
|
||||
/**
|
||||
* @description
|
||||
* An internal callback method triggered on the instance after the inputs are set.
|
||||
* Registers the group with its parent group.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnInit(): void {
|
||||
this._checkParentType();
|
||||
// Register the group with its parent group.
|
||||
this.formDirective!.addFormGroup(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* An internal callback method triggered before the instance is destroyed.
|
||||
* Removes the group from its parent group.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
if (this.formDirective) {
|
||||
// Remove the group from its parent group.
|
||||
this.formDirective.removeFormGroup(this);
|
||||
}
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ export const CHECKBOX_VALUE_ACCESSOR: any = {
|
||||
})
|
||||
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -62,28 +62,23 @@ export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "checked" property on the input element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (_: any) => {}): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => {}): void {
|
||||
this.onTouched = fn;
|
||||
@ -91,8 +86,7 @@ export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
|
@ -75,14 +75,14 @@ export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionE
|
||||
})
|
||||
export class DefaultValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when an input event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -99,8 +99,7 @@ export class DefaultValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "value" property on the input element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
const normalizedValue = value == null ? '' : value;
|
||||
@ -108,20 +107,16 @@ export class DefaultValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (_: any) => void): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => void): void {
|
||||
this.onTouched = fn;
|
||||
@ -129,8 +124,7 @@ export class DefaultValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
|
@ -137,10 +137,7 @@ export class NgForm extends ControlContainer implements Form, AfterViewInit {
|
||||
new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called after the view is initialized. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngAfterViewInit() {
|
||||
this._setUpdateStrategy();
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ export class NgModel extends NgControl implements OnChanges, OnDestroy {
|
||||
_registered = false;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Internal reference to the view model value.
|
||||
* @nodoc
|
||||
*/
|
||||
viewModel: any;
|
||||
|
||||
@ -213,13 +213,7 @@ export class NgModel extends NgControl implements OnChanges, OnDestroy {
|
||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use
|
||||
* only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this._checkForErrors();
|
||||
if (!this._registered) this._setUpControl();
|
||||
@ -233,11 +227,7 @@ export class NgModel extends NgControl implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called before the directive's instance is destroyed. For internal
|
||||
* use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
this.formDirective && this.formDirective.removeControl(this);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export const NUMBER_VALUE_ACCESSOR: any = {
|
||||
/**
|
||||
* @description
|
||||
* The `ControlValueAccessor` for writing a number value and listening to number input changes.
|
||||
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
|
||||
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
|
||||
* directives.
|
||||
*
|
||||
* @usageNotes
|
||||
@ -48,15 +48,15 @@ export const NUMBER_VALUE_ACCESSOR: any = {
|
||||
})
|
||||
export class NumberValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change or input event occurs on the input
|
||||
* element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -64,8 +64,7 @@ export class NumberValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "value" property on the input element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: number): void {
|
||||
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
|
||||
@ -74,10 +73,8 @@ export class NumberValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (_: number|null) => void): void {
|
||||
this.onChange = (value) => {
|
||||
@ -86,10 +83,8 @@ export class NumberValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => void): void {
|
||||
this.onTouched = fn;
|
||||
@ -97,8 +92,7 @@ export class NumberValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
|
@ -112,14 +112,14 @@ export class RadioControlValueAccessor implements ControlValueAccessor, OnDestro
|
||||
_fn!: Function;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = () => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -148,29 +148,21 @@ export class RadioControlValueAccessor implements ControlValueAccessor, OnDestro
|
||||
private _renderer: Renderer2, private _elementRef: ElementRef,
|
||||
private _registry: RadioControlRegistry, private _injector: Injector) {}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive is initialized. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnInit(): void {
|
||||
this._control = this._injector.get(NgControl);
|
||||
this._checkName();
|
||||
this._registry.add(this._control, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
this._registry.remove(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Sets the "checked" property value on the radio input element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
this._state = value === this.value;
|
||||
@ -178,10 +170,8 @@ export class RadioControlValueAccessor implements ControlValueAccessor, OnDestro
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (_: any) => {}): void {
|
||||
this._fn = fn;
|
||||
@ -201,10 +191,8 @@ export class RadioControlValueAccessor implements ControlValueAccessor, OnDestro
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => {}): void {
|
||||
this.onTouched = fn;
|
||||
@ -212,8 +200,7 @@ export class RadioControlValueAccessor implements ControlValueAccessor, OnDestro
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
|
@ -52,15 +52,15 @@ export const RANGE_VALUE_ACCESSOR: StaticProvider = {
|
||||
})
|
||||
export class RangeValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change or input event occurs on the input
|
||||
* element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -68,18 +68,15 @@ export class RangeValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "value" property on the input element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'value', parseFloat(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (_: number|null) => void): void {
|
||||
this.onChange = (value) => {
|
||||
@ -88,10 +85,8 @@ export class RangeValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => void): void {
|
||||
this.onTouched = fn;
|
||||
@ -99,8 +94,7 @@ export class RangeValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the range input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
|
@ -54,8 +54,8 @@ export const formControlBinding: any = {
|
||||
|
||||
export class FormControlDirective extends NgControl implements OnChanges {
|
||||
/**
|
||||
* @description
|
||||
* Internal reference to the view model value.
|
||||
* @nodoc
|
||||
*/
|
||||
viewModel: any;
|
||||
|
||||
@ -116,13 +116,7 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use
|
||||
* only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (this._isControlChanged(changes)) {
|
||||
setUpControl(this.form, this);
|
||||
|
@ -65,7 +65,6 @@ export const controlNameBinding: any = {
|
||||
export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||
private _added = false;
|
||||
/**
|
||||
* @description
|
||||
* Internal reference to the view model value.
|
||||
* @internal
|
||||
*/
|
||||
@ -142,12 +141,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (!this._added) this._setUpControl();
|
||||
if (isPropertyUpdated(changes, this.viewModel)) {
|
||||
@ -157,10 +151,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
if (this.formDirective) {
|
||||
this.formDirective.removeControl(this);
|
||||
|
@ -86,12 +86,7 @@ export class FormGroupDirective extends ControlContainer implements Form, OnChan
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this._checkFormPresent();
|
||||
if (changes.hasOwnProperty('form')) {
|
||||
|
@ -165,10 +165,9 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs are initialized. For internal use only.
|
||||
*
|
||||
* @throws If the directive does not have a valid parent.
|
||||
* @nodoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this._checkParentType();
|
||||
@ -176,8 +175,8 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||
* @nodoc
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
if (this.formDirective) {
|
||||
|
@ -90,21 +90,24 @@ function _extractId(valueString: string): string {
|
||||
providers: [SELECT_VALUE_ACCESSOR]
|
||||
})
|
||||
export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
/** @nodoc */
|
||||
value: any;
|
||||
|
||||
/** @internal */
|
||||
_optionMap: Map<string, any> = new Map<string, any>();
|
||||
|
||||
/** @internal */
|
||||
_idCounter: number = 0;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -128,8 +131,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* Sets the "value" property on the input element. The "selectedIndex"
|
||||
* property is also set if an ID is provided on the option element.
|
||||
*
|
||||
* @param value The checked value
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
this.value = value;
|
||||
@ -142,10 +144,8 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (value: any) => any): void {
|
||||
this.onChange = (valueString: string) => {
|
||||
@ -155,10 +155,8 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => any): void {
|
||||
this.onTouched = fn;
|
||||
@ -166,8 +164,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the select input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
@ -247,10 +244,7 @@ export class NgSelectOption implements OnDestroy {
|
||||
this._renderer.setProperty(this._element.nativeElement, 'value', value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
if (this._select) {
|
||||
this._select._optionMap.delete(this.id);
|
||||
|
@ -83,25 +83,26 @@ abstract class HTMLCollection {
|
||||
})
|
||||
export class SelectMultipleControlValueAccessor implements ControlValueAccessor {
|
||||
/**
|
||||
* @description
|
||||
* The current value
|
||||
* The current value.
|
||||
* @nodoc
|
||||
*/
|
||||
value: any;
|
||||
|
||||
/** @internal */
|
||||
_optionMap: Map<string, ɵNgSelectMultipleOption> = new Map<string, ɵNgSelectMultipleOption>();
|
||||
|
||||
/** @internal */
|
||||
_idCounter: number = 0;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a change event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onChange = (_: any) => {};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The registered callback function called when a blur event occurs on the input element.
|
||||
* @nodoc
|
||||
*/
|
||||
onTouched = () => {};
|
||||
|
||||
@ -123,11 +124,8 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Sets the "value" property on one or of more
|
||||
* of the select's options.
|
||||
*
|
||||
* @param value The value
|
||||
* Sets the "value" property on one or of more of the select's options.
|
||||
* @nodoc
|
||||
*/
|
||||
writeValue(value: any): void {
|
||||
this.value = value;
|
||||
@ -147,11 +145,9 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control value changes
|
||||
* and writes an array of the selected options.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnChange(fn: (value: any) => any): void {
|
||||
this.onChange = (_: any) => {
|
||||
@ -181,10 +177,8 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a function called when the control is touched.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnTouched(fn: () => any): void {
|
||||
this.onTouched = fn;
|
||||
@ -192,8 +186,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||
|
||||
/**
|
||||
* Sets the "disabled" property on the select input element.
|
||||
*
|
||||
* @param isDisabled The disabled value
|
||||
* @nodoc
|
||||
*/
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||
@ -285,10 +278,7 @@ export class ɵNgSelectMultipleOption implements OnDestroy {
|
||||
this._renderer.setProperty(this._element.nativeElement, 'selected', selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnDestroy(): void {
|
||||
if (this._select) {
|
||||
this._select._optionMap.delete(this.id);
|
||||
|
@ -176,19 +176,17 @@ export class RequiredValidator implements Validator {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether the control is empty.
|
||||
* Returns the validation result if enabled, otherwise null.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this.required ? Validators.required(control) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a callback function to call when the validator inputs change.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnValidatorChange(fn: () => void): void {
|
||||
this._onChange = fn;
|
||||
@ -225,9 +223,9 @@ export class RequiredValidator implements Validator {
|
||||
})
|
||||
export class CheckboxRequiredValidator extends RequiredValidator {
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether or not the checkbox has been checked.
|
||||
* Returns the validation result if enabled, otherwise null.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this.required ? Validators.requiredTrue(control) : null;
|
||||
@ -286,19 +284,17 @@ export class EmailValidator implements Validator {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether an email address is valid.
|
||||
* Returns the validation result if enabled, otherwise null.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this._enabled ? Validators.email(control) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a callback function to call when the validator inputs change.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnValidatorChange(fn: () => void): void {
|
||||
this._onChange = fn;
|
||||
@ -374,13 +370,7 @@ export class MinLengthValidator implements Validator, OnChanges {
|
||||
@Input()
|
||||
minlength!: string|number; // This input is always defined, since the name matches selector.
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use
|
||||
* only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if ('minlength' in changes) {
|
||||
this._createValidator();
|
||||
@ -389,19 +379,17 @@ export class MinLengthValidator implements Validator, OnChanges {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether the value meets a minimum length
|
||||
* requirement. Returns the validation result if enabled, otherwise null.
|
||||
* Method that validates whether the value meets a minimum length requirement.
|
||||
* Returns the validation result if enabled, otherwise null.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this.minlength == null ? null : this._validator(control);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a callback function to call when the validator inputs change.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnValidatorChange(fn: () => void): void {
|
||||
this._onChange = fn;
|
||||
@ -460,13 +448,7 @@ export class MaxLengthValidator implements Validator, OnChanges {
|
||||
@Input()
|
||||
maxlength!: string|number; // This input is always defined, since the name matches selector.
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use
|
||||
* only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if ('maxlength' in changes) {
|
||||
this._createValidator();
|
||||
@ -475,19 +457,16 @@ export class MaxLengthValidator implements Validator, OnChanges {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether the value exceeds
|
||||
* the maximum length requirement.
|
||||
* Method that validates whether the value exceeds the maximum length requirement.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this.maxlength != null ? this._validator(control) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a callback function to call when the validator inputs change.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnValidatorChange(fn: () => void): void {
|
||||
this._onChange = fn;
|
||||
@ -549,13 +528,7 @@ export class PatternValidator implements Validator, OnChanges {
|
||||
@Input()
|
||||
pattern!: string|RegExp; // This input is always defined, since the name matches selector.
|
||||
|
||||
/**
|
||||
* @description
|
||||
* A lifecycle method called when the directive's inputs change. For internal use
|
||||
* only.
|
||||
*
|
||||
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||
*/
|
||||
/** @nodoc */
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if ('pattern' in changes) {
|
||||
this._createValidator();
|
||||
@ -564,19 +537,16 @@ export class PatternValidator implements Validator, OnChanges {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Method that validates whether the value matches the
|
||||
* the pattern requirement.
|
||||
* Method that validates whether the value matches the the pattern requirement.
|
||||
* @nodoc
|
||||
*/
|
||||
validate(control: AbstractControl): ValidationErrors|null {
|
||||
return this._validator(control);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Registers a callback function to call when the validator inputs change.
|
||||
*
|
||||
* @param fn The callback function
|
||||
* @nodoc
|
||||
*/
|
||||
registerOnValidatorChange(fn: () => void): void {
|
||||
this._onChange = fn;
|
||||
|
@ -1659,7 +1659,7 @@ export class FormGroup extends AbstractControl {
|
||||
_throwIfControlMissing(name: string): void {
|
||||
if (!Object.keys(this.controls).length) {
|
||||
throw new Error(`
|
||||
There are no form controls registered with this group yet. If you're using ngModel,
|
||||
There are no form controls registered with this group yet. If you're using ngModel,
|
||||
you may want to check next tick (e.g. use setTimeout).
|
||||
`);
|
||||
}
|
||||
@ -2101,7 +2101,7 @@ export class FormArray extends AbstractControl {
|
||||
_throwIfControlMissing(index: number): void {
|
||||
if (!this.controls.length) {
|
||||
throw new Error(`
|
||||
There are no form controls registered with this array yet. If you're using ngModel,
|
||||
There are no form controls registered with this array yet. If you're using ngModel,
|
||||
you may want to check next tick (e.g. use setTimeout).
|
||||
`);
|
||||
}
|
||||
|
24
yarn.lock
24
yarn.lock
@ -2243,6 +2243,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
|
||||
integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
|
||||
|
||||
"@types/multimatch@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/multimatch/-/multimatch-4.0.0.tgz#e14237ade6cba7b79fe3a1a5d4e9579613cee6b6"
|
||||
integrity sha512-xS26gtqY5QASmfU/6jb5vj7F0D0SctgRGtwXsKSNng1knk/OewjISlkMwGonkMCbZCqSoW3s6nL0sAtTlzbL/g==
|
||||
dependencies:
|
||||
multimatch "*"
|
||||
|
||||
"@types/node-fetch@^2.5.7":
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
|
||||
@ -2347,10 +2354,12 @@
|
||||
"@types/source-list-map" "*"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@types/yaml@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.2.0.tgz#4ed577fc4ebbd6b829b28734e56d10c9e6984e09"
|
||||
integrity sha512-GW8b9qM+ebgW3/zjzPm0I1NxMvLaz/YKT9Ph6tTb+Fkeyzd9yLTvQ6ciQ2MorTRmb/qXmfjMerRpG4LviixaqQ==
|
||||
"@types/yaml@^1.9.7":
|
||||
version "1.9.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.9.7.tgz#2331f36e0aac91311a63d33eb026c21687729679"
|
||||
integrity sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==
|
||||
dependencies:
|
||||
yaml "*"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "15.0.0"
|
||||
@ -10714,7 +10723,7 @@ multicast-dns@^6.0.1:
|
||||
dns-packet "^1.3.1"
|
||||
thunky "^1.0.2"
|
||||
|
||||
multimatch@^4.0.0:
|
||||
multimatch@*, multimatch@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3"
|
||||
integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
|
||||
@ -16342,6 +16351,11 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@*, yaml@^1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
|
||||
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
|
||||
|
||||
yaml@^1.7.2:
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.3.tgz#2f420fca58b68ce3a332d0ca64be1d191dd3f87a"
|
||||
|
Reference in New Issue
Block a user