Compare commits

...

441 Commits

Author SHA1 Message Date
4baabf9cd3 release: cut the v11.0.0-next.3 release 2020-09-23 15:21:21 -04:00
7244e1b4e3 docs: release notes for the v10.1.3 release 2020-09-23 15:14:22 -04:00
b1682526dd refactor(dev-infra): simplify runBenchmark (#38941)
* Make url and params optional in runBenchmark
* Make url optional in openBrowser
* Remove unused code from runBenchmark

PR Close #38941
2020-09-22 15:05:34 -07:00
75610505c6 refactor(zone.js): remove usages of blacklist related to UNPATCHED_EVENTS (#38930)
Remove usages of blacklist around UNPATCHED_EVENTS configuration

PR Close #38930
2020-09-22 15:05:01 -07:00
ba3f4c26bb refactor(compiler): make keySpan available for BoundAttributes (#38898)
Though we currently have the knowledge of where the `key` for an
attribute binding appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
`sourceSpan`. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.

PR Close #38898
2020-09-22 15:04:30 -07:00
c8f056beb6 fix(core): ensure TestBed is not instantiated before override provider (#38717)
There is an inconsistency in overrideProvider behaviour. Testing documentation says
(https://angular.io/guide/testing-components-basics#createcomponent) that all override...
methods throw error if TestBed is already instantiated. However overrideProvider doesn't throw any error, but (same as
other override... methods) doesn't replace providers if TestBed is instantiated. Add TestBed instantiation check to
overrideProvider method to make it consistent.

BREAKING CHANGE:

If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
before TestBed initialization is completed.

Issue mentioned here: https://github.com/angular/angular/issues/13460#issuecomment-636005966
Documentation: https://angular.io/guide/testing-components-basics#createcomponent

PR Close #38717
2020-09-22 15:03:44 -07:00
a2068523fd feat(service-worker): add the option to prefer network for navigation requests (#38565)
This commit introduces a new option for the service worker, called
`navigationRequestStrategy`, which adds the possibility to force the service worker
to always create a network request for navigation requests.
This enables the server redirects while retaining the offline behavior.

Fixes #38194

PR Close #38565
2020-09-22 09:29:20 -07:00
145ab3d7e0 docs: Update titles to getting started topics (#38887)
The topics for our getting started tutorial are inconsistent.
This change makes the titles consistent and easier to read.

PR Close #38887
2020-09-21 16:30:35 -07:00
3082f7378b test(compiler-cli): make typescript_ast_factory_spec tests resilient to line-endings (#38925)
The tests were assuming that newlines were `\n` characters but this is not
the case on Windows.

PR Close #38925
2020-09-21 16:24:34 -07:00
297b123151 refactor(compiler-cli): make the output AST translator generic (#38775)
This commit refactors the `ExpressionTranslatorVisitor` so that it
is not tied directly to the TypeScript AST. Instead it uses generic
`TExpression` and `TStatement` types that are then converted
to concrete types by the `TypeScriptAstFactory`.

This paves the way for a `BabelAstFactory` that can be used to
generate Babel AST nodes instead of TypeScript, which will be
part of the new linker tool.

PR Close #38775
2020-09-21 12:27:27 -07:00
a93605f2a4 refactor(compiler-cli): simplify imports from compiler to type translator (#38775)
Previously each identifier was being imported individually, which made for a
very long import statement, but also obscurred, in the code, which identifiers
came from the compiler.

PR Close #38775
2020-09-21 12:27:27 -07:00
15dfd3439a refactor(compiler-cli): split up translator file (#38775)
This file contains a number of classes making it long and hard to work with.
This commit splits the `ImportManager`, `Context` and `TypeTranslatorVisitor`
classes, along with associated functions and types into their own files.

PR Close #38775
2020-09-21 12:27:27 -07:00
123bff7cb6 fix(compiler-cli): generate let statements in ES2015+ mode (#38775)
When the target of the compiler is ES2015 or newer then we should
be generating `let` and `const` variable declarations rather than `var`.

PR Close #38775
2020-09-21 12:27:27 -07:00
6158dc16b4 refactor(compiler): use a named type for cooked/raw string objects (#38775)
Using an interface makes the code cleaner and more readable.
This change also adds the `range` property to the type to be used
for source-mapping.

PR Close #38775
2020-09-21 12:27:27 -07:00
b0a43872a8 refactor(compiler-cli): remove unused imports (#38775)
These imports are not used and so are just bloating the code unnecessarily

PR Close #38775
2020-09-21 12:27:27 -07:00
856e74ac98 refactor(compiler-cli): remove undesirable cast in the type translator (#38775)
The cast to `ts.Identifier` was a hack that "just happened to work".
The new approach is more robust and doesn't have to undermine
the type checker.

PR Close #38775
2020-09-21 12:27:27 -07:00
6ae3b68acf feat(compiler): Parse and recover on incomplete opening HTML tags (#38681)
Let's say we have a code like

```html
<div<span>123</span>
```

Currently this gets parsed into a tree with the element tag `div<span`.
This has at least two downsides:

- An incorrect diagnostic that `</span>` doesn't close an element is
  emitted.
- A consumer of the parse tree using it for editor services is unable to
  provide correct completions for the opening `<span>` tag.

This patch attempts to fix both issues by instead parsing the code into
the same tree that would be parsed for `<div></div><span>123</span>`.

In particular, we do this by optimistically scanning an open tag as
usual, but if we do not notice a terminating '>', we mark the tag as
"incomplete". A parser then emits an error for the incomplete tag and
adds a synthetic (recovered) element node to the tree with the
incomplete open tag's name.

What's the downside of this? For one, a breaking change.

<ol>
<li>

The first breaking change is that `<` symbols that are ambiguously text
or opening tags will be parsed as opening tags instead of text in
element bodies. Take the code

```html
<p>a<b</p>
```

Clearly we cannot have the best of both worlds, and this patch chooses
to swap the parsing strategy to support the new feature. Of course, `<`
can still be inserted as text via the `&lt;` entity.

</li>
</ol>

Part of #38596

PR Close #38681
2020-09-21 12:27:01 -07:00
49f27e31ed test(compiler-cli): re-enable dynamic value diagnostic tests on Windows CI (#37782)
This commit re-enables some tests that were temporarily disabled on Windows,
as they failed on native Windows CI. The Windows filesystem emulation has
been corrected in an earlier commit, such that the original failure would
now also occur during emulation on Linux CI.

PR Close #37782
2020-09-21 12:26:33 -07:00
1a62f74496 test(compiler-cli): fix drive letter casing in Windows filesystem emulation (#37782)
In native windows, the drive letter is a capital letter, while our Windows
filesystem emulation would use lowercase drive letters. This difference may
introduce tests to behave differently in native Windows versus emulated
Windows, potentially causing unexpected CI failures on Windows CI after a PR
has been merged.

Resolves FW-2267

PR Close #37782
2020-09-21 12:26:33 -07:00
2b1b7180db fix(forms): type NG_VALUE_ACCESSOR injection token as array (#29723)
NG_VALUE_ACCESSOR is a multi injection token, users can and
should expect more than one ControlValueAccessor to be
available (and this is how it is used in @angular/forms).

This is now reflected in the definition of the injection token
by typing it as an array of ControlValueAccessor. The motivating
reason is that using the programmatic Injector api will now
type Injector#get correspondingly.

fixes #29351

BREAKING CHANGES

NG_VALUE_ACCESSOR is now typed as a readonly array rather than
a mutable scalar. It is used as a multi injection token and as
such it should always be expected that more than one accessor
may be returned.

PR Close #29723
2020-09-21 12:26:07 -07:00
fdd4fa0009 docs: change wrong default app module by ng new (#38549)
In bootstrapping.md the default AppModule has some extra imports which are not generated
by default in ng new removed those extra imports and add them at appropriate place.

PR Close #38549
2020-09-21 12:25:28 -07:00
984ed39195 feat(common): Add ISO week-numbering year formats support to formatDate (#38828)
Add ISO 8601 week-numbering year formats ('r', 'rr', 'rrr', 'rrrr') support for formatDate function.

Issue:https://github.com/angular/angular/issues/38739

PR Close #38828
2020-09-21 12:24:43 -07:00
0c0c54d615 refactor(compiler): simplify visitor logic for attributes (#38899)
The logic for computing identifiers, specifically for bound attributes
can be simplified by using the value span of the binding rather than the
source span.

PR Close #38899
2020-09-21 12:23:58 -07:00
dfbfabc052 fix(docs-infra): remove scrollbar styles for accessibility (#38852)
This commit removes the scrollbar styles so that the default
styles in the browser render. This widens the webkit scroll bar.
This makes it easier to grab the scrollbar using assistive
technology and devices, and provides a wider target for
those who have dexterity issues. By removing these styles,
We will no longer have to maintain custom scrollbars specific to WebKit
and they will be accessible by default.

PR Close #38852
2020-09-21 12:22:07 -07:00
f3f6a42342 test(docs-infra): replace deprecated ReflectiveInjector with Injector (#38897)
This commit replaces the old and slow ReflectiveInjector that was
deprecated in v5 with the new Injector.

PR Close #38897
2020-09-21 12:21:27 -07:00
e498ea9b5a revert: feat(router): better warning message when a router outlet has not been instantiated (#38920)
This reverts commit [1609815].
The warning that was added created more confusion than it solved and also warned for valid use-cases.

PR Close #38920
2020-09-21 09:35:06 -07:00
a91f0f6b82 refactor(compiler): refactor ast spans test to be more human readable (#38902)
The current tests print out the span numbers, which are really difficult to verify
since it requires manually going to the template string and looking at what
characters appear within those indexes. The better humanization would be
to use the toString method of the spans, which prints the span text itself

PR Close #38902
2020-09-18 16:55:52 -07:00
d5ddb9f340 docs: Grammar fixes (#38900)
Changed several period into colons to be consistent throughout the doc.

Changed "If don't add the interface..." to "If _you_ don't add the interface..."

PR Close #38900
2020-09-18 16:52:52 -07:00
b68fab547a ci: do not require g3 checks for the changes in packages/zone.js/dist folder (#38901)
This commit updates ngbot config to avoid requesting google3 presubmit for the changes in
the `packages/zone.js/dist` folder (which is not synced into google3).

PR Close #38901
2020-09-18 16:48:16 -07:00
16a560119a build: update to latest version of yarn (#38869)
Update the vendored version of yarn to the latest version.

PR Close #38869
2020-09-18 16:47:33 -07:00
88d7bb8386 fix(http): Fix error message when we call jsonp without importing HttpClientJsonpModule (#38756)
Currently, when we call jsonp method without importing HttpClientJsonpModule, an error message appears saying
'Attempted to construct Jsonp request without JsonpClientModule installed.' instance of 'Attempted to
construct Jsonp request without HttpClientJsonpModule installed.'

PR Close #38756
2020-09-18 11:20:36 -07:00
2d6105a784 feat(dev-infra): output the number of new and fixed cycles (#38805)
This commit adds a logic to ouput the number of new and fixed cycles after running circular
dependency checker. This information is useful to better understand an impact of changes in case
the number of new/fixed cycles is relatively big.

PR Close #38805
2020-09-18 11:20:08 -07:00
95b8a8706a refactor(core): reduce the number of circular deps (#38805)
This commit updates several import statements in the core package to decrease the number of
cycles detected by the dependency checker tool.

PR Close #38805
2020-09-18 11:20:08 -07:00
d92a0dd72f fix(zone.js): should invoke xhr send task when no response error occurs (#38836)
Close #38795

in the XMLHttpRequest patch, when get `readystatechange` event, zone.js try to
invoke `load` event listener first, then call `invokeTask` to finish the
`XMLHttpRequest::send` macroTask, but if the request failed because the
server can not be reached, the `load` event listener will not be invoked,
so the `invokeTask` of the `XMLHttpRequest::send` will not be triggered either,
so we will have a non finished macroTask there which will make the Zone
not stable, also memory leak.

So in this PR, if the `XMLHttpRequest.status = 0` when we get the `readystatechange`
event, that means something wents wrong before we reached the server, we need to
invoke the task to finish the macroTask.

PR Close #38836
2020-09-18 11:19:37 -07:00
55485713a3 fix(dev-infra): skip husky git commit hooks while merging pull requests (#38888)
During the merge process, all validations have already been completed so git commit
hooks can be safely skipped.  This additionally, prevents errors from occuring which
would be caused the commit hooks executing, such as when yarn updates and then yarn
commands are unable to run within the same process.

PR Close #38888
2020-09-18 11:14:55 -07:00
d3169c533e refactor(core): remove unused imports (#38818)
This commit removes some unused imports from the spec files.

PR Close #38818
2020-09-18 08:03:48 -07:00
e4424863c2 fix(ngcc): fix compilation of ChangeDetectorRef in pipe constructors (#38892)
In #38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.

This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.

Fixes #38883

PR Close #38892
2020-09-18 08:02:46 -07:00
d795a00137 refactor(compiler): replace Comment nodes with leadingComments property (#38811)
Common AST formats such as TS and Babel do not use a separate
node for comments, but instead attach comments to other AST nodes.
Previously this was worked around in TS by creating a `NotEmittedStatement`
AST node to attach the comment to. But Babel does not have this facility,
so it will not be a viable approach for the linker.

This commit refactors the output AST, to remove the `CommentStmt` and
`JSDocCommentStmt` nodes. Instead statements have a collection of
`leadingComments` that are rendered/attached to the final AST nodes
when being translated or printed.

PR Close #38811
2020-09-18 08:01:25 -07:00
7fb388f929 docs: updating the text of user input page to reflect real location of the forms page (#38802)
PR Close #38802
2020-09-18 08:00:40 -07:00
02c6bff9cf Update aio/content/marketing/events.json (#38874)
Co-authored-by: George Kalpakas <kalpakas.g@gmail.com>
PR Close #38874
2020-09-18 07:59:53 -07:00
ef28e15884 docs: add upcoming angular conferences (#38874)
PR Close #38874
2020-09-18 07:59:49 -07:00
a33d630a21 fix(zone.js): should have better backward compatibilities (#38797)
Close #38561, #38669

zone.js 0.11.1 introduces a breaking change to adpat Angular package format,
and it breaks the module loading order, before 0.11, in IE11, the `zone.js` es5
format bundle will be imported, but after 0.11, the `fesm2015` format bundle will
be imported, which causes error.

And since the only purpose of the `dist` folder of zone.js bundles is to keep backward
 compatibility, in the original commit, I use package redirect to implement that, but
it is not fully backward compatible, we should keep the same dist structure as `0.10.3`.

PR Close #38797
2020-09-17 09:32:19 -07:00
c4b8964424 docs: drop newEvent() compatibility function (#37251)
Because PhantomJS has been deprecated since March 2018, and `newEvent`
is very confusing for newcomers that read the testing documentation,
we remove it entirely, and instead assume most, if not all, newcomers
will run tests in Chrome as it is the default.

Fixes #23370

PR Close #37251
2020-09-17 09:31:17 -07:00
dd8d8c8289 fix(common): add params and reportProgress options to HttpClient.put() overload (#37873)
When the response type is JSON, the `put()` overload signature did not have `reportProgress`
and  `params` options. This makes it difficult to type-check this overload.

This commit adds them to the overload signature.

Fixes #23600

PR Close #37873
2020-09-16 15:28:21 -07:00
129107191c refactor(compiler): always return a mutable clone from Scope#resolve (#38857)
This change prevents comments from a resolved node from appearing at
each location the resolved expression is used and also prevents callers
of `Scope#resolve` from accidentally modifying / adding comments to the
declaration site.

PR Close #38857
2020-09-16 15:27:22 -07:00
722699fb0c fix(dev-infra): handle no caretaker config being defined (#38862)
Properly handle cases where no caretaker config is provided to ng-dev commands

PR Close #38862
2020-09-16 15:22:10 -07:00
5614258cc7 docs(zone.js): Add breaking changes info for zone.js v0.11.1 (#38821)
Before Zone.js `v0.11.1`, Zone.js provides two format of bundles under `dist` folder,
`ES5` bundle `zone.js` and `ES2015` bundle `zone-evergreen.js`, these bundles are used
for `differential loading` of Angular. By default, the following code

```
import 'zone.js';
```

loads the `ES5` bundle `zone.js`.

From `v0.11.1`, Zone.js follows the [Angular Package Format]
(https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs),
so the folder structure of the Zone.js bundles is updated to match `Angular Package Format`.

So the same code

```
import 'zone.js';
```
loads the `ES2015` bundle.

This is a breaking change, so if the apps import zone.js in this way,
the apps will not work in legacy browsers such as `IE11`.

Zone.js still provides the same bundles under `dist` folder to keep backward
compatibility after `v0.11.1`. So the following code in `polyfills.ts` generated
by `Angular CLI` still works.

```
import 'zone.js/dist/zone';
```

For details, please refer the [changelog](./CHANGELOG.md) and
the [PR](https://github.com/angular/angular/pull/36540).

PR Close #38821
2020-09-16 15:21:10 -07:00
e62a918542 docs(forms): fix grammar in first sentence of reset function docs (#38872)
PR Close #38872
2020-09-16 15:20:30 -07:00
49ee90b1b5 docs: fix typo in architecture.md guide (#38853)
PR Close #38853
2020-09-16 15:19:43 -07:00
7849fdde09 feat(router): add migration to update calls to navigateByUrl and createUrlTree with invalid parameters (#38825)
In #38227 the signatures of `navigateByUrl` and `createUrlTree` were updated to exclude unsupported
properties from their `extras` parameter. This migration looks for the relevant method calls that
pass in an `extras` parameter and drops the unsupported properties.

**Before:**
```
this._router.navigateByUrl('/', {skipLocationChange: false, fragment: 'foo'});
```

**After:**
```
this._router.navigateByUrl('/', {
  /* Removed unsupported properties by Angular migration: fragment. */
  skipLocationChange: false
});
```

These changes also move the method call detection logic out of the `Renderer2` migration and into
a common place so that it can be reused in other migrations.

PR Close #38825
2020-09-16 15:16:18 -07:00
97adc27207 docs(bazel): fix typo in BUILD.bazel comments (#38054)
Update BUILD.bazel

PR Close #38054
2020-09-16 15:15:21 -07:00
41bc2701c4 test(docs-infra): simplify EventsComponent tests and add more test cases (#36517)
This commit simplifies the tests of `EventsComponent` (by introducing a
`createMockEvent()` helper and getting rid of the irrelevant `Event`
fields) and adds tests for some more usecases. It also makes the tests
more robust by using Jasmine's `Clock` to mock the current date.

PR Close #36517
2020-09-16 15:14:24 -07:00
a765530277 refactor(docs-infra): remove tooltip from links same as name (#36517)
In the events.json file most of tooltips are same as name so there
were of no use, as they were providing no extra information. So,
removed them from the events.json file

PR Close #36517
2020-09-16 15:14:21 -07:00
5b33798796 feat(docs-infra): created new widget for events page (#36517)
Data in events page was hardcoded and it is manually moved in the table.

Created a new events widget which will automatically move past and upcoming
events from events.json (`aio/content/marketing/events.json`) file to the
relevant table in the events tab

PR Close #36517
2020-09-16 15:14:18 -07:00
44074499dc test(docs-infra): improve typeahead example and add unit test (#34190)
This commit improves the typeahead example, by using the emitted input
value. It also adds a unit test to ensure that the example is working
as intended.

PR Close #34190
2020-09-16 15:13:05 -07:00
ba54671993 test(docs-infra): add unit tests for rxjs examples (#34190)
This commit adds missing unit tests for all rxjs examples from the docs.

Closes #28017

PR Close #34190
2020-09-16 15:13:02 -07:00
a85109fd72 release: cut the v11.0.0-next.2 release 2020-09-16 14:52:51 -07:00
85a2626620 docs: release notes for the v10.1.2 release 2020-09-16 14:49:30 -07:00
d192c87f6a refactor(dev-infra): refactor commit-message files (#38845)
Refactor the commit-message files to be consistent with how other ng-dev tooling
is structured.

PR Close #38845
2020-09-15 16:05:42 -07:00
3817e5f1df fix(router): Fix arguments order for call to shouldReuseRoute (#26949)
The `createOrReuseChildren` function calls shouldReuseRoute with the
previous child values use as the future and the future child value used
as the current argument. This is incosistent with the argument order in
`createNode`. This inconsistent order can make it difficult/impossible
to correctly implement the `shouldReuseRoute` function. Usually this
order doesn't matter because simple equality checks are made on the
args and it doesn't matter which is which.

More detail can be found in the bug report: #16192.

Fix #16192

BREAKING CHANGE: This change corrects the argument order when calling
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
routes, they would be called with the future and current arguments would
be swapped. If your RouteReuseStrategy relies specifically on only the future
or current snapshot state, you may need to update the shouldReuseRoute
implementation's use of "future" and "current" ActivateRouteSnapshots.

PR Close #26949
2020-09-15 11:33:52 -07:00
171a0d0696 docs: add ngc to glossary (#36781)
ngc angular compiler was not mentioned in the glossary.
Glossary should contain the relevant terms in angular
which are hard to get. So, added a small defination of
ngc to the glossary

PR Close #36781
2020-09-15 11:29:50 -07:00
a1c1c450dc test(ngcc): load standard files only once (#38840)
In the integration test suite of ngcc, we load a set of files from
`node_modules` into memory. This includes the `typescript` package and
`@angular` scoped packages, which account for a large number of large
files that needs to be loaded from disk. This commit moves this work
to the top-level, such that it doesn't have to be repeated in all tests.

PR Close #38840
2020-09-15 11:23:13 -07:00
fd44d84a33 perf(ngcc): reduce maximum worker count (#38840)
Recent optimizations to ngcc have significantly reduced the total time
it takes to process `node_modules`, to such extend that sharding across
multiple processes has become less effective. Previously, running
ngcc asynchronously would allow for up to 8 workers to be allocated,
however these workers have to repeat work that could otherwise be shared.
Because ngcc is now able to reuse more shared computations, the overhead
of multiple workers is increased and therefore becomes less effective.
As an additional benefit, having fewer workers requires less memory and
less startup time.

To give an idea, using the following test setup:

```bash
npx @angular/cli new perf-test
cd perf-test
yarn ng add @angular/material
./node_modules/.bin/ngcc --properties es2015 module main \
  --first-only --create-ivy-entry-points
```

We observe the following figures on CI:

|                   | 10.1.1    | PR #38840 |
| ----------------- | --------- | --------- |
| Sync              | 85s       | 25s       |
| Async (8 workers) | 22s       | 16s       |
| Async (4 workers) | -         | 11s       |

In addition to changing the default number of workers, ngcc will now
use the environment variable `NGCC_MAX_WORKERS` that may be configured
to either reduce or increase the number of workers.

PR Close #38840
2020-09-15 11:23:09 -07:00
f0688b4d18 perf(ngcc): introduce cache for sharing data across entry-points (#38840)
ngcc creates typically two `ts.Program` instances for each entry-point,
one for processing sources and another one for processing the typings.
The creation of these programs is somewhat expensive, as it concerns
module resolution and parsing of source files.

This commit implements several layers of caching to optimize the
creation of programs:

1. A shared module resolution cache across all entry-points within a
   single invocation of ngcc. Both the sources and typings program
   benefit from this cache.
2. Sharing the parsed `ts.SourceFile` for a single entry-point between
   the sources and typings program.
3. Sharing parsed `ts.SourceFile`s of TypeScript's default libraries
   across all entry-points within a single invocation. Some of these
   default library typings are large and therefore expensive to parse,
   so sharing the parsed source files across all entry-points offers
   a significant performance improvement.

Using a bare CLI app created using `ng new` + `ng add @angular/material`,
the above changes offer a 3-4x improvement in ngcc's processing time
when running synchronously and ~2x improvement for asynchronous runs.

PR Close #38840
2020-09-15 11:23:04 -07:00
b9ca6d20cc feat(dev-infra): include CI status check in the caretaker check (#38779)
Add a CI status check in the ng-dev caretaker check command.

PR Close #38779
2020-09-15 08:45:02 -07:00
e00535a2a4 fix(dev-infra): remove ANSI escape codes from log file outputs (#38792)
Remove the ANSI codes from the log file outputs to make the ng-dev log files
more readable.

PR Close #38792
2020-09-15 08:44:00 -07:00
593bd594e3 build: create temporary script for symbol extractor tests (#38819)
Creates a temporary script to running all symbol extractor tests.

PR Close #38819
2020-09-14 16:54:39 -07:00
284c70ee9d build: add tag to symbol-extractor tests (#38819)
Add a tag to symbol-extractor tests to allow for bazel querying.

PR Close #38819
2020-09-14 16:54:36 -07:00
78e1ecb161 feat(dev-infra): allow local ng-dev configuration to error on invalid commit messages (#38784)
As part of the commit message conformance check, local commit message checks are
made to be warnings rather than failures. An additional local option is also in
place to allow for the commit message validation failures to be considered errors
instead.

PR Close #38784
2020-09-14 14:34:50 -07:00
3934f0a833 docs(elements): convert the ng add command to code-example (#38834)
the command was hardly visible currently
changing it to shell for visibility

PR Close #38834
2020-09-14 14:31:05 -07:00
297c060ae7 perf(compiler-cli): optimize computation of type-check scope information (#38539)
When type-checking a component, the declaring NgModule scope is used
to create a directive matcher that contains flattened directive metadata,
i.e. the metadata of a directive and its base classes. This computation
is done for all components, whereas the type-check scope is constant per
NgModule. Additionally, the flattening of metadata is constant per
directive instance so doesn't necessarily have to be recomputed for
each component.

This commit introduces a `TypeCheckScopes` class that is responsible
for flattening directives and computing the scope per NgModule. It
caches the computed results as appropriate to avoid repeated computation.

PR Close #38539
2020-09-14 11:54:40 -07:00
077f51685a perf(compiler-cli): only emit directive/pipe references that are used (#38539)
For the compilation of a component, the compiler has to prepare some
information about the directives and pipes that are used in the template.
This information includes an expression for directives/pipes, for usage
within the compilation output. For large NgModule compilation scopes
this has shown to introduce a performance hotspot, as the generation of
expressions is quite expensive. This commit reduces the performance
overhead by only generating expressions for the directives/pipes that
are actually used within the template, significantly cutting down on
the compiler's resolve phase.

PR Close #38539
2020-09-14 11:54:37 -07:00
e162da0753 refactor(dev-infra): do not validate config file multiple times (#38808)
Currently we validate the configuration file on each `getConfig`
invocation. We can only validate once since the configuration
is cached.

Also while being at it, renames the cache variables to lower-case as those
do not represent constants (which are convention-wise upper case).

PR Close #38808
2020-09-14 08:34:15 -07:00
354138eba9 build(docs-infra): upgrade cli command docs sources to 800ba9271 (#38827)
Updating [angular#master](https://github.com/angular/angular/tree/master) from
[cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in
[commit range](32391604b...800ba9271):

**Modified**
- help/build.json
- help/serve.json

PR Close #38827
2020-09-14 08:33:39 -07:00
6768fe9927 fix(dev-infra): correct build setup for dev-infra (#38815)
Correct's the missing dependencies and incorrect build dependencies for the
dev-infra bazel targets.

PR Close #38815
2020-09-11 13:59:30 -07:00
57c442f930 build(router): update symbols for routing app (#38817)
This commit updates the golden symbol files for the routing app.

PR Close #38817
2020-09-11 13:20:34 -07:00
f667e374a9 build: create sample router app (#38714)
This commit creates a sample router test application to introduce the
symbol tests. It serves as a guard to ensure that any future work on the
router package does not unintentionally increase the payload size.

PR Close #38714
2020-09-11 12:10:46 -07:00
15207e3c9c fix(compiler): detect pipes in ICUs in template binder (#38810)
Recent work on compiler internals in #38539 led to an unexpected failure,
where a pipe used exclusively inside of an ICU would no longer be
emitted into the compilation output. This caused runtime errors due to
missing pipes.

The issue occurred because the change in #38539 would determine the set
of used pipes up-front, independent from the template compilation using
the `R3TargetBinder`. However, `R3TargetBinder` did not consider
expressions within ICUs, so any pipe usages within those expressions
would not be detected. This fix unblocks #38539 and also concerns
upcoming linker work, given that prelink compilations would not go
through full template compilation but only `R3TargetBinder`.

PR Close #38810
2020-09-11 12:07:40 -07:00
66129f8ea6 docs: clarify what fixes are merged to LTS versions (#38788)
PR Close #38788
2020-09-11 08:45:42 -07:00
da14b72550 refactor(dev-infra): add default params to runBenchmark (#38748)
* Use '' as the default for 'url'
* Use [] as the default for 'params'
* Use true as the default for 'ignoreBrowserSynchronization'

PR Close #38748
2020-09-11 08:44:35 -07:00
27cc56b359 fix(zone.js): add missing types field in package.json (#38585)
Close #38584

In zone.js 0.11.1, the `types` field is missing in the `package.json`,
the reason is in zone.js 0.11.0, the `files` field is used to specify the
types, but it cause the npm package not contain any bundles issue, so zone.js
0.11.1 remove the `files` field, which cause the `type` definition gone.

This PR concat the `zone.js.d.ts`, `zone.configurations.api.ts`, `zone.api.extensions.ts`
types into a single `zone.d.ts` file.

PR Close #38585
2020-09-11 08:43:53 -07:00
6acea54f62 fix(common): mark locale data arrays as readonly (#30397)
To discourage developers from mutating the arrays returned
from the following methods, their return types have been marked
as readonly.

* `getLocaleDayPeriods()`
* `getLocaleDayNames()`
* `getLocaleMonthNames()`
* `getLocaleEraNames()`

Fixes #27003

BREAKING CHANGE:
The locale data API has been marked as returning readonly arrays, rather
than mutable arrays, since these arrays are shared across calls to the
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
then your code will not longer compile. If you need to mutate the array, you
should now take a copy (e.g. by calling `slice()`) and mutate the copy.

PR Close #30397
2020-09-10 15:35:30 -07:00
2d52c80332 test(compiler): Add back tests for renamed inputs and outputs (#38798)
#38685 corrected the confusion between field and property names so the consumer can
now be determined correctly.

PR Close #38798
2020-09-10 14:33:10 -07:00
03447ba52f docs: Move Displaying data topic and ToH tutorial (#38774)
Move the "Displaying data topic" into the Tutorials section.
Move the ToH tutorial to the top of the tutorials section.

PR Close #38774
2020-09-10 14:32:25 -07:00
8f349b2375 fix(compiler): source span for microsyntax text att should be key span (#38766)
In a microsyntax expressions, some attributes are not bound after
desugaring. For example,
```html
<div *ngFor="let item of items">
</div>
```
gets desugared to
```html
<ng-template ngFor let-items [ngForOf]="items">
</ngtemplate>
```
In this case, `ngFor` should be a literal attribute with no RHS value.
Therefore, its source span should be just the `keySpan` and not the
source span of the original template node.
This allows language service to precisely pinpoint different spans in a
microsyntax to provide accurate information.

PR Close #38766
2020-09-10 14:31:23 -07:00
19598b47ca feat(compiler-cli): add ability to get symbol of reference or variable (#38618)
Adds `TemplateTypeChecker` operation to retrieve the `Symbol` of a
`TmplAstVariable` or `TmplAstReference` in a template.

Sometimes we need to traverse an intermediate variable declaration to arrive at
the correct `ts.Symbol`. For example, loop variables are declared using an intermediate:
```
<div *ngFor="let user of users">
  {{user.name}}
</div>
```
Getting the symbol of user here (from the expression) is tricky, because the TCB looks like:

```
var _t0 = ...; // type of NgForOf
var _t1: any; // context of embedded view for NgForOf structural directive
if (NgForOf.ngTemplateContextGuard(_t0, _t1)) {
  // _t1 is now NgForOfContext<...>
  var _t2 = _t1.$implicit; // let user = '$implicit'
  _t2.name; // user.name expression
}
```
Just getting the `ts.Expression` for the `AST` node `PropRead(ImplicitReceiver, 'user')`
via the sourcemaps will yield the `_t2` expression.  This function recognizes that `_t2`
is a variable declared locally in the TCB, and actually fetch the `ts.Symbol` of its initializer.

These special handlings show the versatility of the `Symbol`
interface defined in the API. With this, when we encounter a template variable,
we can provide the declaration node, as well as specific information
about the variable instance, such as the `ts.Type` and `ts.Symbol`.

PR Close #38618
2020-09-10 12:40:50 -07:00
f56ece4fdc feat(compiler-cli): Add ability to get Symbol of AST expression in component template (#38618)
Adds support to the `TemplateTypeChecker` to get a `Symbol` of an AST
expression in a component template.
Not all expressions will have `ts.Symbol`s (e.g. there is no `ts.Symbol`
associated with the expression `a + b`, but there are for both the a and b
nodes individually).

PR Close #38618
2020-09-10 12:40:47 -07:00
cf2e8b99a8 feat(compiler-cli): Add ability to get Symbol of Templates and Elements in component template (#38618)
Adds support to the `TemplateTypeChecker` for retrieving a `Symbol` for
`TmplAstTemplate` and `TmplAstElement` nodes in a component template.

PR Close #38618
2020-09-10 12:40:44 -07:00
c4556db9f5 feat(compiler-cli): TemplateTypeChecker operation to get Symbol from a template node (#38618)
Specifically, this commit adds support for retrieving a `Symbol` from a
`TmplAstBoundEvent` or `TmplAstBoundAttribute`. Other template nodes
will be supported in following commits.

PR Close #38618
2020-09-10 12:40:41 -07:00
a46e0e48a3 refactor(compiler-cli): Adjust output of TCB to support TemplateTypeChecker Symbol retrieval (#38618)
The statements generated in the TCB are optimized for performance and producing diagnostics.
These optimizations can result in generating a TCB that does not have all the information
needed by the `TemplateTypeChecker` for retrieving `Symbol`s. For example, as an optimization,
the TCB will not generate variable declaration statements for directives that have no
references, inputs, or outputs. However, the `TemplateTypeChecker` always needs these
statements to be present in order to provide `ts.Symbol`s and `ts.Type`s for the directives.

This commit adds logic to the TCB generation to ensure the required
information is available in a form that the `TemplateTypeChecker` can
consume. It also adds an option to the `NgCompiler` that makes this
generation configurable.

PR Close #38618
2020-09-10 12:40:38 -07:00
9e77bd3087 feat(compiler-cli): define interfaces to be used for TemplateTypeChecker (#38618)
This commit defines the interfaces which outline the information the
`TemplateTypeChecker` can return when requesting a Symbol for an item in the
`TemplateAst`.
Rather than providing the `ts.Symbol`, `ts.Type`, etc.
information in several separate functions, the `TemplateTypeChecker` can
instead provide all the useful information it knows about a particular
node in the `TemplateAst` and allow the callers to determine what to do
with it.

PR Close #38618
2020-09-10 12:40:35 -07:00
26f28200bf fix(common): do not round up fractions of a millisecond in DatePipe (#38009)
Currently, the `DatePipe` (via `formatDate()`) rounds fractions of a millisecond to the
nearest millisecond. This can cause dates that are less than a millisecond before midnight
to be incremented to the following day.

The [ECMAScript specification](https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11)
defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms`
becomes `999ms`.

This change brings `formatDate()` and so `DatePipe` inline with the ECMAScript
specification.

Fixes #37989

BREAKING CHANGE:

When passing a date-time formatted string to the `DatePipe` in a format that contains
fractions of a millisecond, the milliseconds will now always be rounded down rather than
to the nearest millisecond.

Most applications will not be affected by this change. If this is not the desired behaviour
then consider pre-processing the string to round the millisecond part before passing
it to the `DatePipe`.

PR Close #38009
2020-09-10 10:55:37 -07:00
ce1efc1af2 fix(localize): ensure that formatOptions is optional (#38787)
Some lower level APIs are used by CLI, and requiring
the `formatOpions` argument at that level is a
breaking change. This commit makes it optional
at every level to avoid the breaking change.

PR Close #38787
2020-09-10 10:55:04 -07:00
d1415162cb fix(core): clear the RefreshTransplantedView when detached (#38768)
The `RefreshTransplantedView` flag is used to indicate that the view or one of its children
is transplanted and dirty, so it should still be refreshed as part of change detection.
This flag is set on the transplanted view itself as well setting a
counter on as its parents.
When a transplanted view is detached and still has this flag, it means
it got detached before it was refreshed. This can happen for "backwards
references" or transplanted views that are inserted at a location that
was already checked. In this case, we should decrement the parent
counters _and_ clear the flag on the detached view so it's not seen as
"transplanted" anymore (it is detached and has no parent counters to
adjust).

fixes #38619

PR Close #38768
2020-09-10 09:11:38 -07:00
db21c4fb44 perf(router): use ngDevMode to tree-shake error messages in router (#38674)
This commit adds `ngDevMode` guard to throw some errors only in dev mode
The ngDevMode flag helps to tree-shake these error messages from production
builds (in dev mode everything will work as it works right now) to decrease
production bundle size.

PR Close #38674
2020-09-10 09:06:35 -07:00
281865bbcf refactor(router): Remove defer as it's not needed anymore (#38781)
This change contains the test from #38780 and also removes `defer` from
the `apply_redirects` logic because the change that introduced
`concatMap` instead of `map`...`concatAll` makes `defer` unnecessary.

PR Close #38781
2020-09-10 08:55:31 -07:00
3406ec15a4 docs: add note about only one label target being allowed to be applied to a PR (#38764)
To clarify the use of GitHub labels for targetting PRs, a not about only being
allowed to apply one label is added.

PR Close #38764
2020-09-10 08:53:47 -07:00
85951a0465 refactor(core): _reset() remove nextRecord (#38752)
The nextRecord is not neccessary, so remove it and use record._nextMoved to iterate

PR Close #38752
2020-09-10 08:52:51 -07:00
0ae00bb1f7 fix(upgrade): add try/catch when downgrading injectables (#38671)
This commit improves the error thrown by the downgrade module with a more
descriptive message on why the downgrade is failing.

Closes #37579

PR Close #38671
2020-09-10 08:50:15 -07:00
1373a98e25 feat(dev-infra): Allow local user ng-dev configuration to disable commit message wizard (#38701)
As not all users, particularly contributors consistently contributing with a deep
understanding of our commit message guidelines, will not want to rely on the
commit message wizard, we allow a user to opt out of using this wizard during
commit message creation.

PR Close #38701
2020-09-09 16:31:17 -07:00
1ed6913b8b feat(dev-infra): Add support for local user ng-dev configuration (#38701)
Create a utility for loading a local user configuration object to describe
local configuration values, such as skipping the commit message wizard.

PR Close #38701
2020-09-09 16:31:16 -07:00
3c4b8b97c1 docs: put docs style guide back in left nav (#38683)
PR Close #38683
2020-09-09 16:22:58 -07:00
f9421184ef refactor(dev-infra): update commit message validation to return validation result (#38703)
Previously, the validateCommitMessage function ran validation and logged the results.
The validateCommitMessage function now returns an object containing the validation
results and the cli action functions are instead responsible for logging the results.

This is being done as a prefactor for a change which allows for commit message
hook validation to be either a blocking error or a warning.

PR Close #38703
2020-09-09 16:22:36 -07:00
c6ebb77cec test(language-service): [ivy] remove all markers from test (#38777)
In the test project there are no longer reference markers and location
markers, so there's no need to "pre-process" the source files to remove
them. This will make the Ivy tests cleaner and faster.

PR Close #38777
2020-09-09 16:21:56 -07:00
a69507a0ad release: cut the v11.0.0-next.1 release 2020-09-09 13:31:47 -07:00
886f58d4fe docs: release notes for the v10.1.1 release 2020-09-09 13:21:46 -07:00
18f84a0328 Revert "perf(compiler-cli): only emit directive/pipe references that are used (#38539)" (#38765)
This reverts commit 4faac78e32.
internal failure:
https://test.corp.google.com/ui#id=OCL:329948619:BASE:329967516:1599160428139:d63165ae

PR Close #38765
2020-09-09 12:21:22 -07:00
b0ca3cd0c4 Revert "perf(compiler-cli): optimize computation of type-check scope information (#38539)" (#38765)
This reverts commit ba95b79a21.
internal failure:
https://test.corp.google.com/ui#id=OCL:329948619:BASE:329967516:1599160428139:d63165ae

PR Close #38765
2020-09-09 12:21:22 -07:00
3d77b64fc3 docs: add Andrew Grekov to GDE resources (#36690)
This commit adds Andrew Grekov to the GDE
resources page and describes his work as a software
engineer using angular and .NET.

PR Close #36690
2020-09-09 09:44:47 -07:00
f645d26e3f docs(docs-infra): add The Deep Dive podcast, update Angular inDepth URL (#37621)
Add the new podcast called The Deep Dive to the list of Podcast resources.

Also replace the name and URL for Angular inDepth as the old URL is deprecated.

PR Close #37621
2020-09-09 09:11:11 -07:00
6d9bfb8368 docs(router): fixed PreloadAllModules comment typo (#38758)
PR Close #38758
2020-09-09 09:07:49 -07:00
7997fc5f97 docs: mark the entryComponents array as deprecated (#38616)
The `entryComponents` array is now deprecated (per https://angular.io/api/core/NgModule#entryComponents
and https://angular.io/guide/deprecations#entryComponents).

PR Close #38616
2020-09-09 09:07:18 -07:00
3cb2a79399 docs: update v9 support status to LTS (#38744)
PR Close #38744
2020-09-09 09:06:56 -07:00
d896c33b0e fix(dev-infra): set build commit message type to allow an optional scope (#38745)
Allow, optionally, a scope to be used with the build type commit message.

PR Close #38745
2020-09-09 09:06:33 -07:00
19a484302d docs: Fix component decorator closing brackets (#38754)
PR Close #38754
2020-09-09 09:06:10 -07:00
ded075a79c docs: add missing space (#38759)
This commit adds a missing space after the comma in listing the rxjs
operators section.

PR Close #38759
2020-09-09 09:05:47 -07:00
ba95b79a21 perf(compiler-cli): optimize computation of type-check scope information (#38539)
When type-checking a component, the declaring NgModule scope is used
to create a directive matcher that contains flattened directive metadata,
i.e. the metadata of a directive and its base classes. This computation
is done for all components, whereas the type-check scope is constant per
NgModule. Additionally, the flattening of metadata is constant per
directive instance so doesn't necessarily have to be recomputed for
each component.

This commit introduces a `TypeCheckScopes` class that is responsible
for flattening directives and computing the scope per NgModule. It
caches the computed results as appropriate to avoid repeated computation.

PR Close #38539
2020-09-08 14:50:38 -07:00
4faac78e32 perf(compiler-cli): only emit directive/pipe references that are used (#38539)
For the compilation of a component, the compiler has to prepare some
information about the directives and pipes that are used in the template.
This information includes an expression for directives/pipes, for usage
within the compilation output. For large NgModule compilation scopes
this has shown to introduce a performance hotspot, as the generation of
expressions is quite expensive. This commit reduces the performance
overhead by only generating expressions for the directives/pipes that
are actually used within the template, significantly cutting down on
the compiler's resolve phase.

PR Close #38539
2020-09-08 14:50:38 -07:00
4360eed9b7 fix(localize): enable whitespace preservation marker in XLIFF files (#38737)
Whitespace can be relevant in extracted XLIFF translation files.
Some i18n tools - e.g. CAT tool (OmegaT) - will reformat
the file to collapse whitespace if there is no indication to tell it
not to.

This commit adds the ability to specify "format options" that are passed
to the translation file serializer. The XLIFF 1.2 and 2.0 seralizers have
been updated to accept `{"xml:space":"preserve"}` format option which will
by added to the `<file>` element in the serialized translation file during
extraction.

Fixes #38679

PR Close #38737
2020-09-08 14:24:51 -07:00
c880e393e9 fix(router): If users are using the Alt key when clicking the router links, prioritize browser’s default behavior (#38375)
In most browsers, clicking links with the Alt key has a special behavior, for example, Chrome
downloads the target resource. As with other modifier keys, the router should stop the original
navigation to avoid preventing the browser’s default behavior.

When users click a link while holding the Alt key together, the browsers behave as follows.

Windows 10:

| Browser    | Behavior                                    |
|:-----------|:--------------------------------------------|
| Chrome 84  | Download the target resource                |
| Firefox 79 | Prevent navigation and therefore do nothing |
| Edge 84    | Download the target resource                |
| IE 11      | No impact                                   |

macOS Catalina:

| Browser    | Behavior                                    |
|:-----------|:--------------------------------------------|
| Chrome 84  | Download the target resource                |
| Firefox 79 | Prevent navigation and therefore do nothing |
| Safari 13  | Download the target resource                |

PR Close #38375
2020-09-08 14:07:11 -07:00
b0c79f2373 docs: Describe a scenario in which ngOnChanges is not called before ngOnInit. (#38625)
Closes #38613

PR Close #38625
2020-09-08 14:06:48 -07:00
a32a317ea1 fix(compiler-cli): ensure that a declaration is available in type-to-value conversion (#38684)
The type-to-value conversion could previously crash if a symbol was
resolved that does not have any declarations, e.g. because it's imported
from a missing module. This would typically result in a semantic
TypeScript diagnostic and halt further compilation, therefore not
reaching the type-to-value conversion logic. In Bazel however, it turns
out that Angular semantic diagnostics are requested even if there are
semantic TypeScript errors in the program, so it would then reach the
type-to-value conversation and crash.

This commit fixes the unsafe access and adds a test that ignores the
TypeScript semantic error, effectively replicating the situation as
experienced under Bazel.

Fixes #38670

PR Close #38684
2020-09-08 14:06:25 -07:00
bfb7eec698 ci: update payload size limit for integration tests (#38746)
This commit updates (reduces) the payload size limit for a couple test apps. This is a result of
adding the `ngDevMode` to tree-shake more dev-mode-only error messages from the core package within
1150649139.

PR Close #38746
2020-09-08 14:00:09 -07:00
7e0b3fd953 fix(compiler-cli): compute source-mappings for localized strings (#38645)
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See #38588 (comment)

PR Close #38645
2020-09-08 13:17:21 -07:00
7a6a061a9e refactor(compiler): move the MessagePiece classes into output_ast.ts (#38645)
The `MessagePiece` and derived classes, `LiteralPiece` and `PlaceholderPiece`
need to be referenced in the `LocalizedString` output AST class, so that we
can render the source-spans of each piece.

PR Close #38645
2020-09-08 13:17:21 -07:00
109555b33a refactor(compiler): track the closing source-span of TagPlaceholders (#38645)
The `TagPlaceholder` can contain children, in which case there are two source
spans of interest: the opening tag and the closing tag. This commit now allows
the closing tag source-span to be tracked, so that it can be used later in
source-mapping.

PR Close #38645
2020-09-08 13:17:20 -07:00
bf31ef29f6 refactor(compiler): capture interpolation source-spans in expression parser (#38645)
The expression parser will split the expression up at the interpolation markers
into expressions and static strings. This commit also captures the positions of
these strings in the expression to be used in source-mapping later.

PR Close #38645
2020-09-08 13:17:20 -07:00
40096bee00 fix(zone.js): run tests in umd format (#37582)
Since the `defineProperty` not swallow error any longer, now the tests compile
source code in `commonjs` mode, and the code generated includes the code like this
```
Object.defineProperty(exports, "__esModule", {value: true});
```

And the `exports` is undefined in some browsers, but the error is swallowed before
this PR, and all tests run successfully, but it is not correct behavior. After this PR,
the code above failed. So we need to compile the source code in `umd` mode.

PR Close #37582
2020-09-08 12:44:18 -07:00
45a73dddfd fix(zone.js): defineProperty patch should not swallow error (#37582)
Close #37432

zone.js monkey patches the `Object.defineProperty` API long time ago
angular/zone.js@383b479
to resolve issues in very old version of Chrome web which override the
property of `CustomElements`, and this is not an issue any longer, so
we want to remove this monkey patch, since it may swallow the errors when the user
want to define property on unconfigurable or frozen object properties.
But currently there are several apps and tests depends on this patch, since
it also change the `configurable` property to `true` by default, so
in this PR we update the logic to not to swallow error any longer unless the property
is the callbacks of `document.registerElements`.

BREAKING CHANGE:

ZoneJS no longer swallows errors produced by `Object.defineProperty` calls.

Prior to this change, ZoneJS monkey patched `Object.defineProperty` and if there is an error
(such as the property is not configurable or not writable) the patched logic swallowed it
and only console.log was produced. This behavior used to hide real errors,
so the logic is now updated to trigger original errors (if any). One exception
where the patch remains in place is `document.registerElement`
(to allow smooth transition for code/polyfills that rely on old behavior in legacy browsers).
If your code relies on the old behavior (where errors were not thrown before),
you may need to update the logic to handle the errors that are no longer masked by ZoneJS patch.

PR Close #37582
2020-09-08 12:44:18 -07:00
687477279b refactor(compiler): move ParsedTemplate interface to compiler (#38594)
Previously this interface was mostly stored in compiler-cli, but it
contains some properties that would be useful for compiling the
"declare component" prelink code.

This commit moves some of the interface over to the compiler
package so that it can be referenced there without creating a
circular dependency between the compiler and compiler-cli.

PR Close #38594
2020-09-08 11:43:25 -07:00
4007422cc6 fix(compiler): correct confusion between field and property names (#38685)
The `R3TargetBinder` accepts an interface for directive metadata which
declares types for `input` and `output` objects. These types convey the
mapping between the property names for an input or output and the
corresponding property name on the component class. Due to
`R3TargetBinder`'s requirements, this mapping was specified with property
names as keys and field names as values.

However, because of duck typing, this interface was accidentally satisifed
by the opposite mapping, of field names to property names, that was produced
in other parts of the compiler. This form more naturally represents the data
model for inputs.

Rather than accept the field -> property mapping and invert it, this commit
introduces a new abstraction for such mappings which is bidirectional,
eliminating the ambiguous plain object type. This mapping uses new,
unambiguous terminology ("class property name" and "binding property name")
and can be used to satisfy both the needs of the binder as well as those of
the template type-checker (field -> property).

A new test ensures that the input/output metadata produced by the compiler
during analysis is directly compatible with the binder via this unambiguous
new interface.

PR Close #38685
2020-09-08 11:43:02 -07:00
1150649139 perf(core): use ngDevMode to tree-shake error messages (#38612)
This commit adds `ngDevMode` guard to throw some errors only in dev mode
(similar to how things work in other parts of Ivy runtime code). The
`ngDevMode` flag helps to tree-shake these error messages from production
builds (in dev mode everything will work as it works right now) to decrease
production bundle size.

PR Close #38612
2020-09-08 11:41:43 -07:00
7869de6136 fix(ngcc): use aliased exported types correctly (#38666)
If a type has been renamed when it was exported, we need to
reference the external public alias name rather than the internal
original name for the type. Otherwise we will try to import the
type by its internal name, which is not publicly accessible.

Fixes #38238

PR Close #38666
2020-09-08 11:41:21 -07:00
2c4a98a285 fix(localize): do not expose NodeJS typings in $localize runtime code (#38700)
A recent change to `@angular/localize` brought in the `AbsoluteFsPath` type
from the `@angular/compiler-cli`. But this brought along with it a reference
to NodeJS typings - specifically the `FileSystem` interface refers to the
`Buffer` type from NodeJS.

This affects compilation of `@angular/localize` code that will be run in
the browser - for example projects that reference `loadTranslations()`.
The compilation breaks if the NodeJS typings are not included in the build.
Clearly it is not desirable to have these typings included when the project
is not targeting NodeJS.

This commit replaces references to the NodeJS `Buffer` type with `Uint8Array`,
which is available across all platforms and is actually the super-class of
`Buffer`.

Fixes #38692

PR Close #38700
2020-09-08 11:40:58 -07:00
92ff6d93eb fix(localize): render location in XLIFF 2 even if there is no metadata (#38713)
Previously, the location of a translation message, in XLIFF 2, was only
rendered if there were also notes for meaning or description. Now the
location will be rendered even if the other metadata is not provided.

Fixes #38705

PR Close #38713
2020-09-08 11:40:35 -07:00
83ace4ed30 refactor(core): remove deprecated ɵɵselect instruction (#38733)
This instruction was deprecated in 664e0015d4
and is no longer referenced in any meaningful
way, so it can be removed.

PR Close #38733
2020-09-08 11:40:12 -07:00
926ffcd8ac fix(router): support lazy loading for empty path named outlets (#38379)
In general, the router only matches and loads a single Route config tree. However,
named outlets with empty paths are a special case where the router can
and should actually match two different `Route`s and ensure that the
modules are loaded for each match.

This change updates the "ApplyRedirects" stage to ensure that named
outlets with empty paths finish loading their configs before proceeding
to the next stage in the routing pipe. This is necessary because if the
named outlet has `loadChildren` but the associated lazy config is not loaded
before following stages attempt to match and activate relevant `Route`s,
an error will occur.

fixes #12842

PR Close #38379
2020-09-08 10:15:21 -07:00
97475d7408 build: upgrade all preview-server JS dependencies to latest versions (#38736)
This commit upgrades all dependencies in `aio/aio-builds-setup/scripts-js/`
to latest versions and also includes all necessary code changes to
ensure the tests are passing with the new dependency versions.

In particular:
- We ensure `nock`'s `Scope#done()` is not called before receiving a
  response to account for a breaking change introduced in
  nock/nock#1960.
- The use of `nock`'s `Scope#log()` method was removed, because the
  method is no longer available since nock/nock#1966. See
  https://github.com/nock/nock#debugging for more info on debugging
  failed matches.

See also
e23ba31b13/migration_guides/migrating_to_13.md
for more info on migrating from `nock` v12 to v13.

PR Close #38736
2020-09-08 10:07:25 -07:00
a29f9a9fb3 fix(dev-infra): change logging of commit message restoration to debug (#38704)
Use debug level of logging for messages in commit message restoration.

PR Close #38704
2020-09-08 10:07:03 -07:00
9f28f82598 docs: add space between icon and text in issue template (#38712)
Closes #37492

PR Close #38712
2020-09-08 10:06:25 -07:00
261f689e9b docs: remove duplicate trans-unit element closing tag (#38715)
PR Close #38715
2020-09-08 10:06:03 -07:00
1d9873c44c docs(zone.js): fix table formatting in markdown (#38723)
PR Close #38723
2020-09-08 10:05:40 -07:00
d9da7e5a18 docs: fix result of sanitization example (#38724)
This is same as #36059 which lost in #36954.
PR Close #38724
2020-09-08 10:04:53 -07:00
79d8795633 docs: fix typos in library guide (#38726)
This PR fixes minor typos in the Creating libraries guide.

PR Close #38726
2020-09-08 10:04:31 -07:00
3e57ca1d98 docs: fix typos in deployment guide (#38727)
This PR fixes some typos regarding the .browserslistrc file in the Deployent guide

PR Close #38727
2020-09-08 10:03:56 -07:00
c2d017de83 docs: word correction (#38729)
PR Close #38729
2020-09-08 10:03:22 -07:00
7baa7ebfc4 docs(core): update CONSTS to DECLS (#38731)
This terminology was changed in d5b87d32b0
but a few instances were missed.

PR Close #38731
2020-09-08 10:02:50 -07:00
4e5286180b docs: fix typo in lightweight injection guide (#38741)
PR Close #38741
2020-09-08 10:02:20 -07:00
73001b42fe docs: remove reverted bug fix from 10.1 change log (#38718)
PR Close #38718
2020-09-08 09:08:27 -07:00
c90eb5450d refactor(compiler-cli): make template parsing errors into diagnostics (#38576)
Previously, the compiler was not able to display template parsing errors as
true `ts.Diagnostic`s that point inside the template. Instead, it would
throw an actual `Error`, and "crash" with a stack trace containing the
template errors.

Not only is this a poor user experience, but it causes the Language Service
to also crash as the user is editing a template (in actuality the LS has to
work around this bug).

With this commit, such parsing errors are converted to true template
diagnostics with appropriate span information to be displayed contextually
along with all other diagnostics. This majorly improves the user experience
and unblocks the Language Service from having to deal with the compiler
"crashing" to report errors.

PR Close #38576
2020-09-03 14:02:35 -07:00
3e97435f1c refactor(compiler-cli): split out template diagnostics package (#38576)
The template type-checking engine includes utilities for creating
`ts.Diagnostic`s for component templates. Previously only the template type-
checker itself created such diagnostics. However, the template parser also
produces errors which should be represented as template diagnostics.

This commit prepares for that conversion by extracting the machinery for
producing template diagnostics into its own sub-package, so that other parts
of the compiler can depend on it without depending on the entire template
type-checker.

PR Close #38576
2020-09-03 14:02:31 -07:00
1c7e5cef3e docs: add dayjs date adapter to resources page (#38031)
PR Close #38031
2020-09-03 12:00:17 -07:00
2cb3d58b42 docs(dev-infra): fix typo in comment (arguements --> arguments) (#38653)
PR Close #38653
2020-09-03 09:45:02 -07:00
44bb85ade4 fix(core): reset tView between tests in Ivy TestBed (#38659)
`tView` that is stored on a component def contains information about directives and pipes
that are available in the scope of this component. Patching component scope causes `tView` to be
updated. Prior to this commit, the `tView` information was not restored/reset in case component
class is not declared in the `declarations` field while calling `TestBed.configureTestingModule`,
thus causing `tView` to be reused between tests (thus preserving scopes information between tests).
This commit updates TestBed logic to preserve `tView` value before applying scope changes and
reset it back to the previous state between tests.

Closes #38600.

PR Close #38659
2020-09-03 09:44:22 -07:00
50f4d8a1ce fix(localize): install @angular/localize in devDependencies by default (#38680)
Previously this package was installed in the default `dependencies` section
of `package.json`, but this meant that its own dependencies are treated as
dependencies of the main project: Babel, for example.

Generally, $localize` is not used at runtime - it is compiled out by the
translation tooling, so there is no need for it to be a full dependency.
In fact, even if it is used at runtime, the package itself is only used
at dev-time since the runtime bits will be bundled into a distributable.
So putting this package in `devDependencies` would only prevent libraries
from bringing the package into application projects that used them. This
is probably good in itself, since it should be up to the downstream project
to decide if it wants to include `@angular/localize` at runtime.

This commit changes the default location of the package to be the
`devDependencies` section, but gives an option `useAtRuntime` to choose
otherwise.

Fixes #38329

PR Close #38680
2020-09-03 09:41:38 -07:00
fdea1804d6 fix(core): remove CollectionChangeRecord symbol (#38668)
Remove CollectionChangeRecord as it was deprecated for removal in v4, use
IterableChangeRecord instead.

BREAKING CHANGE: CollectionChangeRecord has been removed, use IterableChangeRecord
instead

PR Close #38668
2020-09-02 16:45:19 -07:00
1d8c5d88cd refactor(compiler): element.sourceSpan should span the outerHTML (#38581)
Previously, the `sourceSpan` and `startSourceSpan` were the same
object, which meant that you had the following situation:

```
element = <div>some content</div>
sourceSpan = <div>
startSourceSpan = <div>
endSourceSpan = </div>
```

This made `sourceSpan` redundant and meant that if you
wanted a span for the whole element including its content
and closing tag, it had to be computed.

Now `sourceSpan` is separated from `startSourceSpan`
resulting in:

```
element = <div>some content</div>
sourceSpan = <div>some content</div>
startSourceSpan = <div>
endSourceSpan = </div>
```

PR Close #38581
2020-09-02 14:47:31 -07:00
a68f1a78a7 refactor(compiler): element.startSourceSpan is required (#38581)
Previously, the `startSourceSpan` property could be null
but in reality it is always well defined - except for a legacy
case in the old i18n extraction/merging code, where the
typings for source-spans are already being undermined.

Making this property non-null, simplifies code elsewhere
in the project.

PR Close #38581
2020-09-02 14:47:28 -07:00
86e11f1110 refactor(compiler): move the line-ending handling decision (#38581)
Previously the lexer was responsible for deciding whether an "inline"
template should also have its line-endings normalized.

Now this decision is made higher up in the call stack to allow more
flexibility in the parser/lexer.

PR Close #38581
2020-09-02 14:47:25 -07:00
5da1934115 fix(localize): render context of translation file parse errors (#38673)
Previously the position of the error in a translation file when parsing
it was not displayed. Just the error message.

Now the position (line and column) and some context is displayed
along with the error messages.

Fixes #38377

PR Close #38673
2020-09-02 14:46:13 -07:00
86e7cd8117 docs: correct link to chrome status in component style guide (#38682)
Corrects the link to the chromestatus page which errantly linked to features
rather than feature (singular).

Fixes #38676

PR Close #38682
2020-09-02 14:45:20 -07:00
e6ee7c2aeb release: cut the v11.0.0-next.0 release 2020-09-02 13:06:00 -07:00
54687f7765 release: cut the v10.1.0 release 2020-09-02 13:02:58 -07:00
59c234cfb4 build: add configuration for the caretaker command (#38601)
Add configuration information for the new caretaker command

PR Close #38601
2020-09-01 13:05:32 -07:00
a6f3cd93a9 feat(dev-infra): check services/status information of the repository for caretaker (#38601)
The angular team relies on a number of services for hosting code, running CI, etc. This
tool allows for checking the operational status of all services at once as well as the current
state of the repository with respect to merge and triage ready issues and prs.

PR Close #38601
2020-09-01 13:05:30 -07:00
d9fea857db fix(forms): ensure to emit statusChanges on subsequent value update/validations (#38354)
This commit ensures that the `updateValueAndValidity` method takes the
`asyncValidator` into consideration to emit on the `statusChanges` observables.
This is necessary so that any subsequent changes are emitted properly to any
subscribers.

Closes #20424
Closes #14542

BREAKING CHANGE:

Previously if FormControl, FormGroup and FormArray class instances had async validators
defined at initialization time, the status change event was not emitted once async validator
completed. After this change the status event is emitted into the `statusChanges` observable.
If your code relies on the old behavior, you can filter/ignore this additional status change
event.

PR Close #38354
2020-09-01 10:36:31 -07:00
03dbcc7a56 build: update the package.json to 11.0.0-next.0 (#38667)
Update package.json version to reflect master targetting the next major
release train.
2020-09-01 10:35:41 -07:00
c142b071eb build: upgrade cli command docs sources to 32391604b (#38652)
Updating [angular#master](https://github.com/angular/angular/tree/master) from
[cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in
[commit range](ef770f1cb...32391604b):

**Modified**
- help/build.json
- help/generate.json

PR Close #38652
2020-09-01 09:03:25 -07:00
71acf9dd49 docs: Restructure table of contents to provide a more streamlined experience. (#38353)
PR Close #38353
2020-08-31 16:16:54 -07:00
f5a148b1b7 fix(compiler): incorrectly inferring namespace for HTML nodes inside SVG (#38477)
The HTML parser gets an element's namespace either from the tag name
(e.g. `<svg:rect>`) or from its parent element `<svg><rect></svg>`) which
breaks down when an element is inside of an SVG `foreignElement`,
because foreign elements allow nodes from a different namespace to be
inserted into an SVG.

These changes add another flag to the tag definitions which tells child
nodes whether to try to inherit their namespaces from their parents.
It also adds a definition for `foreignObject` with the new flag,
allowing elements placed inside it to infer their namespaces instead.

Fixes #37218.

PR Close #38477
2020-08-31 13:25:38 -07:00
4f28192d62 refactor(dev-infra): use a mixin to require a github-token for an ng-dev command (#38630)
Creates a mixin for requiring a github token to be provided to a command.  This mixin
allows for a centralized management of the requirement and handling of the github-token.

PR Close #38630
2020-08-31 12:32:27 -07:00
0fc2bef0cd docs(service-worker): add links to service worker communication guide (#36847)
PR Close #36847
2020-08-31 11:41:16 -07:00
f5d1e9a2d1 docs(service-worker): add section to explain unrecoverable state (#36847)
PR Close #36847
2020-08-31 11:41:13 -07:00
036a2faf02 feat(service-worker): add UnrecoverableStateError (#36847)
In several occasions it has been observed when the browser has evicted
eagerly cached assets from the cache and which can also not be found on the
server anymore. This can lead to broken state where only parts of the application
will load and others will fail.

This commit fixes this issue by checking for the missing asset in the cache
and on the server. If this condition is true, the broken client will be
notified about the current state through the `UnrecoverableStateError`.

Closes #36539

PR Close #36847
2020-08-31 11:41:11 -07:00
5be4edfa17 fix(service-worker): fix condition to check for a cache-busted request (#36847)
Previously, the condition to make the cache busted was executing although
the network request was successful. However, this is not valid. The cache
should only be marked as busted when the request failed. This commit fixes
the invalid condition.

PR Close #36847
2020-08-31 11:41:09 -07:00
38d6596742 test(service-worker): add helper function remove individual cache (#36847)
This commit adds a helper method to remove individual cached items.

PR Close #36847
2020-08-31 11:41:07 -07:00
0a7a5e3aff docs: Remove confusion between do/avoid templates (#38647)
PR Close #38647
2020-08-31 10:25:16 -07:00
d5fabc303d refactor(forms): remove extra space in error message (#38637)
Remove extra whitespace at package/forms/model.ts error messages

PR Close #38637
2020-08-31 09:31:55 -07:00
ebc0e46501 refactor(dev-infra): improve error message for unexpected version branches (#38622)
Currently the merge script default branch configuration throws an error
if an unexpected version branch is discovered. The error right now
assumes to much knowledge of the logic and the document outlining
the release trains conceptually.

We change it to something more easy to understand that doesn't require
full understanding of the versioning/labeling/branching document that
has been created for the Angular organization.

PR Close #38622
2020-08-31 09:29:58 -07:00
3487b549fd feat(dev-infra): write outputs of command runs to ng-dev log file (#38599)
Creates infrastructure to write outputs of command runs to ng-dev log file.
Additionally, on commands which fail with an exit code greater than 1, an
error log file is created with the posix timestamp of the commands run time
as an identifier.

PR Close #38599
2020-08-31 08:47:15 -07:00
52c7a4bfc6 docs: ng generate module command doc change (#38480)
PR Close #38480
2020-08-31 08:43:19 -07:00
827ba05914 docs: remove first person and space in CircleCI in the testing guide. (#38631)
PR Close #38631
2020-08-31 08:42:04 -07:00
b2857b4e3a docs: remove double space in start-data. (#38642)
PR Close #38642
2020-08-31 08:41:30 -07:00
5d5caf21b8 docs: fix broken markdown in start/start-data (#38644)
PR Close #38644
2020-08-31 08:40:57 -07:00
c1bc070b40 refactor(dev-infra): remove style type from commit style guide (#38639)
The `style` commit type is not part of the commit parser config,
it should be removed from the documentation.

PR Close #38639
2020-08-31 08:40:14 -07:00
930eeaf177 fix(bazel): fix integration test for bazel building (#38629)
Update the API used to request a timestamp.  The previous API we relied on for this
test application, worldclockapi.com no longer serves times and simply 403s on all
requests.  This caused our test to timeout as the HTTP request did not handle a failure
case.  By moving to a new api, the HTTP request responds as expected and timeouts
are corrected as there is not longer a pending microtask in the queue.

PR Close #38629
2020-08-28 11:16:40 -07:00
2dd29fbae7 build: update ng-dev merge config to reflect new label updates (#38620)
Update the ng-dev merge configuration to reflect the new label updates

PR Close #38620
2020-08-28 08:03:21 -07:00
9613660fee ci: update angular robot to be based on new label updates (#38620)
Update the angular robot configuration to reflect the new label updates

PR Close #38620
2020-08-28 08:03:19 -07:00
c0523fc3b4 docs(forms): exclude internal-only methods and properties from docs (#38583)
Prior to this commit, a lot of internal-only class properties and methods (such as `ngOnChanges`)
of the Forms package directives were exposed on angular.io website. These fields are not expected
to be called externally (they are used/invoked by framework only), since they are part of internal
implementations of the following interfaces:

* Angular lifecycle hook interfaces
* ControlValueAccessor interface
* Validator interface

Having these internal-only fields in docs creates unnecessary noise on directive detail pages.
This commit adds the `@nodoc` annotation to these properties and methods to keep fields in the
golden files, but hide them in docs.

PR Close #38583
2020-08-27 16:39:38 -07:00
de1cffb23b build: update the package.json to 10.2.0-next.0
When the rc was cut for 10.1.0-rc.0, the package.json for master should be updated
to to the following next version, in this case 10.2.0-next.0.
2020-08-27 15:59:52 -07:00
31f4557621 ci: update github robot to reflect new target labels (#38428)
Updates the Github robot to reflect the updated target
labels that are used as part of the canonical versioning
and labeling for the Angular organization.

PR Close #38428
2020-08-27 14:52:44 -07:00
7723bfd9ba build: use new labeling and branching in merge script (#38428)
We introduced a new shared configuration for merge script
labels that follow the proposal of:
https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU

These label semantics and the branching are set up for the Angular
framework with this commit. The goal is that labeling and merging
is consistent between all Angular projects and that clear rules
are defined for branching. This was previously not the case.

PR Close #38428
2020-08-27 14:52:42 -07:00
e8ea839df8 docs: update docs to reflect new PR targeting methods for release trains (#38401)
As part of the migration to a common strategy/method for branching and releasing across
the main angular repositories, updates need to be made to the documentation. These changes
reflect the updates made and is based on the following document which describes the
merging label expectations: https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU

PR Close #38401
2020-08-27 14:52:04 -07:00
90cec40cce build: bump to lastest sha of angular/dev-infra's lock-closed action (#38615)
Update to the latest lock-closed action to fix the link which is used.

PR Close #38615
2020-08-27 10:58:29 -07:00
4036281007 docs: Update contributor info for kyliau (#38125)
Added twitter handle, website, and a short bio.

PR Close #38125
2020-08-27 10:39:30 -07:00
164cd274a4 test(docs-infra): add commands to run the unit tests (#34537)
This commit adds the necessary custom commands to run the tests in a
node environment.

PR Close #34537
2020-08-27 09:05:59 -07:00
fedcfec346 test(docs-infra): add missing tests for obserables and promises (#34537)
This commit adds missing tests for obserables and promises which
are both stand-alone mini-apps.

PR Close #34537
2020-08-27 09:05:56 -07:00
618cb32407 docs: add Sam Vloeberghs to GDE list (#37970)
PR Close #37970
2020-08-26 12:52:56 -07:00
4aee0087ea docs: remove outdated CircleCI link from DEVELOPER.md (#38554)
CircleCI updated their UI and now the URLs are different (and cannot be
constructed based on the build number alone). This commit removes a
reference of the obsolete URL pattern to avoid confusion.

Example old URL:
https://circleci.com/gh/angular/angular/<build-number>#artifacts

Example new URL:
https://app.circleci.com/pipelines/github/angular/angular/<build-number>/workflows/<workflow-id>/jobs/<job-id>/artifacts

PR Close #38554
2020-08-26 12:52:26 -07:00
0681a20d28 fix(docs-infra): add guard to not render anchor link for private api (#38589)
This commit adds a guard that prevents rendering anchor links for
private api's.

Closes #38564

PR Close #38589
2020-08-26 12:51:04 -07:00
fb06903237 release: cut the v10.1.0-rc.0 release 2020-08-26 11:57:57 -07:00
ecc6fd0d28 docs: release notes for the v10.0.14 release 2020-08-26 11:51:32 -07:00
80cab26023 docs: Minor fixes in NgModules section (#36177)
Apply minor fixes to various guides of the NgModules section

PR Close #36177
2020-08-25 15:24:02 -07:00
841dfa68f9 docs: typo fixes in the component testing scenarios guide (#38574)
Fixed some typos and removed a warning about limitation of the `fakeAsync` that is already mentioned in a helpful alert

PR Close #38574
2020-08-25 15:16:53 -07:00
f0af387f6c fix(localize): ensure required XLIFF parameters are serialized (#38575)
When extracting i18n messages from source code, the XLIFF
serializers were missing some required attributes on the `<file>`
element.

This commit re-introduces the `original` property to each of XLIFF 1.2
and 2.0 serializers. Also it adds in the required `id` property for the
XLIFF 2.0 seralizer.

Fixes #38570

PR Close #38575
2020-08-25 15:14:19 -07:00
14e90bef58 fix(localize): render text of extracted placeholders (#38536)
Formats like XLIFF allow the text of the original source to
be included as metadata. This commit fixes the message
extractor to also render this text when available.

PR Close #38536
2020-08-25 15:13:23 -07:00
db3a21b382 refactor(localize): add placeholder locations in extracted messages (#38536)
Some translation file formats would like to be able to render the
text of placeholders taken from the original source files. This commit
adds this information to the extracted messages so that it can be
used in translation file serializers.

PR Close #38536
2020-08-25 15:13:20 -07:00
b8351f3b10 refactor(localize): ensure that translate plugin exceptions are not swallowed (#38536)
Previously, exceptions that were not `BabelParseError`s were just ignored.
Such exceptions are most likely programming errors in the package.
They are now re-thrown to ensure that the error is not hidden.

PR Close #38536
2020-08-25 15:13:17 -07:00
81053d3160 refactor(localize): run the translate plugin tests in mock FileSystems (#38536)
This commit is a tidy up of the translate plugin unit tests, but also ensures
that the tests are run in the context of a mock FileSystem. This ensures
that the tests are resilient to future refactors of the plugins that will
require a FileSystem to be initialized.

PR Close #38536
2020-08-25 15:13:15 -07:00
bdba1a062d refactor(localize): include text in original location of extracted messages (#38536)
When extracting messages, source-mapping information is used to find
the original location of the message being extracted. This commit will
now include the text from the original source in the message location
so that it can be serialized into the translation file.

PR Close #38536
2020-08-25 15:13:12 -07:00
23f855b300 refactor(localize): allow ParsedMessage to hold additional location data (#38536)
In preparation for supporting `equiv-text` placeholder information in
extracted translation files, this commit adds these optional properties
to the `ParsedMessage` interface and updates `parseMessage()` to
be able to store them.

PR Close #38536
2020-08-25 15:13:09 -07:00
94a3e0e81d docs: add correct path for karma.conf.js file (#38571)
In the latest Angular CLI versions, the `karma.conf.js` file resides in the root folder of the Angular CLI project.

PR Close #38571
2020-08-25 09:56:32 -07:00
9cbde86534 docs: fix typo in the testing component basics guide (#38573)
The guide ends with a sentence that implies there are more tests following the end of the guide.

PR Close #38573
2020-08-25 09:55:59 -07:00
18e474f522 fix(zone.js): zone.js toString patch should check typeof Promise is function (#38350)
Close #38361

zone.js monkey patch toString, and check the instance is `Promise` or not by using `instanceof Promise`,
sometimes when Promise is not available, the `instanceof` operation fails
and throw `TypeError: Right-hand side of 'instanceof' is not an object`
this PR check `typeof Promise` equals to function or not to prevent the error.

PR Close #38350
2020-08-25 09:51:50 -07:00
cb3db0d31b release: clean up changelog 2020-08-24 15:53:55 -07:00
d36828a7a1 release: cut the v10.1.0-next.8 release 2020-08-24 15:38:13 -07:00
f18e2d5898 docs: release notes for the v10.0.12 release 2020-08-24 15:31:03 -07:00
375f0a6f67 build: update tslint to 6.1.3 (#38076)
This version supports TypeScript 4.0

PR Close #38076
2020-08-24 13:07:05 -07:00
281b647f15 refactor(compiler-cli): remove usage of ts.updateIdentifier (#38076)
With Typescript 4, `ts.updateIdentifier` is no longer available.
Calling `ts.updateIdentifier` used to return the same node when
`typeArguments` was `undefined` because `node.typeArguments`
was also `undefined`.

Relevant TS code:
```js
function updateIdentifier(node, typeArguments) {
  return node.typeArguments !== typeArguments
      ? updateNode(createIdentifier(ts.idText(node), typeArguments), node)
      : node;
}
```

PR Close #38076
2020-08-24 13:07:02 -07:00
0fc44e0436 feat(compiler-cli): add support for TypeScript 4.0 (#38076)
With this change we add support for TypeScript 4.0

PR Close #38076
2020-08-24 13:06:59 -07:00
201a546af8 perf(forms): use internal ngDevMode flag to tree-shake error messages in prod builds (#37821)
This commit adds a guard before throwing any forms errors. This will tree-shake
error messages which cannot be minified. It should also help to reduce the
bundle size of the `forms` package in production by ~20%.

Closes #37697

PR Close #37821
2020-08-24 09:26:28 -07:00
6e643d9874 docs(localize): fix angular.json syntax (#38553)
In chapter internationalization (i18n) at section "Deploy multiple locales" the syntax for angular.json is wrong.
This commit fixes the angular.json, when specifying the translation file and the baseHref for a locale.

PR Close #38553
2020-08-24 09:25:35 -07:00
4985267211 test(language-service): [Ivy] return cursor position in overwritten template (#38552)
In many testing scenarios, there is a common pattern:

1. Overwrite template (inline or external)
2. Find cursor position
3. Call one of language service APIs
4. Inspect spans in result

In order to faciliate this pattern, this commit refactors
`MockHost.overwrite()` and `MockHost.overwriteInlineTemplate()` to
allow a faux cursor symbol `¦` to be injected into the template, and
the methods will automatically remove it before updating the script snapshot.
Both methods will return the cursor position and the new text without
the cursor symbol.

This makes testing very convenient. Here's a typical example:

```ts
const {position, text} = mockHost.overwrite('template.html', `{{ ti¦tle }}`);
const quickInfo = ngLS.getQuickInfoAtPosition('template.html', position);
const {start, length} = quickInfo!.textSpan;
expect(text.substring(start, start + length)).toBe('title');
```

PR Close #38552
2020-08-24 09:25:04 -07:00
b48cc6ead5 feat(language-service): introduce hybrid visitor to locate AST node (#38540)
This commit introduces two visitors, one for Template AST and the other
for Expression AST to allow us to easily find the node that most closely
corresponds to a given cursor position.

This is crucial because many language service APIs take in a `position`
parameter, and the information returned depends on how well we can find
a good candidate node.

In View Engine implementation of language service, the search for the node
and the processing of information to return the result are strongly coupled.
This makes the code hard to understand and hard to debug because the stack
trace is often littered with layers of visitor calls.

With this new feature, we could test the "searching" part separately and
colocate all the logic (aka hacks) that's required to retrieve an accurate
span for a given node.

Right now, only the most "narrow" node is returned by the main exported
function `findNodeAtPosition`. If needed, we could expose the entire AST
path, or expose other methods to provide more context for a node.

Note that due to limitations in the template AST interface, there are
a few known cases where microsyntax spans are not recorded properly.
This will be dealt with in a follow-up PR.

PR Close #38540
2020-08-24 09:24:18 -07:00
874792dc43 feat(compiler): support unary operators for more accurate type checking (#37918)
Prior to this change, the unary + and - operators would be parsed as `x - 0`
and `0 - x` respectively. The runtime semantics of these expressions are
equivalent, however they may introduce inaccurate template type checking
errors as the literal type is lost, for example:

```ts
@Component({
  template: `<button [disabled]="isAdjacent(-1)"></button>`
})
export class Example {
  isAdjacent(direction: -1 | 1): boolean { return false; }
}
```

would incorrectly report a type-check error:

> error TS2345: Argument of type 'number' is not assignable to parameter
  of type '-1 | 1'.

Additionally, the translated expression for the unary + operator would be
considered as arithmetic expression with an incompatible left-hand side:

> error TS2362: The left-hand side of an arithmetic operation must be of
  type 'any', 'number', 'bigint' or an enum type.

To resolve this issues, the implicit transformation should be avoided.
This commit adds a new unary AST node to represent these expressions,
allowing for more accurate type-checking.

Fixes #20845
Fixes #36178

PR Close #37918
2020-08-21 12:25:53 -07:00
e7da4040d6 fix(compiler-cli): adding references to const enums in runtime code (#38542)
We had a couple of places where we were assuming that if a particular
symbol has a value, then it will exist at runtime. This is true in most cases,
but it breaks down for `const` enums.

Fixes #38513.

PR Close #38542
2020-08-21 12:23:21 -07:00
2a643e1ab6 docs: change function name from async -> waitForAsync (#38548)
async function name was changed to waitForAsync but it was left in testing-utility-api
file.

PR Close #38548
2020-08-21 12:17:51 -07:00
364284b0dc fix(dev-infra): ignore comments when validating commit messages (#38438)
When creating a commit with the git cli, git pre-populates the editor
used to enter the commit message with some comments (i.e. lines starting
with `#`). These comments contain helpful instructions or information
regarding the changes that are part of the commit. As happens with all
commit message comments, they are removed by git and do not end up in
the final commit message.

However, the file that is passed to the `commit-msg` to be validated
still contains these comments. This may affect the outcome of the commit
message validation. In such cases, the author will not realize that the
commit message is not in the desired format until the linting checks
fail on CI (which validates the final commit messages and is not
affected by this issue), usually several minutes later.

Possible ways in which the commit message validation outcome can be
affected:
- The minimum body length check may pass incorrectly, even if there is
  no actual body, because the comments are counted as part of the body.
- The maximum line length check may fail incorrectly due to a very long
  line in the comments.

This commit fixes the problem by removing comment lines before
validating a commit message.

Fixes #37865

PR Close #38438
2020-08-21 12:17:14 -07:00
956b25a100 docs: apply code styling in template reference variables guide (#38522)
PR Close #38522
2020-08-20 13:01:33 -07:00
8017ca4db3 fix(docs-infra): fix vertical alignment of external link icons (#38410)
At some places external link icons appear as a subscript. For example
8366effeec/aio/content/guide/roadmap.md\#L37
this commit places external link icons in the middle to improve there
positioning in a line.

PR Close #38410
2020-08-20 09:40:01 -07:00
22f1ac3e37 docs: udpate the details (#37967)
updating my twitter handle and bio as it is changed from
Angular and Web Tech to Angular also the
twitter handle is changed to SantoshYadavDev

PR Close #37967
2020-08-20 09:38:58 -07:00
4ee5e730ab build: upgrade cli command docs sources to ef770f1cb (#38546)
Updating [angular#master](https://github.com/angular/angular/tree/master) from
[cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in
[commit range](b0b27361d...ef770f1cb):

**Modified**
- help/build.json
- help/generate.json
- help/test.json
- help/xi18n.json

PR Close #38546
2020-08-20 09:32:11 -07:00
6442875c99 docs(core): Fix typo in JSDoc for AbstractType<T> (#38541)
PR Close #38541
2020-08-20 09:30:17 -07:00
8f24bc9443 Revert "fix(router): support lazy loading for empty path named outlets (#38379)"
This reverts commit 7ad32649c0.
2020-08-19 21:05:31 -07:00
ac461e1efd fix(localize): extract the correct message ids (#38498)
Previously, if `useLegacyIds` was enabled, the message extractor
was always rendering the legacy message ids in translation
files even if an explicit "custom message id" had been provided
in the original message.

PR Close #38498
2020-08-19 14:19:41 -07:00
f245c6bb15 fix(core): remove closing body tag from inert DOM builder (#38454)
Fix a bug in the HTML sanitizer where an unclosed iframe tag would
result in an escaped closing body tag as the output:

_sanitizeHtml(document, '<iframe>') => '&lt;/body&gt;'

This closing body tag comes from the DOMParserHelper where the HTML to be
sanitized is wrapped with surrounding body tags. When an opening iframe
tag is parsed by DOMParser, which DOMParserHelper uses, everything up
until its matching closing tag is consumed as a text node. In the above
example this includes the appended closing body tag.

By removing the explicit closing body tag from the DOMParserHelper and
relying on the body tag being closed implicitly at the end, the above
example is sanitized as expected:

_sanitizeHtml(document, '<iframe>') => ''

PR Close #38454
2020-08-19 14:18:44 -07:00
68a9a01a64 fix(localize): parse all parts of a translation with nested HTML (#38452)
Previously nested container placeholders (i.e. HTML elements) were
not being fully parsed from translation files. This resulted in bad
translation of messages that contain these placeholders.

Note that this causes the canonical message ID to change for
such messages. Currently all messages generated from
templates use "legacy" message ids that are not affected by
this change, so this fix should not be seen as a breaking change.

Fixes #38422

PR Close #38452
2020-08-19 14:16:41 -07:00
8cd4099db9 fix(localize): include the last placeholder in parsed translation text (#38452)
When creating a `ParsedTranslation` from a set of message parts and
placeholder names a textual representation of the message is computed.
Previously the last placeholder and text segment were missing from this
computed message string.

PR Close #38452
2020-08-19 14:16:38 -07:00
0b54c0c6b4 refactor(compiler-cli): add getTemplateOfComponent to TemplateTypeChecker (#38355)
This commit adds a `getTemplateOfComponent` method to the
`TemplateTypeChecker` API, which retrieves the actual nodes parsed and used
by the compiler for template type-checking. This is advantageous for the
language service, which may need to query other APIs in
`TemplateTypeChecker` that require the same nodes used to bind the template
while generating the TCB.

Fixes #38352

PR Close #38355
2020-08-19 14:07:03 -07:00
1ec609946f docs: Typos fixes in the binding syntax guide (#38519)
PR Close #38519
2020-08-19 14:05:48 -07:00
7ad32649c0 fix(router): support lazy loading for empty path named outlets (#38379)
In general, the router only matches and loads a single Route config tree. However,
named outlets with empty paths are a special case where the router can
and should actually match two different `Route`s and ensure that the
modules are loaded for each match.

This change updates the "ApplyRedirects" stage to ensure that named
outlets with empty paths finish loading their configs before proceeding
to the next stage in the routing pipe. This is necessary because if the
named outlet has `loadChildren` but the associated lazy config is not loaded
before following stages attempt to match and activate relevant `Route`s,
an error will occur.

fixes #12842

PR Close #38379
2020-08-19 11:36:06 -07:00
9ad69c1503 release: cut the zone.js-0.11.1 release (#38537)
PR Close #38537
2020-08-19 10:50:46 -07:00
9af2de821c release: cut the v10.1.0-next.7 release 2020-08-19 09:35:47 -07:00
0270020ac2 docs: release notes for the v10.0.11 release 2020-08-19 09:16:16 -07:00
6b662d10c1 fix(zone.js): zone.js package.json should not include files/directories field (#38528)
Close #38526, #38516, #38513

After update to `APF`, the `directories` and `files` options are not compatible,
so we need to remove those fileds to make sure everything work as expected.

PR Close #38528
2020-08-19 09:06:28 -07:00
55fd725e74 docs: Fix typo in the inputs and outputs guide (#38524)
PR Close #38524
2020-08-19 08:27:44 -07:00
f77fd5e02a feat(dev-infra): create a wizard for building commit messages (#38457)
Creates a wizard to walk through creating a commit message in the correct
template for commit messages in Angular repositories.

PR Close #38457
2020-08-18 17:01:14 -07:00
63ba74fe4e feat(dev-infra): tooling to check out pending PR (#38474)
Creates a tool within ng-dev to checkout a pending PR from the upstream repository.  This automates
an action that many developers on the Angular team need to do periodically in the process of testing
and reviewing incoming PRs.

Example usage:
  ng-dev pr checkout <pr-number>

PR Close #38474
2020-08-18 16:22:47 -07:00
aaa1d8e2fe release: cut the zone.js-0.11.0 release (#38473)
PR Close #38473
2020-08-18 11:47:23 -07:00
dbfb50e9f4 fix(router): ensure routerLinkActive updates when associated routerLinks change (#38511)
This commit introduces a new subscription in the `routerLinkActive` directive which triggers an update
when any of its associated routerLinks have changes. `RouterLinkActive` not only needs to know when
links are added or removed, but it also needs to know about if a link it already knows about
changes in some way.

Quick note that `from...mergeAll` is used instead of just a simple
`merge` (or `scheduled...mergeAll`) to avoid introducing new rxjs
operators in order to keep bundle size down.

Fixes #18469

PR Close #38511
2020-08-18 10:21:49 -07:00
bee44b3359 Revert "fix(router): ensure routerLinkActive updates when associated routerLinks change (#38349)" (#38511)
This reverts commit e0e5c9f195.
Failures in Google tests were detected.

PR Close #38511
2020-08-18 10:21:47 -07:00
723a9ff095 docs(common): Wrong parameter description on TrackBy (#38495)
Track By Function receive the T[index] data, not the node id.
TrackByFunction reference description has the same issue.
PR Close #38495
2020-08-18 10:08:44 -07:00
e472f5f688 refactor(ngcc): update yargs and typings for yargs (#38470)
Updating yargs and typings for the updated yargs module.

PR Close #38470
2020-08-17 15:30:33 -07:00
8373b720f3 refactor(localize): update yargs and typings for yargs (#38470)
Updating yargs and typings for the updated yargs module.

PR Close #38470
2020-08-17 15:30:32 -07:00
301513311e refactor(dev-infra): update yargs and typings for yargs (#38470)
Updating yargs and typings for the updated yargs module.

PR Close #38470
2020-08-17 15:30:32 -07:00
64cf087ae5 release: cut the v10.1.0-next.6 release 2020-08-17 13:23:09 -07:00
fec9dcbeb0 docs: release notes for the v10.0.10 release 2020-08-17 13:19:03 -07:00
e0e5c9f195 fix(router): ensure routerLinkActive updates when associated routerLinks change (#38349)
This commit introduces a new subscription in the `routerLinkActive` directive which triggers an update
when any of its associated routerLinks have changes. `RouterLinkActive` not only needs to know when
links are added or removed, but it also needs to know about if a link it already knows about
changes in some way.

Quick note that `from...mergeAll` is used instead of just a simple
`merge` (or `scheduled...mergeAll`) to avoid introducing new rxjs
operators in order to keep bundle size down.

Fixes #18469

PR Close #38349
2020-08-17 12:33:59 -07:00
cfe424e875 refactor(language-service): [Ivy] remove temporary compiler (#38310)
Now that Ivy compiler has a proper `TemplateTypeChecker` interface
(see https://github.com/angular/angular/pull/38105) we no longer need to
keep the temporary compiler implementation.

The temporary compiler was created to enable testing infrastructure to
be developed for the Ivy language service.

This commit removes the whole `ivy/compiler` directory and moves two
functions `createTypeCheckingProgramStrategy` and
`getOrCreateTypeCheckScriptInfo` to the `LanguageService` class.

Also re-enable the Ivy LS test since it's no longer blocking development.

PR Close #38310
2020-08-17 11:30:33 -07:00
3b9c802dee fix(ngcc): detect synthesized delegate constructors for downleveled ES2015 classes (#38463)
Similarly to the change we landed in the `@angular/core` reflection
capabilities, we need to make sure that ngcc can detect pass-through
delegate constructors for classes using downleveled ES2015 output.

More details can be found in the preceding commit, and in the issue
outlining the problem: #38453.

Fixes #38453.

PR Close #38463
2020-08-17 10:55:40 -07:00
ca07da4563 fix(core): detect DI parameters in JIT mode for downleveled ES2015 classes (#38463)
In the Angular Package Format, we always shipped UMD bundles and previously even ES5 module output.
With V10, we removed the ES5 module output but kept the UMD ES5 output.

For this, we were able to remove our second TypeScript transpilation. Instead we started only
building ES2015 output and then downleveled it to ES5 UMD for the NPM packages. This worked
as expected but unveiled an issue in the `@angular/core` reflection capabilities.

In JIT mode, Angular determines constructor parameters (for DI) using the `ReflectionCapabilities`. The
reflection capabilities basically read runtime metadata of classes to determine the DI parameters. Such
metadata can be either stored in static class properties like `ctorParameters` or within TypeScript's `design:params`.

If Angular comes across a class that does not have any parameter metadata, it tries to detect if the
given class is actually delegating to an inherited class. It does this naively in JIT by checking if the
stringified class (function in ES5) matches a certain pattern. e.g.

```js
function MatTable() {
  var _this = _super.apply(this, arguments) || this;
```

These patterns are reluctant to changes of the class output. If a class is not recognized properly, the
DI parameters will be assumed empty and the class is **incorrectly** constructed without arguments.

This actually happened as part of v10 now. Since we downlevel ES2015 to ES5 (instead of previously
compiling sources directly to ES5), the class output changed slightly so that Angular no longer detects
it. e.g.

```js
var _this = _super.apply(this, __spread(arguments)) || this;
```

This happens because the ES2015 output will receive an auto-generated constructor if the class
defines class properties. This constructor is then already containing an explicit `super` call.

```js
export class MatTable extends CdkTable {
    constructor() {
        super(...arguments);
        this.disabled = true;
    }
}
```

If we then downlevel this file to ES5 with `--downlevelIteration`, TypeScript adjusts the `super` call so that
the spread operator is no longer used (not supported in ES5). The resulting super call is different to the
super call that would have been emitted if we would directly transpile to ES5. Ultimately, Angular no
longer detects such classes as having an delegate constructor -> and DI breaks.

We fix this by expanding the rather naive RegExp patterns used for the reflection capabilities
so that downleveled pass-through/delegate constructors are properly detected. There is a risk
of a false-positive as we cannot detect whether `__spread` is actually the TypeScript spread
helper, but given the reflection patterns already make lots of assumptions (e.g. that `super` is
actually the superclass, we should be fine making this assumption too. The false-positive would
not result in a broken app, but rather in unnecessary providers being injected (as a noop).

Fixes #38453

PR Close #38463
2020-08-17 10:55:37 -07:00
81c3e809aa fix(localize): render ICU placeholders in extracted translation files (#38484)
Previously placeholders were only rendered for dynamic interpolation
expressons in `$localize` tagged strings. But there are also potentially
dynamic values in ICU expressions too, so we need to render these as
placeholders when extracting i18n messages into translation files.

PR Close #38484
2020-08-17 10:44:26 -07:00
be96510ce9 test(compiler): add additional i18n serialization tests (#38484)
The addiational tests check that ICUs containing interpolations
are serialized correctly.

PR Close #38484
2020-08-17 10:44:24 -07:00
cb05c0102f fix(core): move generated i18n statements to the consts field of ComponentDef (#38404)
This commit updates the code to move generated i18n statements into the `consts` field of
ComponentDef to avoid invoking `$localize` function before component initialization (to better
support runtime translations) and also avoid problems with lazy-loading when i18n defs may not
be present in a chunk where it's referenced.

Prior to this change the i18n statements were generated at the top leve:

```
var I18N_0;
if (typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode) {
    var MSG_X = goog.getMsg(“…”);
    I18N_0 = MSG_X;
} else {
    I18N_0 = $localize('...');
}

defineComponent({
    // ...
    template: function App_Template(rf, ctx) {
        i0.ɵɵi18n(2, I18N_0);
    }
});
```

This commit updates the logic to generate the following code instead:

```
defineComponent({
    // ...
    consts: function() {
        var I18N_0;
        if (typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode) {
            var MSG_X = goog.getMsg(“…”);
            I18N_0 = MSG_X;
        } else {
            I18N_0 = $localize('...');
        }
        return [
            I18N_0
        ];
    },
    template: function App_Template(rf, ctx) {
        i0.ɵɵi18n(2, 0);
    }
});
```

Also note that i18n template instructions now refer to the `consts` array using an index
(similar to other template instructions).

PR Close #38404
2020-08-17 10:13:57 -07:00
5f90b64328 refactor(compiler): i18n compiler tests refactoring (#38404)
This commit refactors i18n compiler tests to avoid code duplication and simplify further maintenance and updates.

PR Close #38404
2020-08-17 10:13:55 -07:00
71079ce47e fix(common): Allow scrolling when browser supports scrollTo (#38468)
This commit fixes a regression from "fix(common): ensure
scrollRestoration is writable (#30630)" that caused scrolling to not
happen at all in browsers that do not support scroll restoration. The
issue was that `supportScrollRestoration` was updated to return `false`
if a browser did not have a writable `scrollRestoration`. However, the
previous behavior was that the function would return `true` if
`window.scrollTo` was defined. Every scrolling function in the
`ViewportScroller` used `supportScrollRestoration` and, with the update
in bb88c9fa3d, no scrolling would be
performed if a browser did not have writable `scrollRestoration` but
_did_ have `window.scrollTo`.

Note, that this failure was detected in the saucelabs tests. IE does not
support scroll restoration so IE tests were failing.

PR Close #38468
2020-08-14 11:41:22 -07:00
ca798804b2 fix(router): export DefaultRouteReuseStrategy to Router public_api (#31575)
export DefaultRouteStrategy class that was used internally and exposed, and add documentation for each one of methods

PR Close #31575
2020-08-13 16:02:41 -07:00
b071495f92 fix(core): fix multiple nested views removal from ViewContainerRef (#38317)
When removal of one view causes removal of another one from the same
ViewContainerRef it triggers an error with views length calculation. This commit
fixes this bug by removing a view from the list of available views before invoking
actual view removal (which might be recursive and relies on the length of the list
of available views).

Fixes #38201.

PR Close #38317
2020-08-13 13:35:53 -07:00
Ahn
d5f819ebc1 style(compiler-cli): remove unused constant (#38441)
Remove unused constant allDiagnostics

PR Close #38441
2020-08-13 13:32:41 -07:00
1388c1761f perf(compiler-cli): don't emit template guards when child scope is empty (#38418)
For a template that contains for example `<span *ngIf="first"></span>`
there's no need to render the `NgIf` guard expression, as the child
scope does not have any type-checking statements, so any narrowing
effect of the guard is not applicable.

This seems like a minor improvement, however it reduces the number of
flow-node antecedents that TypeScript needs to keep into account for
such cases, resulting in an overall reduction of type-checking time.

PR Close #38418
2020-08-13 13:28:46 -07:00
fb8f4b4d72 perf(compiler-cli): only generate directive declarations when used (#38418)
The template type-checker would always generate a directive declaration
even if its type was never used. For example, directives without any
input nor output bindings nor exportAs references don't need the
directive to be declared, as its type would never be used.

This commit makes the `TcbOp`s that are responsible for declaring a
directive as optional, such that they are only executed when requested
from another operation.

PR Close #38418
2020-08-13 13:28:44 -07:00
f42e6ce917 perf(compiler-cli): only generate type-check code for referenced DOM elements (#38418)
The template type-checker would generate a statement with a call
expression for all DOM elements in a template of the form:

```
const _t1 = document.createElement("div");
```

Profiling has shown that this is a particularly expensive call to
perform type inference on, as TypeScript needs to perform signature
selection of `Document.createElement` and resolve the exact type from
the `HTMLElementTagNameMap`. However, it can be observed that the
statement by itself does not contribute anything to the type-checking
result if `_t1` is not actually used anywhere, which is only rarely the
case---it requires that the element is referenced by its name from
somewhere else in the template. Consequently, the type-checker can skip
generating this statement altogether for most DOM elements.

The effect of this optimization is significant in several phases:
1. Less type-check code to generate
2. Less type-check code to emit and parse again
3. No expensive type inference to perform for the call expression

The effect on phase 3 is the most significant here, as type-checking is
not currently incremental in the sense that only phases 1 and 2 can
be reused from a prior compilation. The actual type-checking of all
templates in phase 3 needs to be repeated on each incremental
compilation, so any performance gains we achieve here are very
beneficial.

PR Close #38418
2020-08-13 13:28:42 -07:00
175c79d1d8 test(docs-infra): remove deprecated ReflectiveInjector (#38408)
This commit replaces the old and slow `ReflectiveInjector` that was
deprecated in v5 with the new `Injector`. Note: This change was only
done in the spec files inside the `aio` folder.

While changing this, it was not possible to directly use `Injector.get`
to get the correct typing for the mocked classes. For example:

```typescript
locationService = injector.get<TestLocationService>(LocationService);
```

Fails with:

> Argument of type 'typeof LocationService' is not assignable to parameter
of type 'Type<TestLocationService> | InjectionToken<TestLocationService> |
AbstractType<TestLocationService>'.
  Type 'typeof LocationService' is not assignable to type 'Type<TestLocationService>'.
    Property 'searchResult' is missing in type 'LocationService' but required in type
    'TestLocationService'.

Therefore, it was necessary to first convert to `unknown` and then to
`TestLocationService`.

```typescript
locationService = injector.get(LocationService) as unknown as TestLocationService;
```

PR Close #38408
2020-08-13 12:56:13 -07:00
945751e2e8 ci: disable closure size tracking test (#38449)
We should define ngDevMode to false in Closure, but --define only works in the global scope.
With ngDevMode not being set to false, this size tracking test provides little value but a lot of
headache to continue updating the size.

PR Close #38449
2020-08-13 11:41:13 -07:00
b769771d60 refactor(router): Add annotations to correct Router documentation (#38448)
The `@HostListener` functions and lifecycle hooks aren't intended to be public API but
do need to appear in the `.d.ts` files or type checking will break. Adding the
nodoc annotation will correctly hide this function on the docs site.

Again, note that `@internal` cannot be used because the result would be
that the functions then do not appear in the `.d.ts` files. This would
break lifecycle hooks because the class would be seen as not
implementing the interface correctly. This would also break
`HostListener` because the compiled templates would attempt to call the
`onClick` functions, but those would also not appear in the `d.ts` and
would produce errors like "Property 'onClick' does not exist on type 'RouterLinkWithHref'".

PR Close #38448
2020-08-13 11:36:10 -07:00
a80f654af9 fix(core): error if CSS custom property in host binding has number in name (#38432)
Fixes an error if a CSS custom property, used inside a host binding, has a
number in its name. The error is thrown because the styling parser only
expects characters from A to Z,dashes, underscores and a handful of other
characters.

Fixes #37292.

PR Close #38432
2020-08-13 10:35:07 -07:00
aa847cb014 build: run browsers tests on chromium locally (#38435)
Previously we added a browser target for `firefox` into the
dev-infra package. It looks like as part of this change, we
accidentally switched the local web testing target to `firefox`.

Web tests are not commonly run locally as we use Domino and
NodeJS tests for primary development. Sometimes though we intend
to run tests in a browser. This would currently work with Firefox
but not on Windows (as Firefox is a noop there in Bazel).

This commit switches the primary browser back to `chromium`. Also
Firefox has been added as a second browser to web testing targets.

This allows us to reduce browsers in the legacy Saucelabs job. i.e.
not running Chrome and Firefox there. This should increase stability
and speed up the legacy job (+ reduced rate limit for Saucelabs).

PR Close #38435
2020-08-13 09:37:02 -07:00
8763d8201c build: update ng-dev config file for new commit message configuration (#38430)
Removes the commit message types from the config as they are now staticly
defined in the dev-infra code.

PR Close #38430
2020-08-13 09:11:19 -07:00
9f7a37b4e9 feat(dev-infra): migrate to unified commit message types in commit message linting (#38430)
Previously commit message types were provided as part of the ng-dev config in the repository
using the ng-dev toolset.  This change removes this configuration expectation and instead
predefines the valid types for commit messages.

Additionally, with this new unified set of types requirements around providing a scope have
been put in place.  Scopes are either required, optional or forbidden for a given commit
type.

PR Close #38430
2020-08-13 09:11:17 -07:00
773f7908c0 feat(dev-infra): update to latest benchpress version (#38440)
We recently updated the benchpress package to have a more loose
Angular core peer dependency, and less other unused dependencies.

We should make sure to use that in the dev-infra package so that
peer dependencies can be satisified in consumer projects, and so
that less unused dependencies are brought into projects.

PR Close #38440
2020-08-13 09:09:31 -07:00
f4ced74e3a feat(dev-infra): save invalid commit message attempts to be restored on next commit attempt (#38304)
When a commit message fails validation, rather than throwing out the commit message entirely
the commit message is saved into a draft file and restored on the next commit attempt.

PR Close #38304
2020-08-13 08:45:25 -07:00
8366effeec refactor(dev-infra): extract the commit message parsing function into its own file (#38429)
Extracts the commit message parsing function into its own file.

PR Close #38429
2020-08-12 16:10:07 -07:00
5f2e475abf docs: remove unused Input decorator (#38306)
In the part "5. Add In-app Navigation" of the tutorial it was already removed
PR Close #38306
2020-08-12 11:26:10 -07:00
aa3520eb7d refactor(dev-infra): use promptConfirm util in ng-dev's formatter (#38419)
Use the promptConfirm util instead of manually creating a confirm prompt with
inquirer.

PR Close #38419
2020-08-12 11:25:10 -07:00
823dd5b341 docs: update web-worker CLI commands to bash style (#38421)
With this change we update the CLI generate commands to be in bash style.

PR Close #38421
2020-08-12 11:24:35 -07:00
d6d7caa2a8 release: cut the v10.1.0-next.5 release 2020-08-12 09:57:20 -07:00
dcf7baf3d1 docs: release notes for the v10.0.9 release 2020-08-12 09:49:28 -07:00
4d17418569 docs: delete one superfluous sentence (#38339)
PR Close #38339
2020-08-12 08:23:18 -07:00
a2e069fdda build: run formatting automatically on pre-commit hook (#38402)
Runs the `ng-dev format changed` command whenever the `git commit` command is
run.  As all changes which are checked by CI will require this check passing, this
change can prevent needless roundtrips to correct lint/formatting errors. This
automatic formatting can be bypassed with the `--no-verify` flag on the `git commit`
command.

PR Close #38402
2020-08-11 16:32:54 -07:00
28534d83ee feat(dev-infra): Add support for formatting all staged files (#38402)
Adds an ng-dev formatter option to format all of the staged files. This will can
be used to format only the staged files during the pre-commit hook.

PR Close #38402
2020-08-11 16:32:54 -07:00
a6292faa97 docs: remove solution style tsconfig (#38394)
Following the issues highlighted in
https://docs.google.com/document/d/1eB6cGCG_2ircfS5GzpDC9dBgikeYYcMxghVH5sDESHw/edit?usp=sharing
and discussions held with the TypeScript team.
Together with the TypeScript team it was decided that the best course of action is to rollback this feature.

In future, it is not excluded that solution style tsconfigs are re-introduced.

See: https://github.com/angular/angular-cli/pull/18478

PR Close #38394
2020-08-11 16:32:20 -07:00
e2e5f83869 ci: update payload size limits for Closure tests (#38411)
Currently the Closure-related tests are not tree-shaking the dev-mode-only content, thus payload
size checks are failing even if dev-mode-only content is added.
The 2e9fdbde9e commit
added some logic to JIT compiler, which is likely triggered the payload size increase. This commit
updates the payload size limits for Closure-related test to get master and patch branches back to
the "green" state.

PR Close #38411
2020-08-11 10:59:39 -07:00
71138f6004 feat(compiler-cli): Add compiler option to report errors when assigning to restricted input fields (#38249)
The compiler does not currently report errors when there's an `@Input()`
for a `private`, `protected`, or `readonly` directive/component class member.
This change adds an option to enable reporting errors when a template
attempts to bind to one of these restricted input fields.

PR Close #38249
2020-08-11 09:55:48 -07:00
fa0104017a refactor(compiler-cli): only use type constructors for directives with generic types (#38249)
Prior to this change, the template type checker would always use a
type-constructor to instantiate a directive. This type-constructor call
serves two purposes:

1. Infer any generic types for the directive instance from the inputs
   that are passed in.
2. Type check the inputs that are passed into the directive's inputs.

The first purpose is only relevant when the directive actually has any
generic types and using a type-constructor for these cases inhibits
a type-check performance penalty, as a type-constructor's signature is
quite complex and needs to be generated for each directive.

This commit refactors the generated type-check blocks to only generate
a type-constructor call for directives that have generic types. Type
checking of inputs is achieved by generating individual statements for
all inputs, using assignments into the directive's fields.

Even if a type-constructor is used for type-inference of generic types
will the input checking also be achieved using the individual assignment
statements. This is done to support the rework of the language service,
which will start to extract symbol information from the type-check
blocks.

As a future optimization, it may be possible to reduce the number of
inputs passed into a type-constructor to only those inputs that
contribute the the type-inference of the generics. As this is not a
necessity at the moment this is left as follow-up work.

Closes #38185

PR Close #38249
2020-08-11 09:55:48 -07:00
80b67e02b7 fix(compiler-cli): infer quote expressions as any type in type checker (#37917)
"Quote expressions" are expressions that start with an identifier followed by a
comma, allowing arbitrary syntax to follow. These kinds of expressions would
throw a an error in the template type checker, which would make them hard to
track down. As quote expressions are not generally used at all, the error would
typically occur for URLs that would inadvertently occur in a binding:

```html
<a [href]="https://example.com"></a>
```

This commit lets such bindings be inferred as the `any` type.

Fixes #36568
Resolves FW-2051

PR Close #37917
2020-08-11 09:54:53 -07:00
18098d38b8 fix(compiler-cli): avoid creating value expressions for symbols from type-only imports (#37912)
In TypeScript 3.8 support was added for type-only imports, which only brings in
the symbol as a type, not their value. The Angular compiler did not yet take
the type-only keyword into account when representing symbols in type positions
as value expressions. The class metadata that the compiler emits would include
the value expression for its parameter types, generating actual imports as
necessary. For type-only imports this should not be done, as it introduces an
actual import of the module that was originally just a type-only import.

This commit lets the compiler deal with type-only imports specially, preventing
a value expression from being created.

Fixes #37900

PR Close #37912
2020-08-11 09:53:25 -07:00
9514fd9080 fix(compiler): evaluate safe navigation expressions in correct binding order (#37911)
When using the safe navigation operator in a binding expression, a temporary
variable may be used for storing the result of a side-effectful call.
For example, the following template uses a pipe and a safe property access:

```html
<app-person-view [enabled]="enabled" [firstName]="(person$ | async)?.name"></app-person-view>
```

The result of the pipe evaluation is stored in a temporary to be able to check
whether it is present. The temporary variable needs to be declared in a separate
statement and this would also cause the full expression itself to be pulled out
into a separate statement. This would compile into the following
pseudo-code instructions:

```js
var temp = null;
var firstName = (temp = pipe('async', ctx.person$)) == null ? null : temp.name;
property('enabled', ctx.enabled)('firstName', firstName);
```

Notice that the pipe evaluation happens before evaluating the `enabled` binding,
such that the runtime's internal binding index would correspond with `enabled`,
not `firstName`. This introduces a problem when the pipe uses `WrappedValue` to
force a change to be detected, as the runtime would then mark the binding slot
corresponding with `enabled` as dirty, instead of `firstName`. This results
in the `enabled` binding to be updated, triggering setters and affecting how
`OnChanges` is called.

In the pseudo-code above, the intermediate `firstName` variable is not strictly
necessary---it only improved readability a bit---and emitting it inline with
the binding itself avoids the out-of-order execution of the pipe:

```js
var temp = null;
property('enabled', ctx.enabled)
  ('firstName', (temp = pipe('async', ctx.person$)) == null ? null : temp.name);
```

This commit introduces a new `BindingForm` that results in the above code to be
generated and adds compiler and acceptance tests to verify the proper behavior.

Fixes #37194

PR Close #37911
2020-08-11 09:51:10 -07:00
2e9fdbde9e fix(core): prevent NgModule scope being overwritten in JIT compiler (#37795)
In JIT compiled apps, component definitions are compiled upon first
access. For a component class `A` that extends component class `B`, the
`B` component is also compiled when the `InheritDefinitionFeature` runs
during the compilation of `A` before it has finalized. A problem arises
when the compilation of `B` would flush the NgModule scoping queue,
where the NgModule declaring `A` is still pending. The scope information
would be applied to the definition of `A`, but its compilation is still
in progress so requesting the component definition would compile `A`
again from scratch. This "inner compilation" is correctly assigned the
NgModule scope, but once the "outer compilation" of `A` finishes it
would overwrite the inner compilation's definition, losing the NgModule
scope information.

In summary, flushing the NgModule scope queue could trigger a reentrant
compilation, where JIT compilation is non-reentrant. To avoid the
reentrant compilation, a compilation depth counter is introduced to
avoid flushing the NgModule scope during nested compilations.

Fixes #37105

PR Close #37795
2020-08-11 09:50:27 -07:00
df76a2048b fix(router): restore 'history.state' object for navigations coming from Angular router (#28108) (#28176)
When navigations coming from Angular router we may have a payload stored in state property. When this
 exists, set extras's state to the payload.

PR Close #28176
2020-08-11 08:36:13 -07:00
3d156162af fix(dev-infra): update i18n-related file locations in PullApprove config (#38403)
The changes in https://github.com/angular/angular/pull/38368 split `render3/i18n.ts` files into
smaller scripts, but the PullApprove config was not updated to reflect that. This commit updates
the PullApprove config to reflect the recent changes in i18n-related files.

PR Close #38403
2020-08-10 17:29:51 -07:00
5dc8d287aa fix(core): queries not matching string injection tokens (#38321)
Queries weren't matching directives that provide themselves via string
injection tokens, because the assumption was that any string passed to
a query decorator refers to a template reference.

These changes make it so we match both template references and
providers while giving precedence to the template references.

Fixes #38313.
Fixes #38315.

PR Close #38321
2020-08-10 15:27:24 -07:00
6da9e5851a fix(compiler-cli): preserve quotes in class member names (#38387)
When we were outputting class members for `setClassMetadata` calls,
we were using the string representation of the member name. This can
lead to us generating invalid code when the name contains dashes and
is quoted (e.g. `@Output() 'has-dashes' = new EventEmitter()`), because
the quotes will be stripped for the string representation.

These changes fix the issue by using the original name AST node that was
used for the declaration and which knows whether it's supposed to be
quoted or not.

Fixes #38311.

PR Close #38387
2020-08-10 15:26:45 -07:00
250e299dc3 refactor(core): break i18n.ts into smaller files (#38368)
This commit contains no changes to code. It only breaks `i18n.ts` file
into `i18n.ts` + `i18n_apply.ts` + `i18n_parse.ts` +
`i18n_postprocess.ts` for easier maintenance.

PR Close #38368
2020-08-10 15:07:42 -07:00
8f708b561c fix(router): defer loading of wildcard module until needed (#38348)
Defer loading the wildcard module so that it is not loaded until
subscribed to. This fixes an issue where it was being eagerly loaded.
As an example, wildcard module loading should only occur after all other potential
matches have been exhausted. A test case for this was also added to
demonstrate the fix.

Fixes #25494

PR Close #38348
2020-08-10 13:20:08 -07:00
e34c33cd46 fix(platform-server): remove styles added by ServerStylesHost on destruction (#38367)
When a ServerStylesHost instance is destroyed, all of the shared styles added to the DOM
head element by that instance should be removed.  Without this removal, over time a large
number of style rules will build up and cause extra memory pressure.  This brings the
ServerStylesHost in line with the DomStylesHost used by the platform browser, which
performs this same cleanup.

PR Close #38367
2020-08-10 13:12:23 -07:00
6d8c73a4d6 fix(core): Store the currently selected ICU in LView (#38345)
The currently selected ICU was incorrectly being stored it `TNode`
rather than in `LView`.

Remove: `TIcuContainerNode.activeCaseIndex`
Add: `LView[TIcu.currentCaseIndex]`

PR Close #38345
2020-08-10 12:41:17 -07:00
6ff28ac944 docs: Remove redundant sentence from Router (#38398)
PR Close #38398
2020-08-10 09:52:30 -07:00
0de93fd402 docs: update team contributors page (#38384)
Removing Kara, Denny, Judy, Tony, Matias as they are no longer actively working on the project
PR Close #38384
2020-08-10 09:51:50 -07:00
445ac15a78 docs: fix purpose description of "builders.json" (#36830)
PR Close #36830
2020-08-07 15:04:56 -07:00
856db56cca refactor(forms): get rid of duplicate functions (#38371)
This commit performs minor refactoring in Forms package to get rid of duplicate functions.
It looks like the functions were duplicated due to a slightly different type signatures, but
their logic is completely identical. The logic in retained functions remains the same and now
these function also accept a generic type to achieve the same level of type safety.

PR Close #38371
2020-08-07 11:40:04 -07:00
354e66efad refactor(common): use getElementById in ViewportScroller.scrollToAnchor (#30143)
This commit uses getElementById and getElementsByName when an anchor scroll happens,
to avoid escaping the anchor and wrapping the code in a try/catch block.

Related to #28960

PR Close #30143
2020-08-07 11:14:31 -07:00
702958e968 refactor(core): add debug ranges to LViewDebug with matchers (#38359)
This change provides better typing for the `LView.debug` property which
is intended to be used by humans while debugging the application with
`ngDevMode` turned on.

In addition this chang also adds jasmine matchers for better asserting
that `LView` is in the correct state.

PR Close #38359
2020-08-06 16:58:11 -07:00
df7f3b04b5 fix(service-worker): fix the chrome debugger syntax highlighter (#38332)
The Chrome debugger is not able to render the syntax properly when the
code contains backticks. This is a known issue in Chrome and they have an
open [issue](https://bugs.chromium.org/p/chromium/issues/detail?id=659515) for that.
This commit adds the work-around to use double backslash with one
backtick ``\\` `` at the end of the line.

This can be reproduced by running the following command:

`yarn bazel test //packages/forms/test --config=debug`

When opening the chrome debugger tools, you should see the correct
code highlighting syntax.

PR Close #38332
2020-08-06 15:22:57 -07:00
7525f3afc1 fix(compiler-cli): type-check inputs that include undefined when there's coercion members (#38273)
For attribute bindings that target a directive's input, the template
type checker is able to verify that the type of the input expression is
compatible with the directive's declaration for said input. This
checking adheres to the `strictNullChecks` flag as configured in the
TypeScript compilation, such that errors are reported for expressions
that include `undefined` or `null` in their type if the input's
declaration does not include those types.

There was a bug with this level of type-checking for directives that
also declare coercion members, where binding an expression that includes
the `undefined` type to a directive's input that does not include the
`undefined` type would not be reported as error.

This commit fixes the bug by changing the type-constructor in type-check
code to use an intersection type of regular inputs and coerced inputs,
instead of a union type. The union type would inadvertently allow
`undefined` types to be assigned into the regular inputs, as that would
still satisfy the characteristics of a union type.

As a result of this change, you may start to see build failures if
`strictTemplates` is enabled and `strictInputTypes` is not disabled.
These errors are legitimate and some action is required to achieve a
successful build:

1. Update the templates for which an error is reported and introduce the
   non-null assertion operator at the end of the expression. This
   removes the `undefined` type from the expression's type, making it
   appear as a valid assignment.
2. Disable `strictNullInputTypes` in the compiler options. This will
   implicitly add the non-null assertion operators similar to option 1,
   but all templates in the compilation are affected.
3. Update the directive's input declaration to include the `undefined`
   type, if the directive is not implemented in an external library.

PR Close #38273
2020-08-06 15:21:02 -07:00
570d156ce4 test: update components repo to test against recent revision (#38273)
The changes in angular/components#20136 are required to allow the
framework tests to succeed.

PR Close #38273
2020-08-06 15:21:02 -07:00
26be5b4994 refactor(core): extract icuSwitchCase, icuUpdateCase, removeNestedIcu (#38154)
Extract `icuSwitchCase`, `icuUpdateCase`, `removeNestedIcu` into
separate functions to align them with the `.debug` property text.

PR Close #38154
2020-08-06 15:20:17 -07:00
3821dc5f6c refactor(core): add human readable debug for i18n (#38154)
I18n code breaks up internationalization into opCodes which are then stored
in arrays. To make it easier to debug the codebase this PR adds `debug`
property to the arrays which presents the data in human readable format.

PR Close #38154
2020-08-06 15:20:17 -07:00
18cd1a9937 docs(service-worker): describe how asset-/data-group order affects request handling (#38364)
The order of asset- and data-groups in `ngsw-config.json` affects how a
request is handled by the ServiceWorker. Previously, this was not
clearly documented.

This commit describes how the order of asset-/data-groups affects
request handling.

Closes #21189

PR Close #38364
2020-08-06 11:41:58 -07:00
0551fbdf88 fix(docs-infra): correctly generate CLI commands docs when the overview page moves (#38365)
Previously, the [processCliCommands][1] dgeni processor, which is used
to generate the docs pages for the CLI commands, expected the CLI
commands overview page (with a URL of `cli`) to exist as a child of a
top-level navigation section (`CLI Commands`). If one tried to move the
`CLI Commands` section inside another section, `processCliCommnads`
would fail to find it and thus fail to generate the CLI commands docs.
This problem came up in #38353.

This commit updates the `processCliCommands` processor to be able to
find it regardless of the position of the `CLI Commands` section inside
the navigation doc.

[1]:
dca4443a8e/aio/tools/transforms/cli-docs-package/processors/processCliCommands.js (L7-L9)

PR Close #38365
2020-08-06 11:41:05 -07:00
dca4443a8e fix(compiler-cli): mark eager NgModuleFactory construction as not side effectful (#38320)
Roll forward of #38147.

This allows Closure compiler to tree shake unused constructor calls to `NgModuleFactory`, which is otherwise considered
side-effectful. The Angular compiler generates factory objects which are exported but typically not used, as they are
only needed for compatibility with View Engine. This results in top-level constructor calls, such as:

```typescript
export const FooNgFactory = new NgModuleFactory(Foo);
```

`NgModuleFactory` has a side-effecting constructor, so this statement cannot be tree shaken, even if `FooNgFactory` is
never imported. The `NgModuleFactory` continues to reference its associated `NgModule` and prevents the module and all
its unused dependencies from being tree shaken, making Closure builds significantly larger than necessary.

The fix here is to wrap `NgModuleFactory` constructor with `noSideEffects(() => /* ... */)`, which tricks the Closure
compiler into assuming that the invoked function has no side effects. This allows it to tree-shake unused
`NgModuleFactory()` constructors when they aren't imported. Since the factory can be removed, the module can also be
removed (if nothing else references it), thus tree shaking unused dependencies as expected.

The one notable edge case is for lazy loaded modules. Internally, lazy loading is done as a side effect when the lazy
script is evaluated. For Angular, this side effect is registering the `NgModule`. In Ivy this is done by the
`NgModuleFactory` constructor, so lazy loaded modules **cannot** have their top-level `NgModuleFactory` constructor
call tree shaken. We handle this case by looking for the `id` field on `@NgModule` annotations. All lazy loaded modules
include an `id`. When this `id` is found, the `NgModuleFactory` is generated **without** with `noSideEffects()` call,
so Closure will not tree shake it and the module will lazy-load correctly.

PR Close #38320
2020-08-06 09:02:16 -07:00
2a745c8df8 refactor(compiler): add ModuleInfo interface (#38320)
This introduces a new `ModuleInfo` interface to represent some of the statically analyzed data from an `NgModule`. This
gets passed into transforms to give them more context around a given `NgModule` in the compilation.

PR Close #38320
2020-08-06 09:02:16 -07:00
a18f82b458 refactor(core): add noSideEffects() as private export (#38320)
This is to enable the compiler to generate `noSideEffects()` calls. This is a private export, gated by `ɵ`.

PR Close #38320
2020-08-06 09:02:16 -07:00
696a9b01ef docs: remove https://angular.io from internal links (#38360)
PR #36601 introduces icons on all links if the link contains
https:// or http:// but there were some internal links left
which contained https://angular.io. Removed https://angular.io
from all these links.

PR Close #38360
2020-08-06 09:01:34 -07:00
d7c043ba35 docs: add a page with the Angular roadmap (#38358)
PR Close #38358
2020-08-05 18:35:02 -07:00
0c2490368e refactor(platform-browser): specify return type of parseEventName (#38089)
This commit refactors the argument of the `parseEventName` function
to use an object with named properties instead of using an object indexer.

PR Close #38089
2020-08-05 17:06:28 -07:00
bb88c9fa3d fix(common): ensure scrollRestoration is writable (#30630)
Some specialised browsers that do not support scroll restoration
(e.g. some web crawlers) do not allow `scrollRestoration` to be
writable.

We already sniff the browser to see if it has the `window.scrollTo`
method, so now we also check whether `window.history.scrollRestoration`
is writable too.

Fixes #30629

PR Close #30630
2020-08-05 16:13:15 -07:00
8227b56f9e style(docs-infra): reformat ScrollService file (#30630)
Pre-empting code formatting changes when the
code is updated in a subsequent commit.

PR Close #30630
2020-08-05 16:13:15 -07:00
1609815743 feat(router): better warning message when a router outlet has not been instantiated (#30246)
It is confusing when routes are successfully activated but a component
is not present on a page, with this message it's more clear.

PR Close #30246
2020-08-05 12:55:35 -07:00
763023472b fix(router): prevent calling unsubscribe on undefined subscription in RouterPreloader (#38344)
Previously, the `ngOnDestroy` method called `unsubscribe` regardless of if `subscription` had
been initialized.  This can lead to an error attempting to call `unsubscribe` of undefined.
This change prevents this error, and instead only attempts `unsubscribe` when the subscription
has been defined.

PR Close #38344
2020-08-05 10:54:41 -07:00
ba175be41f fix(compiler-cli): match wrapHost parameter types within plugin interface (#38004)
The `TscPlugin` interface using a type of `ts.CompilerHost&Partial<UnifiedModulesHost>` for the `host` parameter
of the `wrapHost` method. However, prior to this change, the interface implementing `NgTscPlugin` class used a
type of `ts.CompilerHost&UnifiedModulesHost` for the parameter. This change corrects the inconsistency and
allows `UnifiedModulesHost` members to be optional when using the `NgtscPlugin`.

PR Close #38004
2020-08-05 10:54:07 -07:00
f0766a4474 feat(dev-infra): provide organization-wide merge-tool label configuration (#38223)
Previously, each Angular repository had its own strategy/configuration
for merging pull requests and cherry-picking. We worked out a new
strategy for labeling/branching/versioning that should be the canonical
strategy for all actively maintained projects in the Angular organization.

This PR provides a `ng-dev` merge configuration that implements the
labeling/branching/merging as per the approved proposal.

See the following document for the proposal this commit is based on
for the merge script labeling/branching: https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU

The merge tool label configuration can be conveniently accesed
within each `.ng-dev` configuration, and can also be extended
if there are special labels on individual projects. This is one
of the reasons why the labels are not directly built into the
merge script. The script should remain unopinionated and flexible.

The configuration is conceptually powerful enough to achieve the
procedures as outlined in the versioning/branching/labeling proposal.

PR Close #38223
2020-08-05 10:53:17 -07:00
6f0f0d3ea2 feat(dev-infra): support user-failures when computing branches for target label (#38223)
The merge tool provides a way for configurations to determine the branches
for a label lazily. This is supported because it allows labels to respect
the currently selected base branch through the Github UI. e.g. if `target: label`
is applied on a PR and the PR is based on the patch branch, then the change
could only go into the selected target branch, while if it would be based on
`master`, the change would be cherry-picked to `master` too. This allows for
convenient back-porting of changes if they did not apply cleanly to the primary
development branch (`master`).

We want to expand this function so that it is possible to report failures if an
invalid target label is appplied (e.g. `target: major` not allowed in
some situations), or if the Github base branch is not valid for the given target
label (e.g. if `target: lts` is used, but it's not based on a LTS branch).

PR Close #38223
2020-08-05 10:53:17 -07:00
576e329f33 feat(dev-infra): provide github API instance to lazy merge configuration (#38223)
The merge script currently accepts a configuration function that will
be invoked _only_ when the `ng-dev merge` command is executed. This
has been done that way because the merge tooling usually relies on
external requests to Git or NPM for constructing the branch configurations.

We do not want to perform these slow external queries on any `ng-dev` command
though, so this became a lazily invoked function.

This commit adds support for these configuration functions to run
asynchronously (by returning a Promise that will be awaited), so that
requests could also be made to the Github API. This is benefical as it
could avoid dependence on the local Git state and the HTTP requests
are more powerful/faster.

Additionally, in order to be able to perform Github API requests
with an authenticated instance, the merge tool will pass through
a `GithubClient` instance that uses the specified `--github-token`
(or from the environment). This ensures that all API requests use
the same `GithubClient` instance and can be authenticated (mitigating
potential rate limits).

PR Close #38223
2020-08-05 10:53:17 -07:00
585ef2bdd7 docs: fix typo in glossary (#38318)
Add missing comma  in structural directive section that made dash display incorrectly.

PR Close #38318
2020-08-05 10:52:27 -07:00
2fcabe1557 release: cut the v10.1.0-next.4 release 2020-08-04 16:13:39 -07:00
192ef42304 docs: release notes for the v10.0.8 release 2020-08-04 16:07:27 -07:00
8fbf40bf40 feat(core): update reference and doc to change async to waitAsync. (#37583)
The last commit change `async` to `waitForAsync`.
This commit update all usages in the code and also update aio doc.

PR Close #37583
2020-08-03 12:54:13 -07:00
8f074296c2 feat(core): rename async to waitForAsync to avoid confusing (#37583)
@angular/core/testing provide `async` test utility, but the name `async` is
confusing with the javascript keyword `async`. And in some test case, if you
want to use both the `async` from `@angular/core/testing` and `async/await`,
you may have to write the code like this.

```typescript
it('test async operations', async(async() => {
  const result = await asyncMethod();
  expect(result).toEqual('expected');
}));
```

So in this PR, the `async` is renamed to `waitForAsync` and also deprecate `async`.

PR Close #37583
2020-08-03 12:54:13 -07:00
e49b053dac build: cleanup .bazelrc file to no longer set unused flags (#38124)
This option is no longer needed in Bazel and will be an error in the future

PR Close #38124
2020-08-03 12:53:11 -07:00
87baa06cc6 revert: docs(core): correct SomeService to SomeComponent (#38325)
This reverts commit b4449e35bf.

The example given from the previous change was for a component selector and not a provider selector.

This change fixes it.

Fixes #38323.

PR Close #38325
2020-08-03 12:52:19 -07:00
ff9f4de4f1 fix(compiler): update unparsable character reference entity error messages (#38319)
Within an angular template, when a character entity is unable to be parsed, previously a generic
unexpected character error was thrown.  This does not properly express the issue that was discovered
as the issue is actually caused by the discovered character making the whole of the entity unparsable.
The compiler will now instead inform via the error message what string was attempted to be parsed
and what it was attempted to be parsed as.

Example, for this template:
```
<p>
  &#x123p
</p>
```
Before this change:
`Unexpected character "p"`

After this change:
`Unable to parse entity "&#x123p" - hexadecimal character reference entities must end with ";"`

Fixes #26067

PR Close #38319
2020-07-31 15:32:53 -07:00
3a46c2da7c refactor(docs-infra): update docs examples tslint.json to match CLI and fix failures (#38143)
This commit updates the `tslint.json` configuration file, that is used
to lint the docs examples, to match the one generated for new Angular
CLI apps. There are some minimal differences (marked with `TODO`
comments) for things, such as component selector prefix, that would
require extensive and/or difficult to validate changes in guides.

This commit also includes the final adjustments to make the docs
examples code compatible with the new tslint rules. (The bulk of the
work has been done in previous commits.)

PR Close #38143
2020-07-31 11:00:06 -07:00
bfd13c06e1 refactor(docs-infra): fix docs examples for Angular-specific tslint rules (#38143)
This commit updates the docs examples to be compatible with the
following Angular-specific tslint rules:
- `component-selector`
- `directive-selector`
- `no-conflicting-lifecycle`
- `no-host-metadata-property`
- `no-input-rename`
- `no-output-native`
- `no-output-rename`

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
5303773daf refactor(docs-infra): fix docs examples for tslint rule prefer-const (#38143)
This commit updates the docs examples to be compatible with the
`prefer-const` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
ba11f7b90b refactor(docs-infra): fix docs examples for tslint rules related to underscores in variable names (#38143)
This commit updates the docs examples to be compatible with the
`variable-name` tslint rule without requiring the
`allow-leading-underscore` and `allow-trailing-underscore` options.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
1db4f508e6 refactor(docs-infra): fix docs examples for tslint rules related to variable names (#38143)
This commit updates the docs examples to be compatible with the
`no-shadowed-variable` and `variable-name` tslint rules.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
6334749d2c refactor(docs-infra): fix docs examples for tslint rule member-ordering (#38143)
This commit updates the docs examples to be compatible with the
`member-ordering` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
3c7359f026 refactor(docs-infra): fix docs examples for tslint rule no-angle-bracket-type-assertion (#38143)
This commit updates the docs examples to be compatible with the
`no-angle-bracket-type-assertion` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
8aa29438ac refactor(docs-infra): fix docs examples for tslint rules related to object properties (#38143)
This commit updates the docs examples to be compatible with the
`no-string-literal`, `object-literal-key-quotes` and
`object-literal-shorthand` tslint rules.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
fc709423f2 refactor(docs-infra): fix docs examples for tslint rule only-arrow-functions (#38143)
This commit updates the docs examples to be compatible with the
`only-arrow-functions` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:06 -07:00
3012a8e71c style(docs-infra): fix docs examples for tslint rule jsdoc-format (#38143)
This commit updates the docs examples to be compatible with the
`jsdoc-format` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:05 -07:00
77f38d3be1 style(docs-infra): fix docs examples for tslint rule semicolon (#38143)
This commit updates the docs examples to be compatible with the
`semicolon` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:05 -07:00
7c0f11789b style(docs-infra): fix docs examples for tslint rules related to whitespace (#38143)
This commit updates the docs examples to be compatible with the `align`,
`space-before-function-paren` and `typedef-whitespace` tslint rules.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:05 -07:00
0a791e4a50 style(docs-infra): fix docs examples for tslint rule import-spacing (#38143)
This commit updates the docs examples to be compatible with the
`import-spacing` tslint rule.

This is in preparation of updating the docs examples `tslint.json` to
match the one generated for new Angular CLI apps in a future commit.

PR Close #38143
2020-07-31 11:00:05 -07:00
d89200ad24 refactor(docs-infra): remove unnecessary use strict from docs examples TS files (#38143)
By default, TypeScript will emit `"use strict"` directives, so it is not
necessary to include `'use strict'` in `.ts` files:
https://www.typescriptlang.org/docs/handbook/compiler-options.html#:~:text=--noImplicitUseStrict

PR Close #38143
2020-07-31 11:00:05 -07:00
00b7186cb2 refactor(docs-infra): remove unused styleguide examples (#38143)
The `03-*` code style rule have been removed from the style guide in
be0bc799f3.

This commit removes the corresponding files and related unused code from
the`styleguide` example project.

PR Close #38143
2020-07-31 11:00:05 -07:00
e8896b9de3 fix(language-service): [ivy] do not retrieve ts.Program at startup (#38120)
This commit removes compiler instantiation at startup.
This is because the constructor is invoked during the plugin loading phase,
in which the project has not been completely loaded.

Retrieving `ts.Program` at startup will trigger an `updateGraph` operation,
which could only be called after the Project has loaded completely.
Without this change, the Ivy LS cannot be loaded as a tsserver plugin.

Note that the whole `Compiler` class is temporary, so changes made there are
only for development. Once we have proper integration with ngtsc the
`Compiler` class would be removed.

PR Close #38120
2020-07-30 16:54:19 -07:00
6f6102d8ad fix(compiler): add PURE annotation to getInheritedFactory calls (#38291)
Currently the `getInheritedFactory` function is implemented to allow
closure to remove the call if the base factory is unused.  However, this
method does not work with terser.  By adding the PURE annotation,
terser will also be able to remove the call when unused.

PR Close #38291
2020-07-30 16:53:52 -07:00
4c7f233fa8 docs: release notes for the v10.0.7 release 2020-07-30 16:51:40 -07:00
fd51e01335 fix(compiler): Metadata should not include methods on Object.prototype (#38292)
This commit fixes a bug in View Engine whereby the compiler errorneously
thinks that a method of a component has decorator metadata when that
method is one of those in `Object.prototype`, for example `toString`.

This bug is discovered in v10.0.4 of `@angular/language-service` after
the default bundle format was switched from ES5 to ES2015.

ES5 output:
```js
if (propMetadata[propName]) {
    decorators.push.apply(decorators, __spread(propMetadata[propName]));
}
```

ES2015 output:
```js
if (propMetadata[propName]) {
    decorators.push(...propMetadata[propName]);
}
```

The bug was not discovered in ES5 because the polyfill for the spread
operator happily accepts parameters that do not have the `iterable`
symbol:

```js
function __spread() {
    for (var ar = [], i = 0; i < arguments.length; i++)
        ar = ar.concat(__read(arguments[i]));
    return ar;
}
```

whereas in es2015 it’ll fail since the iterable symbol is not present in
`propMetadata['toString']` which evaluates to a function.

Fixes https://github.com/angular/vscode-ng-language-service/issues/859

PR Close #38292
2020-07-30 15:18:28 -07:00
3a525d196b Revert "fix(compiler): mark NgModuleFactory construction as not side effectful (#38147)" (#38303)
This reverts commit 7f8c2225f2.

This commit caused test failures internally, which were traced back to the
optimizer removing NgModuleFactory constructor calls when those calls caused
side-effectful registration of NgModules by their ids.

PR Close #38303
2020-07-30 12:19:35 -07:00
1eebb7f189 test(compiler-cli): disable one TypeChecker test on Windows due to path sensitivity issue (#38294)
This commit disables one TypeChecker test (added as a part of
https://github.com/angular/angular/pull/38105) which make assertions about the filename while
running on Windows.

Such assertions are currently suffering from a case sensitivity issue.

PR Close #38294
2020-07-29 17:49:45 -07:00
8effc83b92 docs(router): clarify how base href is used to construct targets (#38123)
The documentation is not clear on how the base href and APP_BASE_HREF are used. This commit
should help clarify more complicated use-cases beyond the most common one of just a '/'

PR Close #38123
2020-07-29 13:34:02 -07:00
7f8c2225f2 fix(compiler): mark NgModuleFactory construction as not side effectful (#38147)
This allows Closure compiler to tree shake unused constructor calls to `NgModuleFactory`, which is otherwise considered
side-effectful. The Angular compiler generates factory objects which are exported but typically not used, as they are
only needed for compatibility with View Engine. This results in top-level constructor calls, such as:

```typescript
export const FooNgFactory = new NgModuleFactory(Foo);
```

`NgModuleFactory` has a side-effecting constructor, so this statement cannot be tree shaken, even if `FooNgFactory` is
never imported. The `NgModuleFactory` continues to reference its associated `NgModule` and prevents the module and all
its unused dependencies from being tree shaken. This effectively prevents all components from being tree shaken, making
Closure builds significantly larger than they should be.

The fix here is to wrap `NgModuleFactory` constructor with `noSideEffects(() => /* ... */)`, which tricks the Closure
compiler into assuming that the invoked function has no side effects. This allows it to tree-shake unused
`NgModuleFactory()` constructors when they aren't imported. Since the factory can be removed, the module can also be
removed (if nothing else references it), thus tree shaking unused components as expected.

PR Close #38147
2020-07-29 13:32:08 -07:00
887c350f9d refactor(compiler): wrap large strings in function (#38253)
Large strings constants are now wrapped in a function which is called whenever used. This works around a unique
limitation of Closure, where it will **always** inline string literals at **every** usage, regardless of how large the
string literal is or how many times it is used.The workaround is to use a function rather than a string literal.
Closure has differently inlining semantics for functions, where it will check the length of the function and the number
of times it is used before choosing to inline it. By using a function, `ngtsc` makes Closure more conservative about
inlining large strings, and avoids blowing up the bundle size.This optimization is only used if the constant is a large
string. A wrapping function is not included for other use cases, since it would just increase the bundle size and add
unnecessary runtime performance overhead.

PR Close #38253
2020-07-29 13:31:03 -07:00
103a95c182 docs: update bio picture (#38272)
Updates my profile picture which was quite old.

PR Close #38272
2020-07-29 10:33:36 -07:00
1b17722091 refactor(docs-infra): Lazy-loads SVG icons (#38268)
Prior to this commit, SVG icons were all loaded in the constructor
of the `CustomIconRegistry`. This commit avoids that, and loads SVG
icons on demand.

PR Close #38268
2020-07-29 10:32:54 -07:00
b280d54470 refactor(docs-infra): simplify/improve CopierService hidden textarea creation (#38244)
This commit simplifies the creation of the temporary, hidden
`<textarea>` element used by `CopierService` by switching from absolute
to fixed positioning and not requiring page's scroll offset.

It also makes the following minor improvements:
- Make the element invisible (via `opacity: 0`).
- Instruct screen-readers to ignore the element (via
  `aria-hidden: true`).

NOTE: These improvements are based on Angular CDK's [PendingCopy][1]
      class and the changes proposed in PR angular/components#20073.

[1]: https://github.com/angular/components/blob/89b5fa89d1437c3054c5/src/cdk/clipboard/pending-copy.ts

PR Close #38244
2020-07-29 10:32:05 -07:00
d96824acdb fix(docs-infra): preserve focus on copy (and prevent scrolling to bottom on IE11) (#38244)
The `CopierService` is used for copying text to the user's clipboard. It
is, for example, used in `CodeComponent` to copy example code snippets.
This is implemented by creating a temporary, hidden `<textarea>`
elements, setting its value to the text that needs to be copied,
executing the `copy` command and finally removing the element from the
DOM.

Previously, as a result of `CopierService`'s implementation, the focused
element would lose focus, while the temporary `<textarea>` element would
implicitly gain focus when selecting its contents. This had an even
worse side-effect on IE11, which seems to scroll to the bottom of the
containing element (here `<body>`) when the focused element is removed.

This commit fixes these issues by keeping track of the previously
focused element and restoring its focus after the copy operation.

NOTE: This fix is inspired by Angular CDK's [PendingCopy][1] class.

[1]: https://github.com/angular/components/blob/89b5fa89d1437c3054c5/src/cdk/clipboard/pending-copy.ts

Fixes #37796

PR Close #38244
2020-07-29 10:32:05 -07:00
9ebd461a22 refactor(docs-infra): improve code readability of CopierService (#38244)
This commit improves the code readability of the `CopierService` by:
- Adding/Improving JSDoc comments for methods.
- Avoiding unnecessary instance-wide properties.
- Fixing indentation to be consistent (at two spaces).
- Clearly separating the logic for creating and populating a
  `<textarea>` from the logic for selecting and copying its contents.

PR Close #38244
2020-07-29 10:32:05 -07:00
d8c07b83c3 refactor(compiler-cli): support type-checking a single component (#38105)
This commit adds a method `getDiagnosticsForComponent` to the
`TemplateTypeChecker`, which does the minimum amount of work to retrieve
diagnostics for a single component.

With the normal `ReusedProgramStrategy` this offers virtually no improvement
over the standard `getDiagnosticsForFile` operation, but if the
`TypeCheckingProgramStrategy` supports separate shims for each component,
this operation can yield a faster turnaround for components that are
declared in files with many other components.

PR Close #38105
2020-07-29 10:31:21 -07:00
8f73169979 refactor(compiler-cli): add TemplateId to template diagnostics (#38105)
Previously, a stable template id was implemented for each component in a
file. This commit adds this id to each `TemplateDiagnostic` generated from
the template type-checker, so it can potentially be used for filtration.

PR Close #38105
2020-07-29 10:31:20 -07:00
3c0424e7e0 refactor(compiler-cli): allow overriding templates in the type checker (#38105)
This commit adds an `overrideComponentTemplate` operation to the template
type-checker. This operation changes the template used during template
type-checking operations.

Overriding a template causes any previous work for it to be discarded, and
the template type-checking engine will regenerate the TCB for that template
on the next request.

This operation can be used by a consumer such as the language service to
get rapid feedback or diagnostics as the user is editing a template file,
without the need for a full incremental build iteration.

Closes #38058

PR Close #38105
2020-07-29 10:31:20 -07:00
de14b2c670 refactor(compiler-cli): efficient single-file type checking diagnostics (#38105)
Previously, the `TemplateTypeChecker` abstraction allowed fetching
diagnostics for a single file, but under the hood would generate type
checking code for the entire program to satisfy the request.

With this commit, an `OptimizeFor` hint is passed to `getDiagnosticsForFile`
which indicates whether the user intends to request diagnostics for the
whole program or is truly interested in just the single file. If the latter,
the `TemplateTypeChecker` can perform only the work needed to produce
diagnostics for just that file, thus returning answers more efficiently.

PR Close #38105
2020-07-29 10:31:20 -07:00
c573d91285 refactor(compiler-cli): allow program strategies to opt out of inlining (#38105)
The template type-checking engine relies on the abstraction interface
`TypeCheckingProgramStrategy` to create updated `ts.Program`s for
template type-checking. The basic API is that the type-checking engine
requests changes to certain files in the program, and the strategy provides
an updated `ts.Program`.

Typically, such changes are made to 'ngtypecheck' shim files, but certain
conditions can cause template type-checking to require "inline" operations,
which change user .ts files instead. The strategy used by 'ngc' (the
`ReusedProgramStrategy`) supports these kinds of updates, but other clients
such as the language service might not always support modifying user files.

To accommodate this, the `TypeCheckingProgramStrategy` interface was
modified to include a `supportsInlineOperations` flag. If an implementation
specifies `false` for inline support, the template type-checking system will
return diagnostics on components which would otherwise require inline
operations.

Closes #38059

PR Close #38105
2020-07-29 10:31:20 -07:00
16c7441c2f refactor(compiler-cli): introduce the TemplateTypeChecker abstraction (#38105)
This commit significantly refactors the 'typecheck' package to introduce a
new abstraction, the `TemplateTypeChecker`. To achieve this:

* a 'typecheck:api' package is introduced, containing common interfaces that
  consumers of the template type-checking infrastructure can depend on
  without incurring a dependency on the template type-checking machinery as
  a whole.
* interfaces for `TemplateTypeChecker` and `TypeCheckContext` are introduced
  which contain the abstract operations supported by the implementation
  classes `TemplateTypeCheckerImpl` and `TypeCheckContextImpl` respectively.
* the `TemplateTypeChecker` interface supports diagnostics on a whole
  program basis to start with, but the implementation is purposefully
  designed to support incremental diagnostics at a per-file or per-component
  level.
* `TemplateTypeChecker` supports direct access to the type check block of a
  component.
* the testing utility is refactored to be a lot more useful, and new tests
  are added for the new abstraction.

PR Close #38105
2020-07-29 10:31:20 -07:00
736f6337b2 refactor(compiler-cli): make file/shim split 1:n instead of 1:1 (#38105)
Previously in the template type-checking engine, it was assumed that every
input file would have an associated type-checking shim. The type check block
code for all components in the input file would be generated into this shim.

This is fine for whole-program type checking operations, but to support the
language service's requirements for low latency, it would be ideal to be
able to check a single component in isolation, especially if the component
is declared along with many others in a single file.

This commit removes the assumption that the file/shim mapping is 1:1, and
introduces the concept of component-to-shim mapping. Any
`TypeCheckingProgramStrategy` must provide such a mapping.

To achieve this:

 * type checking record information is now split into file-level data as
   well as per-shim data.
 * components are now assigned a stable `TemplateId` which is unique to the
   file in which they're declared.

PR Close #38105
2020-07-29 10:31:20 -07:00
9c8bc4a239 fix(common): narrow NgIf context variables in template type checker (#36627)
When the `NgIf` directive is used in a template, its context variables
can be used to capture the bound value. This is sometimes used in
complex expressions, where the resulting value is captured in a
context variable. There's two syntax forms available:

1. Binding to `NgIfContext.ngIf` using the `as` syntax:
```html
<span *ngIf="enabled && user as u">{{u.name}}</span>
```

2. Binding to `NgIfContext.$implicit` using the `let` syntax:
```html
<span *ngIf="enabled && user; let u">{{u.name}}</span>
```

Because of the semantics of `ngIf`, it is known that the captured
context variable is truthy, however the template type checker
would not consider them as such and still report errors when
`strict` is enabled.

This commit updates `NgIf`'s context guard to make the types of the
context variables truthy, avoiding the issue.

Based on https://github.com/angular/angular/pull/35125

PR Close #36627
2020-07-29 10:30:44 -07:00
cf4da82ac3 Revert "refactor(platform-browser): specify return type of parseEventName (#38089)"
This reverts commit 174aac68f7.
2020-07-29 09:30:11 -07:00
57575e379f release: cut the v10.1.0-next.3 release 2020-07-28 15:17:32 -07:00
28c3e2d15d docs: release notes for the v10.0.6 release 2020-07-28 15:07:19 -07:00
2a45b932e2 build: fix broken build (#38274)
```
export const __core_private_testing_placeholder__ = '';
```
This API should be removed. But doing so seems to break `google3` and
so it requires a bit of investigation. A work around is to mark it as
`@codeGenApi` for now and investigate later.

PR Close #38274
2020-07-28 12:30:59 -07:00
5a12ab4a13 Revert "ci: roll back phased review conditions" (#38259)
This reverts commit ca8eafc2983f983803cd03e4a08bf732672712dd.

PR Close #38259
2020-07-28 11:26:27 -07:00
8a543d8b50 ci: only check active groups for the no-groups-above-this-* checks (#38259)
Since PullApprove starts all inactive groups as a pending state, to properly
assess if any groups we care about are pending we must only check the active
groups.  We additionally do this with rejected because the intention of the
reusable checks is around checking active rules only.

PR Close #38259
2020-07-28 11:26:27 -07:00
9893576ef0 docs(elements): update api doc for custom elements (#38252)
by adding cross-references to Angular Elements Overview guide.

PR Close #38252
2020-07-28 11:19:03 -07:00
af80bdb470 fix(core): Attribute decorator attributeName is mandatory (#38131)
`Attribute` decorator has defined `attributeName` as optional but actually its
 mandatory and compiler throws an error if `attributeName` is undefined. Made
`attributeName` mandatory in the `Attribute` decorator to reflect this functionality

Fixes #32658

PR Close #38131
2020-07-28 11:17:24 -07:00
Ahn
b4449e35bf docs(core): correct SomeService to SomeComponent (#38264)
PR Close #38264
2020-07-28 11:10:58 -07:00
3d0be5213e docs: update api reference doc for router-link-active directive (#38247)
Edits and organizes the usage information for the directive.

PR Close #38247
2020-07-28 11:09:44 -07:00
be3e7050d5 ci: roll back phased review conditions (#38257)
It was determined that the list of 'pending' groups also included inactive groups.
That means that the 'no-groups-above-this-pending' would generally fail because
there's almost always some inactive group above it.

This commit removes the conditions for phased review while we
investigate if the inactive groups can be excluded.

PR Close #38257
2020-07-28 10:02:14 -07:00
cf98db28d5 docs: Refactor module-types.md to make it easier to understand (#38206)
Project DOCS-736 to rewrite headings to focus on user tasks,
verify that the content is up-to-date and complete, and
add relevant links to other NgModule topics to improve readability.
Also addresses one of many issues in GitHub issue 21531.

PR Close #38206
2020-07-28 10:01:37 -07:00
5621452ff0 ci: add more owners for limited categories (#38170)
* Add alxhub, atscott, and AndrewKushnir to code owners
* Add atscott & AndrewKushnir to public-api and size-tracking

Follow-up to #37994

PR Close #38170
2020-07-28 10:01:04 -07:00
b0676e8fab docs: Refactor ngmodule-vs-jsmodule.md to make it easier to understand (#38148)
Project DOCS-734 to rewrite headings to focus on user tasks,
verify that the content is up-to-date and complete, and
add relevant links to other NgModule topics to improve readability.
Also addresses one of many issues in GitHub issue 21531.

PR Close #38148
2020-07-28 10:00:28 -07:00
b142283ba2 fix(core): unify the signature between ngZone and noopZone (#37581)
Now we have two implementations of Zone in Angular, one is NgZone, the other is NoopZone.
They should have the same signatures, includes
1. properties
2. methods

In this PR, unify the signatures of the two implementations, and remove the unnecessary cast.

PR Close #37581
2020-07-28 09:59:49 -07:00
e79b6c31f9 Revert "refactor(core): remove unused export (#38224)"
This reverts commit fbe1a9cbaa.
2020-07-28 09:54:25 -07:00
65cc0c8bd6 fix(compiler-cli): Add support for string literal class members (#38226)
The current implementation of the TypeScriptReflectionHost does not account for members that
are string literals, i.e. `class A { 'string-literal-prop': string; }`

PR Close #38226
2020-07-27 15:26:27 -07:00
03a6252123 docs: update api reference doc for router link directive (#38181)
Edits and organizes the usage information for the directive.

PR Close #38181
2020-07-27 15:25:44 -07:00
174aac68f7 refactor(platform-browser): specify return type of parseEventName (#38089)
This commit refactors the argument of the `parseEventName` function
to use an object with named properties instead of using an object indexer.

PR Close #38089
2020-07-27 15:24:59 -07:00
5d3ba8dec7 test: update ts-api-guardian's strip_export_pattern to exclude Ivy instructions (#38224)
Previously the instructions were included in the golden files to monitor the frequency and rate of
the instruction API changes for the purpose of understanding the stability of this API (as it was
considered for becoming a public API and deployed to npm via generated code).

This experiment has confirmed that the instruction API is not stable enough to be used as public
API. We've since also came up with an alternative plan to compile libraries with the Ivy compiler
for npm deployment and this plan does not rely on making Ivy instructions public.

For these reasons, I'm removing the instructions from the golden files as it's no longer important
to track them.

The are three instructions that are still being included: `ɵɵdefineInjectable`, `ɵɵinject`, and
`ɵɵInjectableDef`.

These instructions are already generated by the VE compiler to support tree-shakable providers, and
code depending on these instructions is already deployed to npm. For this reason we need to treat
them as public api.

This change also reduces the code review overhead, because changes to public api golden files now
require multiple approvals.

PR Close #38224
2020-07-27 14:37:41 -07:00
fbe1a9cbaa refactor(core): remove unused export (#38224)
This export used to be here to turn this file into an ES Module - this is no longer needed
because the file contains imports.

PR Close #38224
2020-07-27 14:37:41 -07:00
8f7d89436f refactor: correct @publicApi and @codeGenApi markers in various files (#38224)
The markers were previously incorrectly assigned. I noticed the issues when reviewing
the golden files and this change corrects them.

PR Close #38224
2020-07-27 14:37:41 -07:00
96aa14df01 fix(zone.js): zone patch rxjs should return null _unsubscribe correctly. (#37091)
Close #31684.

In some rxjs operator, such as `retryWhen`, rxjs internally will set
`Subscription._unsubscribe` method to null, and the current zone.js monkey patch
didn't handle this case correctly, even rxjs set _unsubscribe to null, zone.js
still return a function by finding the prototype chain.

This PR fix this issue and the following test will pass.

```
const errorGenerator = () => {
  return throwError(new Error('error emit'));
};

const genericRetryStrategy = (finalizer: () => void) => (attempts: Observable<any>) =>
    attempts.pipe(
      mergeMap((error, i) => {
        const retryAttempt = i + 1;
        if (retryAttempt > 3) {
          return throwError(error);
        }
        return timer(retryAttempt * 1);
      }),
      finalize(() => finalizer()));

errorGenerator()
  .pipe(
    retryWhen(genericRetryStrategy(() => {
      expect(log.length).toBe(3);
      done();
    })),
    catchError(error => of(error)))
  .subscribe()
```

PR Close #37091
2020-07-27 12:10:27 -07:00
2b6ab57d78 docs: add template ref var to glossary (#36743)
There is not an entry in the glossary for template
reference variable. To clarify for site visitors,
we are adding one here.

PR Close #36743
2020-07-27 12:01:47 -07:00
b65b6163f7 docs: fix breaking URL for RxJS marble testing (#38209)
When checking this URL for the `RxJS marble testing` Ive found it pointing to `Page not found`

PR Close #38209
2020-07-27 11:12:07 -07:00
f74cfadf64 docs: clarify the description of pipes (#37950)
This commit clarifies some of the language regarding pipes in the pipes guide.
This commit also specifies the term transforming rather than formatting.

PR Close #37950
2020-07-27 10:23:20 -07:00
8e5969bb52 fix(compiler): share identical stylesheets between components in the same file (#38213)
Prior to this commit, duplicated styles defined in multiple components in the same file were not
shared between components, thus causing extra payload size. This commit updates compiler logic to
use `ConstantPool` for the styles (while generating the `styles` array on component def), which
enables styles sharing when needed (when duplicates styles are present).

Resolves #38204.

PR Close #38213
2020-07-27 10:04:30 -07:00
8fdfa7b604 refactor(compiler): allow strings with certain length to be included into ConstantPool (#38213)
Prior to this commit, the `ConstantPool` ignored all primitive values. It turned out that it's
beneficial to include strings above certain length to the pool as well. This commit updates the
`ConstantPool` logic to allow such strings to be shared across multiple instances if needed.
For instance, this is helpful for component styles that might be reused across multiple components
in the same file.

PR Close #38213
2020-07-27 10:04:30 -07:00
2fdc18b42c refactor(compiler): separate compilation and transform phases (#38213)
This commit splits the transformation into 2 separate steps: Ivy compilation and actual transformation
of corresponding TS nodes. This is needed to have all `o.Expression`s generated before any TS transforms
happen. This allows `ConstantPool` to properly identify expressions that can be shared across multiple
components declared in the same file.

Resolves #38203.

PR Close #38213
2020-07-27 10:04:30 -07:00
1296003445 docs: add ng-add save option (#38198)
PR Close #38198
2020-07-27 09:52:14 -07:00
4dfc3fe6a2 refactor(router): extract Router config utils to a separate file (#38229)
This commit refactors Router package to move config utils to a separate file for better
organization and to resolve the problem with circular dependency issue.

Resolves #38212.

PR Close #38229
2020-07-27 09:49:14 -07:00
67e3ecc7e3 fix(dev-infra): Ensure conditions with groups do not fail verification (#37798)
There are a few changes in this PR to ensure conditions that are based
on groups (i.e. `- groups.pending.length == 0`) do not fail the verify
task:

* Remove the warning when a condition is encountered that depends on the
`groups` state. The warning will otherwise be printed once for every
file that triggers the execution of the condition (400,000+ times)
* Add an `unverifiable` flag to `GroupCondition` interface and set it to
true when an error is encountered due to attempting to get the state of
`groups` in a condition
* Ignore any unverifiable conditions when gathering unmatched
conditions. These should not be considered `unmatched` for verification
purposes.
* Print the unverifiable conditions by group in the results

Sample output:
```

┌──────────────────────────────────────────────────────────────────────────────┐
│                         PullApprove results by group                         │
└──────────────────────────────────────────────────────────────────────────────┘
Groups skipped (4 groups)
Matched conditions by Group (37 groups)
Unmatched conditions by Group (0 groups)
Unverifiable conditions by Group (3 groups)
  [public-api]
    len(groups.pending.exclude("required-minimum-review")...
    len(groups.rejected.exclude("required-minimum-review")...
  [size-tracking]
    len(groups.pending.exclude("required-minimum-review")...
    len(groups.rejected.exclude("required-minimum-review")...
  [circular-dependencies]
    len(groups.pending.exclude("required-minimum-review")...
    len(groups.rejected.exclude("required-minimum-review")...

```

PR Close #37798
2020-07-24 17:59:39 -07:00
9821443150 feat(dev-infra): add phased review to groups requiring final sign-off after initial review (#37798)
The size-tracking, public-api, and circular-dependencies groups can get a lot of
PRs to review. In addition, the members of these groups do not always
have the necessary context to fully review the PR in question. This
change ensures that the owners in the groups where the changes are being
made have approve the changes (ie, the aren't pending or rejected)
before requesting final sign-off from these three critical groups.

PR Close #37798
2020-07-24 17:59:39 -07:00
c91cdea0cd refactor(dev-infra): create anchors/aliases for excluded always active groups (#37798)
global-approvers, global-docs-approvers, and required-minimum-review groups are always active. It's useful
to have aliases for getting groups that are active/pending/rejected while excluding these few.

PR Close #37798
2020-07-24 17:59:39 -07:00
6a3e68b606 docs(zone.js): update zone.js bundle doc since the APF change (#37919)
Since the PR #36540 change the zone.js bundles to Angular Package Format, the
bundle name/location are changed, so this PR updated the `README.md` doc for the
zone bundles.
Also add the recent added new bundles `zone-patch-message-port` doc.

PR Close #37919
2020-07-24 15:46:45 -07:00
1822cbcd46 fix(zone.js): patch nodejs EventEmtter.prototype.off (#37863)
Close #35473

zone.js nodejs patch should also patch `EventEmitter.prototype.off` as `removeListener`.
So `off` can correctly remove the listeners added by `EventEmitter.prototype.addListener`

PR Close #37863
2020-07-24 15:45:00 -07:00
a71f114ba4 fix(zone.js): clearTimeout/clearInterval should call on object global (#37858)
Close #37333

`clearTimeout` is patched by `zone.js`, and it finally calls the native delegate of `clearTimeout`,
the current implemention only call `clearNative(id)`, but it should call on object `global` like
`clearNative.call(global, id)`. Otherwise in some env, it will throw error
`clearTimeout called on an object that does not implement interface Window`

PR Close #37858
2020-07-24 15:22:47 -07:00
253337dc0a feat(zone.js): move MutationObserver/FileReader to different module (#31657)
Separate `EventTarget`, `FileReader`, `MutationObserver` and `IntersectionObserver` patches into different module.
So the user can disable those modules separately.

PR Close #31657
2020-07-24 15:12:28 -07:00
6e2db228af docs: Fix link by removing a space (#38214)
PR Close #38214
2020-07-24 09:53:06 -07:00
cce5583e75 docs(core): Fix incorrectly rendered code example in structural directives guide (#38207)
The code example was missing a close brace and also incorrectly rendered
the template div as an actual div in the page DOM.

PR Close #38207
2020-07-24 09:52:30 -07:00
307db74e93 docs: fixed that class attribute is not closed (#38219)
PR Close #38219
2020-07-24 08:15:44 -07:00
88d4b269b5 build(docs-infra): simplify ExampleZipper by removing PackageJsonCustomizer (#38192)
Previously, `ExampleZipper` (the tool used for creating ZIP archives
from our docs examples) used the `PackageJsonCustomizer` to generate
`package.json` files for each example type. This had the following
drawbacks:
- The generated files had to be kept up-to-date with the corresponding
  boilerplate files in `aio/tools/examples/shared/boilerplate/` and
  there was no easy way to find out when the files got out-of-sync.
- The `PackageJsonCustomizer` logic was non-trivial and difficult to
  reason about.
- The same information was duplicated in the boilerplate files and the
  customizer configuration files.

This setup was useful when we used a single `package.json` file for all
docs examples. Now, however, each example type can have its own
boilerplate `package.json` file, including scripts and dependencies
relevant to the example type. Therefore, it is no longer necessary to
generate `package.json` files for ZIP archives.

This commit eliminates the drawbacks mentioned above and simplifies the
`ExampleZipper` tool by removing `PackageJsonCustomizer` and re-using
the boilerplate `package.json` files for ZIP archives.

The changes in this commit also fix some ZIP archives that were
previously broken (for example due to missing dependencies).

PR Close #38192
2020-07-23 11:08:11 -07:00
ee22aa592e fix(docs-infra): correctly display copy button in IE11 (#38186)
Fix button top portion was clipped in IE11 by setting overflow to visible

Fixes #37816

PR Close #38186
2020-07-23 11:07:28 -07:00
dd09fb5348 build(docs-infra): upgrade cli command docs sources to b0b27361d (#38182)
Updating [angular#master](https://github.com/angular/angular/tree/master) from
[cli-builds#master](https://github.com/angular/cli-builds/tree/master).

##
Relevant changes in
[commit range](b76099083...b0b27361d):

**Modified**
- help/update.json

PR Close #38182
2020-07-23 11:06:17 -07:00
d0060dcfdc refactor(dev-infra): Add support for groups in the conditions evaluator (#38164)
Conditions can refer to the groups array that is a list of the preceding groups.
This commit adds support to the verification for those conditions.

This commit also adds some tests to the parsing and condition matching
to ensure everything works as expected.

PR Close #38164
2020-07-23 11:05:42 -07:00
7b2e2f5d91 build(forms): create sample forms app (#38044)
This commit creates a sample forms test application to introduce the symbol
tests. It serves as a guard to ensure that any future work on the
forms package does not unintentionally increase the payload size.

PR Close #38044
2020-07-23 11:04:46 -07:00
b518b30dae docs: add Kevin Kreuzer to GDE page (#37929)
This commit adds Kevin Kreuzer to the Angular GDE page along with a biography, his contributions, and a photograph.

PR Close #37929
2020-07-23 11:03:57 -07:00
51aa4aa1c3 docs: update dynamic-component loading guide (#36959)
The 'entryComponents' array is no longer a special case for dynamic component loading because of the Ivy compiler.

PR Close #36959
2020-07-23 11:01:08 -07:00
8bb8f98c28 docs: remove duplicate https:// (#38199)
This doc contained a duplicate `http://` before the domain name leading to an invalid link.
This commit fixes this issue.
PR Close #38199
2020-07-23 10:54:44 -07:00
3c1866b5bb docs: update api reference for router outlet directive (#38166)
Incorporate more specific information about multiple outlets and how to target them, with link to tutorial example.

PR Close #38166
2020-07-22 20:50:12 -07:00
062b8d90af refactor(forms): refactor common validators used in unit tests (#38020)
A util file is added to forms test package:
- it exposes simpleAsyncValidator, asyncValidator and asyncValidatorReturningObservable validators
- it refactors simpleAsyncValidator and asyncValidator to use common promise creation code
- it exposes currentStateOf allowing to get the validation state of a list of AbstractControl

Closes #37831

PR Close #38020
2020-07-22 20:42:43 -07:00
8df888dfb4 fix(elements): run strategy methods in correct zone (#37814)
Default change detection fails in some cases for @angular/elements where
component events are called from the wrong zone.

This fixes the issue by running all ComponentNgElementStrategy methods
in the same zone it was created in.

Fixes #24181

PR Close #37814
2020-07-22 20:35:47 -07:00
778ad3776a docs: create coding standards doc (#37700)
Create initial document for Angular framework coding standards. This
document will evolve over time. This version contains all
non-controversial rules as discussed in a recent team meeting. Some text
and examples were copied from angular/components.

PR Close #37700
2020-07-22 20:32:34 -07:00
5a733629b5 build(docs-infra): remove boilerplate file listings in example-boilerplate.js (#38173)
To avoid unnecessary code duplication in docs examples, we have some
boilerplate files for various example types (in
`aio/tools/examples/shared/boilerplate/`). These files are copied to
each example project in `aio/content/examples/` (according to the
example's type, as specified in its `example-config.json` file).

Previously, the `example-boilerplate.js`, which is responsible for
copying the boilerplate files, had lists for files to be copied for each
project type and only copied the listed files from the boilerplate
directory to the example directory. This approach had some drawbacks:
- Files need to be updated in two separate locations: in the boilerplate
  directory that includes the files and the file list in
  `example-boilerplate.js`.
- It is easy to add a file in the boilerplate directory but forget to
  add it in `example-boilerplate.js` and not realize that it is not
  being included in the example project (including the generated
  StackBlitz project and ZIP archive).

This commit changes the approach by removing the boilerplate file
listings from `example-boilerplate.js` and copying all files from a
boilerplate directory to example directories. This addresses the above
drawbacks and simplifies the `example-boilerplate.js` script.

I have verified that the resulting code example doc regions as well as
the generated StackBlitz projects and ZIP archives are identical to the
ones generated before this commit.

PR Close #38173
2020-07-22 10:15:09 -07:00
65da87722d fix(docs-infra): include .gitignore file in CLI-based docs examples (#38173)
Previously, the `.gitignore` file that is part of the boilerplate files
for CLI-based docs examples (located in
`aio/tools/examples/shared/boilerplate/cli/`) was not added to the
example projects, because it was not included in the boilerplate file
list in `example-boilerplate.js`.

This commit fixes it by adding the `.gitignore` file to the list. This
ensures that docs examples more closely match CLI-generated projects.

PR Close #38173
2020-07-22 10:15:09 -07:00
937b89c230 fix(docs-infra): correctly add polyfills.ts file as boilerplate for i18n docs examples (#38173)
Docs examples of type `i18n` need a slightly modified version of
`polyfills.ts` that imports `@angular/localize/init`. Previously, this
file was not included in `i18n` example projects for two reasons:

- While the file was included in the `i18n` boilerplate files (at
  `aio/tools/examples/shared/boilerplate/i18n/`), it was not included in
  the boilerplate file list in `example-boilerplate.js`.
- The file was in the wrong location: It was located at the project root
  instead of inside the `src/` directory.

This commit addresses the above issues (i.e. adds the file to the
boilerplate file list for `i18n` projects and moves the file inside the
`src/` directory).

PR Close #38173
2020-07-22 10:15:09 -07:00
b3d81a837b build(docs-infra): remove obsolete systemjs.config.web[.build].js files from docs examples (#38173)
There were some `systemjs.config.web[.build].js` files in the `systemjs`
boilerplate directory that are not used any more. In the past, these
files were used in the Plunker-based live examples, but we no longer use
Plunker for live examples.

This commit removes these obsolete files.

PR Close #38173
2020-07-22 10:15:09 -07:00
7491b854b3 build(docs-infra): remove obsolete typings.d.ts files from angular.io and docs examples (#38173)
There were two `typings.d.ts` files with SystemJS module definitions in
`aio/src/` and `aio/tools/examples/shared/boilerplate/cli/`. These are
remnants from old CLI versions that used SystemJS and are no longer
needed. For docs examples specifically, these files were never copied
over to example projects and thus not included in StackBlitz projects
and ZIP archives.

This commit removes these obsolete files.

PR Close #38173
2020-07-22 10:15:09 -07:00
a1c9f7cdb3 docs: fix typo in ng_control.ts (#38157)
PR Close #38157
2020-07-22 10:14:24 -07:00
d88711c2fc docs: add Ivy and View Engine test scripts (#38149)
Developer docs previously stated to use `yarn bazel test //packages/...` which attempts to test all packages with View
Engine (the default), even though not all support View Engine. This updates the doc to use `yarn test-ivy-aot` and
`yarn test-non-ivy` which tests both Ivy and View Engine while filtering out tests which are not compatible with each
renderer.

PR Close #38149
2020-07-22 10:13:29 -07:00
5e742d29d0 docs: fix typo from singular to plural spelling (#36586)
This commit fixes the spelling of the singular form
of the word function to the plural spelling in
packages/core/src/application_init.ts

PR Close #36586
2020-07-22 10:12:44 -07:00
970d10c671 release: cut the v10.1.0-next.2 release 2020-07-22 09:55:21 -07:00
8851ba9c9d docs: release notes for the v10.0.5 release 2020-07-22 09:49:33 -07:00
1397 changed files with 44014 additions and 19765 deletions

View File

@ -136,15 +136,6 @@ build:remote --remote_executor=remotebuildexecution.googleapis.com
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times. # retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
test:saucelabs --flaky_test_attempts=1 test:saucelabs --flaky_test_attempts=1
###############################
# NodeJS rules settings
# These settings are required for rules_nodejs
###############################
# Turn on managed directories feature in Bazel
# This allows us to avoid installing a second copy of node_modules
common --experimental_allow_incremental_repository_updates
#################################################### ####################################################
# User bazel configuration # User bazel configuration
# NOTE: This needs to be the *last* entry in the config. # NOTE: This needs to be the *last* entry in the config.

View File

@ -32,8 +32,8 @@ var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelver
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the # Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable. # cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
var_5: &components_repo_unit_tests_cache_key v7-angular-components-f428c00465dfcf8a020237f22532480eedbd2cb6 var_5: &components_repo_unit_tests_cache_key v9-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components- var_6: &components_repo_unit_tests_cache_key_fallback v9-angular-components-
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and # Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
# `build-ivy-npm-packages`. # `build-ivy-npm-packages`.
@ -653,9 +653,23 @@ jobs:
name: Starting Saucelabs tunnel service name: Starting Saucelabs tunnel service
command: ./tools/saucelabs/sauce-service.sh run command: ./tools/saucelabs/sauce-service.sh run
background: true background: true
- run: yarn tsc -p packages # add module umd tsc compile option so the test can work
- run: yarn tsc -p modules # properly in the legacy browsers
- run: yarn tsc -p packages --module UMD
- run: yarn tsc -p modules --module UMD
- run: yarn bazel build //packages/zone.js:npm_package - run: yarn bazel build //packages/zone.js:npm_package
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
# test in all supported browsers on Saucelabs anyway until this job can be removed.
- run:
name: Preparing Bazel-generated fixtures required in legacy tests
command: |
yarn bazel build //packages/core/test:downleveled_es5_fixture
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
dist/all/@angular/core/test/reflection/es5_downleveled_inheritance_fixture.js
- run: - run:
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready. # Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
name: Waiting for Saucelabs tunnel to connect name: Waiting for Saucelabs tunnel to connect
@ -735,6 +749,8 @@ jobs:
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ && cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
yarn --cwd packages/zone.js electrontest yarn --cwd packages/zone.js electrontest
- run: yarn --cwd packages/zone.js jesttest - run: yarn --cwd packages/zone.js jesttest
- run: yarn --cwd packages/zone.js/test/typings install --frozen-lockfile --non-interactive
- run: yarn --cwd packages/zone.js/test/typings test
# Windows jobs # Windows jobs
# Docs: https://circleci.com/docs/2.0/hello-world-windows/ # Docs: https://circleci.com/docs/2.0/hello-world-windows/

View File

@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git" setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
setPublicVar COMPONENTS_REPO_BRANCH "master" setPublicVar COMPONENTS_REPO_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`. # **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
setPublicVar COMPONENTS_REPO_COMMIT "f428c00465dfcf8a020237f22532480eedbd2cb6" setPublicVar COMPONENTS_REPO_COMMIT "09e68db8ed5b1253f2fe38ff954ef0df019fc25a"
#################################################################################################### ####################################################################################################

View File

@ -1,5 +1,5 @@
--- ---
name: "\U0001F41EBug report" name: "\U0001F41E Bug report"
about: Report a bug in the Angular Framework about: Report a bug in the Angular Framework
--- ---
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅 <!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅

View File

@ -1,5 +1,5 @@
--- ---
name: "\U0001F680Feature request" name: "\U0001F680 Feature request"
about: Suggest a feature for Angular Framework about: Suggest a feature for Angular Framework
--- ---

View File

@ -1,5 +1,5 @@
--- ---
name: "❓Support request" name: "❓ Support request"
about: Questions and requests for support about: Questions and requests for support
--- ---

View File

@ -1,5 +1,5 @@
--- ---
name: "\U0001F6E0Angular CLI" name: "\U0001F6E0 Angular CLI"
about: Issues and feature requests for Angular CLI about: Issues and feature requests for Angular CLI
--- ---

View File

@ -1,5 +1,5 @@
--- ---
name: "\U0001F48EAngular Components" name: "\U0001F48E Angular Components"
about: Issues and feature requests for Angular Components about: Issues and feature requests for Angular Components
--- ---

View File

@ -68,20 +68,20 @@ merge:
- "packages/**/integrationtest/**" - "packages/**/integrationtest/**"
- "packages/**/test/**" - "packages/**/test/**"
- "packages/zone.js/*" - "packages/zone.js/*"
- "packages/zone.js/dist/**"
- "packages/zone.js/doc/**" - "packages/zone.js/doc/**"
- "packages/zone.js/example/**" - "packages/zone.js/example/**"
- "packages/zone.js/scripts/**" - "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 # 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. mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
\nPlease help to unblock it by resolving these conflicts. Thanks!"
# label to monitor # label to monitor
mergeLabel: "PR action: merge" mergeLabel: "action: merge"
# adding any of these labels will also add the merge label # adding any of these labels will also add the merge label
mergeLinkedLabels: mergeLinkedLabels:
- "PR action: merge-assistance" - "action: merge-assistance"
# list of checks that will determine if the merge label can be added # list of checks that will determine if the merge label can be added
checks: checks:
@ -94,17 +94,17 @@ merge:
# whether the PR shouldn't have a conflict with the base branch # whether the PR shouldn't have a conflict with the base branch
noConflict: true 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: requiredLabels:
- "PR target: *" - "target: *"
- "cla: yes" - "cla: yes"
# list of labels that a PR shouldn't have, checked after the required labels with a regexp # list of labels that a PR shouldn't have, checked after the required labels with a regexp
forbiddenLabels: forbiddenLabels:
- "PR target: TBD" - "target: TBD"
- "PR action: cleanup" - "action: cleanup"
- "PR action: review" - "action: review"
- "PR state: blocked" - "state: blocked"
- "cla: no" - "cla: no"
# list of PR statuses that need to be successful # list of PR statuses that need to be successful
@ -121,12 +121,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 # 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 # {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
# {{PLACEHOLDER}} will be replaced by the list of failing checks # {{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: 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."
\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 # options for the triage plugin
triage: triage:
@ -186,4 +181,4 @@ rerunCircleCI:
# set to true to disable # set to true to disable
disabled: false disabled: false
# the label which when added triggers a rerun of the default CircleCI workflow # 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"

View File

@ -10,6 +10,6 @@ jobs:
if: github.repository == 'angular/angular' if: github.repository == 'angular/angular'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: angular/dev-infra/github-actions/lock-closed@66462f6 - uses: angular/dev-infra/github-actions/lock-closed@414834b2b24dd2df37c6ed00808387ee6fd91b66
with: with:
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }} lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}

3
.gitignore vendored
View File

@ -40,6 +40,9 @@ yarn-error.log
# User specific bazel settings # User specific bazel settings
.bazelrc.user .bazelrc.user
# User specific ng-dev settings
.ng-dev.user*
.notes.md .notes.md
baseline.json baseline.json

19
.ng-dev/caretaker.ts Normal file
View 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`,
}
]
};

View File

@ -7,18 +7,6 @@ export const commitMessage: CommitMessageConfig = {
maxLineLength: 120, maxLineLength: 120,
minBodyLength: 20, minBodyLength: 20,
minBodyLengthTypeExcludes: ['docs'], minBodyLengthTypeExcludes: ['docs'],
types: [
'build',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'release',
'style',
'test',
],
scopes: [ scopes: [
'animations', 'animations',
'bazel', 'bazel',

View File

@ -1,3 +1,4 @@
import {caretaker} from './caretaker';
import {commitMessage} from './commit-message'; import {commitMessage} from './commit-message';
import {format} from './format'; import {format} from './format';
import {github} from './github'; import {github} from './github';
@ -8,4 +9,5 @@ module.exports = {
format, format,
github, github,
merge, merge,
caretaker,
}; };

View File

@ -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 * 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). * are respected by the merge script (e.g. the target labels).
*/ */
export const merge = (): MergeConfig => { export const merge: DevInfraMergeConfig['merge'] = async api => {
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
return { return {
githubApiMerge: false, githubApiMerge: false,
claSignedLabel: 'cla: yes', claSignedLabel: 'cla: yes',
mergeReadyLabel: /^PR action: merge(-assistance)?/, mergeReadyLabel: /^action: merge(-assistance)?/,
caretakerNoteLabel: 'PR action: merge-assistance', caretakerNoteLabel: 'action: merge-assistance',
commitMessageFixupLabel: 'commit message fixup', commitMessageFixupLabel: 'commit message fixup',
labels: [ labels: await getDefaultTargetLabelConfiguration(api, github, '@angular/core'),
{
pattern: 'PR target: master-only',
branches: ['master'],
},
{
pattern: 'PR target: patch-only',
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patch],
},
],
requiredBaseCommits: { requiredBaseCommits: {
// PRs that target either `master` or the patch branch, need to be rebased // PRs that target either `master` or the patch branch, need to be rebased
// on top of the latest commit message validation fix. // on top of the latest commit message validation fix.
// These SHAs are the commits that update the required license text in the header. // These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a', 'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24' '10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
}, },
}; };
}; };

View File

@ -67,6 +67,25 @@ version: 3
# Meta field that goes unused by PullApprove to allow for defining aliases to be # Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config. # used throughout the config.
meta: meta:
# The following groups have no file based conditions and will be initially `active` on all PRs
# - `global-approvers`
# - `global-docs-approvers`
# - `required-minimum-review`
#
# By checking the number of active/pending/rejected groups when these are excluded, we can determine
# if any other groups are matched.
#
# Note: Because all inactive groups start as pending, we are only checking pending and rejected active groups.
#
# Also note that the ordering of groups matters in this file. The only groups visible to the current
# one are those that appear above it.
no-groups-above-this-pending: &no-groups-above-this-pending
len(groups.active.pending.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
no-groups-above-this-rejected: &no-groups-above-this-rejected
len(groups.active.rejected.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
no-groups-above-this-active: &no-groups-above-this-active
len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved" can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved" can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
defaults: &defaults defaults: &defaults
@ -490,8 +509,8 @@ groups:
- > - >
contains_any_globs(files, [ contains_any_globs(files, [
'packages/core/src/i18n/**', 'packages/core/src/i18n/**',
'packages/core/src/render3/i18n.ts', 'packages/core/src/render3/i18n/**',
'packages/core/src/render3/i18n.md', 'packages/core/src/render3/instructions/i18n.ts',
'packages/core/src/render3/interfaces/i18n.ts', 'packages/core/src/render3/interfaces/i18n.ts',
'packages/common/locales/**', 'packages/common/locales/**',
'packages/common/src/i18n/**', 'packages/common/src/i18n/**',
@ -863,6 +882,7 @@ groups:
- *can-be-global-docs-approved - *can-be-global-docs-approved
- > - >
contains_any_globs(files, [ contains_any_globs(files, [
'aio/content/guide/roadmap.md',
'aio/content/marketing/**', 'aio/content/marketing/**',
'aio/content/images/bios/**', 'aio/content/images/bios/**',
'aio/content/images/marketing/**', 'aio/content/images/marketing/**',
@ -1090,6 +1110,7 @@ groups:
'dev-infra/**', 'dev-infra/**',
'docs/BAZEL.md', 'docs/BAZEL.md',
'docs/CARETAKER.md', 'docs/CARETAKER.md',
'docs/CODING_STANDARDS.md',
'docs/COMMITTER.md', 'docs/COMMITTER.md',
'docs/DEBUG.md', 'docs/DEBUG.md',
'docs/DEBUG_COMPONENTS_REPO_IVY.md', 'docs/DEBUG_COMPONENTS_REPO_IVY.md',
@ -1142,6 +1163,8 @@ groups:
public-api: public-api:
<<: *defaults <<: *defaults
conditions: conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved - *can-be-global-approved
- > - >
contains_any_globs(files, [ contains_any_globs(files, [
@ -1155,14 +1178,16 @@ groups:
]) ])
reviewers: reviewers:
users: users:
- AndrewKushnir
- IgorMinar - IgorMinar
- alxhub - alxhub
- atscott
- jelbourn - jelbourn
- petebacondarwin - petebacondarwin
- pkozlowski-opensource - pkozlowski-opensource
reviews: reviews:
request: -1 # request reviews from everyone request: 4 # Request reviews from four people
required: 3 # require at least 3 approvals required: 3 # Require that three people approve
reviewed_for: required reviewed_for: required
@ -1172,6 +1197,8 @@ groups:
size-tracking: size-tracking:
<<: *defaults <<: *defaults
conditions: conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved - *can-be-global-approved
- > - >
contains_any_globs(files, [ contains_any_globs(files, [
@ -1179,14 +1206,16 @@ groups:
]) ])
reviewers: reviewers:
users: users:
- AndrewKushnir
- IgorMinar - IgorMinar
- alxhub - alxhub
- atscott
- jelbourn - jelbourn
- petebacondarwin - petebacondarwin
- pkozlowski-opensource - pkozlowski-opensource
reviews: reviews:
request: -1 # request reviews from everyone request: 4 # Request reviews from four people
required: 2 # require at least 2 approvals required: 2 # Require that two people approve
reviewed_for: required reviewed_for: required
@ -1196,6 +1225,8 @@ groups:
circular-dependencies: circular-dependencies:
<<: *defaults <<: *defaults
conditions: conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved - *can-be-global-approved
- > - >
contains_any_globs(files, [ contains_any_globs(files, [
@ -1203,9 +1234,11 @@ groups:
]) ])
reviewers: reviewers:
users: users:
- AndrewKushnir
- IgorMinar - IgorMinar
- alxhub
- atscott
- jelbourn - jelbourn
- josephperrott
- petebacondarwin - petebacondarwin
- pkozlowski-opensource - pkozlowski-opensource
@ -1227,7 +1260,10 @@ groups:
]) ])
reviewers: reviewers:
users: users:
- AndrewKushnir
- IgorMinar - IgorMinar
- alxhub
- atscott
- jelbourn - jelbourn
- josephperrott - josephperrott
- mhevery - mhevery
@ -1257,14 +1293,7 @@ groups:
# `global-approvers` can still approve PRs that match this `fallback` rule, # `global-approvers` can still approve PRs that match this `fallback` rule,
# but that should be an exception and not an expectation. # but that should be an exception and not an expectation.
conditions: conditions:
# The following groups have no file based conditions and will be initially `active` on all PRs - *no-groups-above-this-active
# - `global-approvers`
# - `global-docs-approvers`
# - `required-minimum-review`
#
# By checking the number of active groups when these are excluded, we can determine
# if any other groups are matched.
- len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
# When any of the `global-*` groups is approved, they cause other groups to deactivate. # When any of the `global-*` groups is approved, they cause other groups to deactivate.
# In those cases, the condition above would evaluate to `true` while in reality, only a global # In those cases, the condition above would evaluate to `true` while in reality, only a global
# approval has been provided. To ensure we don't activate the fallback group in such cases, # approval has been provided. To ensure we don't activate the fallback group in such cases,

View File

@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE, const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
// ignore cruft // ignore cruft
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']); 'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']);
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
// never ignore these files // never ignore these files
@ -44663,6 +44663,7 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) { function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
return tar.pack(cwd, { return tar.pack(cwd, {
ignore: ignoreFunction, ignore: ignoreFunction,
sort: true,
map: header => { map: header => {
const suffix = header.name === '.' ? '' : `/${header.name}`; const suffix = header.name === '.' ? '' : `/${header.name}`;
header.name = `package${suffix}`; header.name = `package${suffix}`;
@ -46678,7 +46679,7 @@ function mkdirfix (name, opts, cb) {
/* 194 */ /* 194 */
/***/ (function(module, exports) { /***/ (function(module, exports) {
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}} module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
/***/ }), /***/ }),
/* 195 */ /* 195 */
@ -98338,7 +98339,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
const bundle = yield fetchBundle(config, bundleUrl); const bundle = yield fetchBundle(config, bundleUrl);
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`); const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`);
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`); reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath)); yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
yield (_fs || _load_fs()).writeFile(yarnPath, bundle); yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
@ -100190,7 +100191,7 @@ let main = exports.main = (() => {
const config = new (_config || _load_config()).default(reporter); const config = new (_config || _load_config()).default(reporter);
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true); const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args); const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]);
if (shouldWrapOutput) { if (shouldWrapOutput) {
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version }); reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
@ -100604,7 +100605,7 @@ let start = (() => {
}); });
try { try {
if (yarnPath.endsWith(`.js`)) { if (/\.[cm]?js$/.test(yarnPath)) {
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts); exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
} else { } else {
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts); exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);

View File

@ -2,4 +2,4 @@
# yarn lockfile v1 # yarn lockfile v1
yarn-path ".yarn/releases/yarn-1.22.4.js" yarn-path ".yarn/releases/yarn-1.22.5.js"

View File

@ -34,7 +34,7 @@ filegroup(
filegroup( filegroup(
name = "angularjs_scripts", name = "angularjs_scripts",
srcs = [ srcs = [
# We also declare the unminfied AngularJS files since these can be used for # We also declare the unminified AngularJS files since these can be used for
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts) # local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
"@npm//:node_modules/angular/angular.js", "@npm//:node_modules/angular/angular.js",
"@npm//:node_modules/angular/angular.min.js", "@npm//:node_modules/angular/angular.min.js",

View File

@ -1,3 +1,380 @@
<a name="11.0.0-next.3"></a>
# 11.0.0-next.3 (2020-09-23)
### Bug Fixes
* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600)
* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7))
* **core:** ensure TestBed is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b))
* **forms:** type NG_VALUE_ACCESSOR injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351)
### Features
* **common:** Add ISO week-numbering year formats support to formatDate ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39))
* **compiler:** Parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596)
* **router:** add migration to update calls to navigateByUrl and createUrlTree with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd)), closes [#38227](https://github.com/angular/angular/issues/38227)
* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194)
### BREAKING CHANGES
* **core:** If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This
behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they
throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function.
Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an
error, thus there is a chance that some tests (where `TestBed.overrideProvider` is
called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls
before TestBed initialization is completed.
<a name="10.1.3"></a>
## 10.1.3 (2020-09-23)
### Bug Fixes
* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0))
* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883)
### Reverts
* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6))
<a name="11.0.0-next.2"></a>
# 11.0.0-next.2 (2020-09-16)
### Bug Fixes
* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [/www.ecma-international.org/ecma-262/5.1/#sec-15](https://github.com//www.ecma-international.org/ecma-262/5.1//issues/sec-15) [#37989](https://github.com/angular/angular/issues/37989)
* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003)
* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2))
* **router:** Fix arguments order for call to shouldReuseRoute ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192) [#16192](https://github.com/angular/angular/issues/16192)
### Features
* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db))
* **compiler-cli:** Add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9))
* **compiler-cli:** Add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4))
* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4))
* **compiler-cli:** define interfaces to be used for TemplateTypeChecker ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3))
### Performance Improvements
* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516))
* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060))
* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f))
### BREAKING CHANGES
* **router:** This change corrects the argument order when calling
RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child
routes, they would be called with the future and current arguments would
be swapped. If your RouteReuseStrategy relies specifically on only the future
or current snapshot state, you may need to update the shouldReuseRoute
implementation's use of "future" and "current" ActivateRouteSnapshots.
* **common:** The locale data API has been marked as returning readonly arrays, rather
than mutable arrays, since these arrays are shared across calls to the
API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc)
then your code will not longer compile. If you need to mutate the array, you
should now take a copy (e.g. by calling `slice()`) and mutate the copy.
* **common:** When passing a date-time formatted string to the `DatePipe` in a format that contains
fractions of a millisecond, the milliseconds will now always be rounded down rather than
to the nearest millisecond.
Most applications will not be affected by this change. If this is not the desired behaviour
then consider pre-processing the string to round the millisecond part before passing
it to the `DatePipe`.
<a name="10.1.2"></a>
## 10.1.2 (2020-09-16)
### Bug Fixes
* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539)
* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619)
* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d))
* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691)
* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579)
### Performance Improvements
* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405))
* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67))
* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7))
* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466))
<a name="11.0.0-next.1"></a>
# 11.0.0-next.1 (2020-09-09)
### Bug Fixes
* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd)), closes [#38588](https://github.com/angular/angular/issues/38588)
* **core:** remove CollectionChangeRecord symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180))
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842)
### BREAKING CHANGES
* **core:** CollectionChangeRecord has been removed, use IterableChangeRecord
instead
<a name="10.1.1"></a>
## 10.1.1 (2020-09-09)
### Bug Fixes
* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6))
* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588)
* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670)
* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600)
* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692)
* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679)
* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329)
* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377)
* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705)
* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238)
* **router:** If users are using the Alt key when clicking the router links, prioritize browsers default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d))
### Performance Improvements
* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff))
<a name="11.0.0-next.0"></a>
# 11.0.0-next.0 (2020-09-02)
### Bug Fixes
* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542)
* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf))
### Features
* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539)
### BREAKING CHANGES
* **forms:** Previously if FormControl, FormGroup and FormArray class instances had async validators
defined at initialization time, the status change event was not emitted once async validator
completed. After this change the status event is emitted into the `statusChanges` observable.
If your code relies on the old behavior, you can filter/ignore this additional status change
event.
<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))
### 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))
<a name="10.0.14"></a>
## 10.0.14 (2020-08-26)
<a name="10.0.12"></a>
## 10.0.12 (2020-08-24)
### Bug Fixes
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
### Features
* **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.0.11"></a>
## 10.0.11 (2020-08-19)
### Bug Fixes
* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469)
<a name="10.0.10"></a>
## 10.0.10 (2020-08-17)
### Bug Fixes
* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630)
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453)
* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292)
* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201)
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469)
<a name="10.0.9"></a>
## 10.0.9 (2020-08-12)
### Bug Fixes
* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629)
* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194)
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912)
* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568)
* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147)
* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82))
* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311)
* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105)
* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315)
* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f))
* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149))
* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314))
* **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.0.8"></a>
## 10.0.8 (2020-08-04)
### Bug Fixes
* **compiler:** add PURE annotation to getInheritedFactory calls ([#38291](https://github.com/angular/angular/issues/38291)) ([03d8e31](https://github.com/angular/angular/commit/03d8e31))
* **compiler:** update unparsable character reference entity error messages ([#38319](https://github.com/angular/angular/issues/38319)) ([cea4678](https://github.com/angular/angular/commit/cea4678)), closes [#26067](https://github.com/angular/angular/issues/26067)
<a name="10.0.7"></a>
## 10.0.7 (2020-07-30)
### Bug Fixes
* **compiler:** Metadata should not include methods on Object.prototype ([#38292](https://github.com/angular/angular/issues/38292)) ([879ff08](https://github.com/angular/angular/commit/879ff08))
<a name="10.0.6"></a>
## 10.0.6 (2020-07-28)
### Bug Fixes
* **compiler:** share identical stylesheets between components in the same file ([#38213](https://github.com/angular/angular/issues/38213)) ([264950b](https://github.com/angular/angular/commit/264950b)), closes [#38204](https://github.com/angular/angular/issues/38204)
* **compiler-cli:** Add support for string literal class members ([#38226](https://github.com/angular/angular/issues/38226)) ([b1e7775](https://github.com/angular/angular/commit/b1e7775))
* **core:** `Attribute` decorator `attributeName` is mandatory ([#38131](https://github.com/angular/angular/issues/38131)) ([1c4fcce](https://github.com/angular/angular/commit/1c4fcce)), closes [#32658](https://github.com/angular/angular/issues/32658)
* **core:** unify the signature between ngZone and noopZone ([#37581](https://github.com/angular/angular/issues/37581)) ([d5264f5](https://github.com/angular/angular/commit/d5264f5))
<a name="10.0.5"></a>
## 10.0.5 (2020-07-22)
### Bug Fixes
* **compiler:** properly associate source spans for implicitly closed elements ([#38126](https://github.com/angular/angular/issues/38126)) ([e80278c](https://github.com/angular/angular/commit/e80278c)), closes [#36118](https://github.com/angular/angular/issues/36118)
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#38030](https://github.com/angular/angular/issues/38030)) ([dba4023](https://github.com/angular/angular/commit/dba4023)), closes [#36777](https://github.com/angular/angular/issues/36777)
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#38119](https://github.com/angular/angular/issues/38119)) ([14b4718](https://github.com/angular/angular/commit/14b4718)), closes [#30497](https://github.com/angular/angular/issues/30497)
* **core:** error due to integer overflow when there are too many host bindings ([#38014](https://github.com/angular/angular/issues/38014)) ([7b6e73c](https://github.com/angular/angular/commit/7b6e73c)), closes [#37876](https://github.com/angular/angular/issues/37876) [#37876](https://github.com/angular/angular/issues/37876)
* **core:** incorrectly validating properties on ng-content and ng-container ([#37773](https://github.com/angular/angular/issues/37773)) ([17ddab9](https://github.com/angular/angular/commit/17ddab9))
<a name="10.0.4"></a> <a name="10.0.4"></a>
## 10.0.4 (2020-07-15) ## 10.0.4 (2020-07-15)
@ -18,62 +395,6 @@
* **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) * **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> <a name="10.0.3"></a>
## 10.0.3 (2020-07-08) ## 10.0.3 (2020-07-08)
@ -355,12 +676,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more
information and updates. information and updates.
If you used Closure Compiler with Angular in the past, you will likely 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, rather than consuming the version we publish on npm,
which is primarily optimized for Webpack/Rollup + Terser build pipeline. which is primarily optimized for Webpack/Rollup + Terser build pipeline.
As a temporary workaround, you might consider using your current build 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 will ensure that your build pipeline produces buildable and
runnable artifacts, at the cost of increased payload size due to runnable artifacts, at the cost of increased payload size due to
advanced optimizations being disabled. advanced optimizations being disabled.
@ -368,17 +689,17 @@ advanced optimizations being disabled.
If you were affected by this change, please help us understand your 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. 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). 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: 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). 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. 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. You should contact the library author to fix their library to provide a type parameter when they use this class.
@ -1706,7 +2027,7 @@ API surface going forward.
* **core:** Injector.get now accepts abstract classes to return * **core:** Injector.get now accepts abstract classes to return
type-safe values. Previous implementation returned `any` through the type-safe values. Previous implementation returned `any` through the
deprecated implementation. 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). 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).

View File

@ -230,7 +230,6 @@ Must be one of the following:
* **fix**: A bug fix * **fix**: A bug fix
* **perf**: A code change that improves performance * **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature * **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 * **test**: Adding missing tests or correcting existing tests

View File

@ -16,13 +16,6 @@ import {BuildNums, PrNums, SHA} from './constants';
const logger = new Logger('mock-external-apis'); const logger = new Logger('mock-external-apis');
const log = (...args: any[]) => {
// Filter out non-matching URL checks
if (!/^matching.+: false$/.test(args[0])) {
logger.log(...args);
}
};
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN'); const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN'); const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
@ -91,8 +84,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
}; };
// Create request scopes // Create request scopes
const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist(); const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`); const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
////////////////////////////// //////////////////////////////

View File

@ -27,28 +27,28 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"delete-empty": "^3.0.0", "delete-empty": "^3.0.0",
"express": "^4.17.1", "express": "^4.17.1",
"jasmine": "^3.5.0", "jasmine": "^3.6.1",
"nock": "^12.0.3", "nock": "^13.0.4",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.1",
"shelljs": "^0.8.4", "shelljs": "^0.8.4",
"source-map-support": "^0.5.19", "source-map-support": "^0.5.19",
"tar-stream": "^2.1.2", "tar-stream": "^2.1.3",
"tslib": "^1.11.1" "tslib": "^2.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/body-parser": "^1.19.0", "@types/body-parser": "^1.19.0",
"@types/express": "^4.17.6", "@types/express": "^4.17.8",
"@types/jasmine": "^3.5.10", "@types/jasmine": "^3.5.14",
"@types/nock": "^11.1.0", "@types/nock": "^11.1.0",
"@types/node": "^13.13.2", "@types/node": "^14.6.4",
"@types/node-fetch": "^2.5.7", "@types/node-fetch": "^2.5.7",
"@types/shelljs": "^0.8.7", "@types/shelljs": "^0.8.8",
"@types/supertest": "^2.0.8", "@types/supertest": "^2.0.10",
"nodemon": "^2.0.3", "nodemon": "^2.0.4",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"supertest": "^4.0.2", "supertest": "^4.0.2",
"tslint": "^6.1.1", "tslint": "^6.1.3",
"tslint-jasmine-noSkipOrFocus": "^1.0.9", "tslint-jasmine-noSkipOrFocus": "^1.0.9",
"typescript": "^3.8.3" "typescript": "^4.0.2"
} }
} }

View File

@ -214,23 +214,24 @@ describe('GithubApi', () => {
}); });
it('should call \'https.request()\' with the correct options', () => { it('should call \'https.request()\' with the correct options', async () => {
const requestHandler = nock('https://api.github.com') const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method') .intercept('/path', 'method')
.reply(200); .reply(200);
(api as any).request('method', '/path'); await (api as any).request('method', '/path');
requestHandler.done(); requestHandler.done();
}); });
it('should add the \'Authorization\' header containing the \'githubToken\'', () => { it('should add the \'Authorization\' header containing the \'githubToken\'', async () => {
const requestHandler = nock('https://api.github.com') const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method', undefined, { .intercept('/path', 'method', undefined, {
reqheaders: {Authorization: 'token 12345'}, reqheaders: {Authorization: 'token 12345'},
}) })
.reply(200); .reply(200);
(api as any).request('method', '/path');
await (api as any).request('method', '/path');
requestHandler.done(); requestHandler.done();
}); });
@ -244,12 +245,13 @@ describe('GithubApi', () => {
}); });
it('should \'JSON.stringify\' and send the data along with the request', () => { it('should \'JSON.stringify\' and send the data along with the request', async () => {
const data = {key: 'value'}; const data = {key: 'value'};
const requestHandler = nock('https://api.github.com') const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method', JSON.stringify(data)) .intercept('/path', 'method', JSON.stringify(data))
.reply(200); .reply(200);
(api as any).request('method', '/path', data);
await (api as any).request('method', '/path', data);
requestHandler.done(); requestHandler.done();
}); });

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
**/src/karma.conf.js **/src/karma.conf.js
**/.angular-cli.json **/.angular-cli.json
**/.editorconfig **/.editorconfig
**/.gitignore
**/angular.json **/angular.json
**/tsconfig.json **/tsconfig.json
**/bs-config.e2e.json **/bs-config.e2e.json

View File

@ -1,5 +1,3 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Accessibility example e2e tests', () => { describe('Accessibility example e2e tests', () => {
@ -8,11 +6,11 @@ describe('Accessibility example e2e tests', () => {
browser.get(''); browser.get('');
}); });
it('should display Accessibility Example', function () { it('should display Accessibility Example', () => {
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example'); expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
}); });
it('should take a number and change progressbar width', function () { it('should take a number and change progressbar width', () => {
element(by.css('input')).sendKeys('16'); element(by.css('input')).sendKeys('16');
expect(element(by.css('input')).getAttribute('value')).toEqual('016'); expect(element(by.css('input')).getAttribute('value')).toEqual('016');
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px'); expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');

View File

@ -1,3 +1,4 @@
// tslint:disable: no-host-metadata-property
// #docregion progressbar-component // #docregion progressbar-component
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';

View File

@ -1,20 +1,18 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('AngularJS to Angular Quick Reference Tests', function () { describe('AngularJS to Angular Quick Reference Tests', () => {
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it('should display no poster images after bootstrap', function () { it('should display no poster images after bootstrap', () => {
testImagesAreDisplayed(false); testImagesAreDisplayed(false);
}); });
it('should display proper movie data', function () { it('should display proper movie data', () => {
// We check only a few samples // We check only a few samples
let expectedSamples: any[] = [ const expectedSamples: any[] = [
{row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true}, {row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true},
{row: 0, column: 2, value: 'Celeritas'}, {row: 0, column: 2, value: 'Celeritas'},
{row: 1, column: 3, matches: /Dec 1[678], 2015/}, // absorb timezone dif; we care about date format {row: 1, column: 3, matches: /Dec 1[678], 2015/}, // absorb timezone dif; we care about date format
@ -25,18 +23,17 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
]; ];
// Go through the samples // Go through the samples
let movieRows = getMovieRows(); const movieRows = getMovieRows();
for (let i = 0; i < expectedSamples.length; i++) { for (const sample of expectedSamples) {
let sample = expectedSamples[i]; const tableCell = movieRows.get(sample.row)
let tableCell = movieRows.get(sample.row)
.all(by.tagName('td')).get(sample.column); .all(by.tagName('td')).get(sample.column);
// Check the cell or its nested element // Check the cell or its nested element
let elementToCheck = sample.element const elementToCheck = sample.element
? tableCell.element(by.tagName(sample.element)) ? tableCell.element(by.tagName(sample.element))
: tableCell; : tableCell;
// Check element attribute or text // Check element attribute or text
let valueToCheck = sample.attr const valueToCheck = sample.attr
? elementToCheck.getAttribute(sample.attr) ? elementToCheck.getAttribute(sample.attr)
: elementToCheck.getText(); : elementToCheck.getText();
@ -51,42 +48,42 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
} }
}); });
it('should display images after Show Poster', function () { it('should display images after Show Poster', () => {
testPosterButtonClick('Show Poster', true); testPosterButtonClick('Show Poster', true);
}); });
it('should hide images after Hide Poster', function () { it('should hide images after Hide Poster', () => {
testPosterButtonClick('Hide Poster', false); testPosterButtonClick('Hide Poster', false);
}); });
it('should display no movie when no favorite hero is specified', function () { it('should display no movie when no favorite hero is specified', () => {
testFavoriteHero(null, 'Please enter your favorite hero.'); testFavoriteHero(null, 'Please enter your favorite hero.');
}); });
it('should display no movie for Magneta', function () { it('should display no movie for Magneta', () => {
testFavoriteHero('Magneta', 'No movie, sorry!'); testFavoriteHero('Magneta', 'No movie, sorry!');
}); });
it('should display a movie for Dr Nice', function () { it('should display a movie for Dr Nice', () => {
testFavoriteHero('Dr Nice', 'Excellent choice!'); testFavoriteHero('Dr Nice', 'Excellent choice!');
}); });
function testImagesAreDisplayed(isDisplayed: boolean) { function testImagesAreDisplayed(isDisplayed: boolean) {
let expectedMovieCount = 3; const expectedMovieCount = 3;
let movieRows = getMovieRows(); const movieRows = getMovieRows();
expect(movieRows.count()).toBe(expectedMovieCount); expect(movieRows.count()).toBe(expectedMovieCount);
for (let i = 0; i < expectedMovieCount; i++) { for (let i = 0; i < expectedMovieCount; i++) {
let movieImage = movieRows.get(i).element(by.css('td > img')); const movieImage = movieRows.get(i).element(by.css('td > img'));
expect(movieImage.isDisplayed()).toBe(isDisplayed); expect(movieImage.isDisplayed()).toBe(isDisplayed);
} }
} }
function testPosterButtonClick(expectedButtonText: string, isDisplayed: boolean) { function testPosterButtonClick(expectedButtonText: string, isDisplayed: boolean) {
let posterButton = element(by.css('app-movie-list tr > th > button')); const posterButton = element(by.css('app-movie-list tr > th > button'));
expect(posterButton.getText()).toBe(expectedButtonText); expect(posterButton.getText()).toBe(expectedButtonText);
posterButton.click().then(function () { posterButton.click().then(() => {
testImagesAreDisplayed(isDisplayed); testImagesAreDisplayed(isDisplayed);
}); });
} }
@ -96,12 +93,12 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
} }
function testFavoriteHero(heroName: string, expectedLabel: string) { function testFavoriteHero(heroName: string, expectedLabel: string) {
let movieListComp = element(by.tagName('app-movie-list')); const movieListComp = element(by.tagName('app-movie-list'));
let heroInput = movieListComp.element(by.tagName('input')); const heroInput = movieListComp.element(by.tagName('input'));
let favoriteHeroLabel = movieListComp.element(by.tagName('h3')); const favoriteHeroLabel = movieListComp.element(by.tagName('h3'));
let resultLabel = movieListComp.element(by.css('span > p')); const resultLabel = movieListComp.element(by.css('span > p'));
heroInput.clear().then(function () { heroInput.clear().then(() => {
heroInput.sendKeys(heroName || ''); heroInput.sendKeys(heroName || '');
expect(resultLabel.getText()).toBe(expectedLabel); expect(resultLabel.getText()).toBe(expectedLabel);
if (heroName) { if (heroName) {

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { MovieListComponent } from './movie-list.component'; import { MovieListComponent } from './movie-list.component';

View File

@ -1,8 +1,8 @@
// #docregion // #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@NgModule({ @NgModule({
imports: [ BrowserModule ], imports: [ BrowserModule ],

View File

@ -1,9 +1,9 @@
// #docregion // #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { MovieListComponent } from './movie-list.component'; import { MovieListComponent } from './movie-list.component';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';

View File

@ -1,5 +1,3 @@
'use strict'; // necessary for es6 output in node
import { browser, ExpectedConditions as EC } from 'protractor'; import { browser, ExpectedConditions as EC } from 'protractor';
import { logging } from 'selenium-webdriver'; import { logging } from 'selenium-webdriver';
import * as openClose from './open-close.po'; import * as openClose from './open-close.po';

View File

@ -34,7 +34,7 @@ export class AppComponent {
// #docregion prepare-router-outlet // #docregion prepare-router-outlet
prepareRoute(outlet: RouterOutlet) { prepareRoute(outlet: RouterOutlet) {
return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation']; return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
} }
// #enddocregion prepare-router-outlet // #enddocregion prepare-router-outlet

View File

@ -1,4 +1,6 @@
// tslint:disable: variable-name
// #docplaster // #docplaster
// #docregion
import { Component, HostBinding, OnInit } from '@angular/core'; import { Component, HostBinding, OnInit } from '@angular/core';
import { trigger, transition, animate, style, query, stagger } from '@angular/animations'; import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
@ -52,13 +54,11 @@ export class HeroListPageComponent implements OnInit {
@HostBinding('@pageAnimations') @HostBinding('@pageAnimations')
public animatePage = true; public animatePage = true;
_heroes = [];
// #docregion filter-animations // #docregion filter-animations
heroTotal = -1; heroTotal = -1;
// #enddocregion filter-animations // #enddocregion filter-animations
get heroes() { get heroes() { return this._heroes; }
return this._heroes; private _heroes = [];
}
ngOnInit() { ngOnInit() {
this._heroes = HEROES; this._heroes = HEROES;

View File

@ -8,8 +8,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
// #docregion trigger, trigger-wildcard1, trigger-transition // #docregion trigger, trigger-wildcard1, trigger-transition
animations: [ animations: [
trigger('openClose', [ trigger('openClose', [
// #enddocregion events1 // #docregion state1
// #docregion state1, events1
// ... // ...
// #enddocregion events1 // #enddocregion events1
state('open', style({ state('open', style({
@ -34,8 +33,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
transition('closed => open', [ transition('closed => open', [
animate('0.5s') animate('0.5s')
]), ]),
// #enddocregion trigger, component // #enddocregion transition2, trigger, component
// #enddocregion transition2
// #docregion trigger-wildcard1 // #docregion trigger-wildcard1
transition('* => closed', [ transition('* => closed', [
animate('1s') animate('1s')
@ -70,7 +68,9 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
}) })
// #docregion events // #docregion events
export class OpenCloseComponent { export class OpenCloseComponent {
// #enddocregion events1, events // #enddocregion events1, events, component
@Input() logging = false;
// #docregion component
isOpen = true; isOpen = true;
toggle() { toggle() {
@ -78,9 +78,8 @@ export class OpenCloseComponent {
} }
// #enddocregion component // #enddocregion component
@Input() logging = false;
// #docregion events1, events // #docregion events1, events
onAnimationEvent ( event: AnimationEvent ) { onAnimationEvent( event: AnimationEvent ) {
// #enddocregion events1, events // #enddocregion events1, events
if (!this.logging) { if (!this.logging) {
return; return;

View File

@ -1,5 +1,3 @@
'use strict'; // necessary for es6 output in node
import { protractor, browser, element, by, ElementFinder } from 'protractor'; import { protractor, browser, element, by, ElementFinder } from 'protractor';
const nameSuffix = 'X'; const nameSuffix = 'X';
@ -21,7 +19,7 @@ describe('Architecture', () => {
}); });
it(`has h2 '${expectedH2}'`, () => { it(`has h2 '${expectedH2}'`, () => {
let h2 = element.all(by.css('h2')).map((elt: any) => elt.getText()); const h2 = element.all(by.css('h2')).map((elt: any) => elt.getText());
expect(h2).toEqual(expectedH2); expect(h2).toEqual(expectedH2);
}); });
@ -34,42 +32,42 @@ function heroTests() {
const targetHero: Hero = { id: 2, name: 'Dr Nice' }; const targetHero: Hero = { id: 2, name: 'Dr Nice' };
it('has the right number of heroes', () => { it('has the right number of heroes', () => {
let page = getPageElts(); const page = getPageElts();
expect(page.heroes.count()).toEqual(3); expect(page.heroes.count()).toEqual(3);
}); });
it('has no hero details initially', function () { it('has no hero details initially', () => {
let page = getPageElts(); const page = getPageElts();
expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail'); expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail');
}); });
it('shows selected hero details', async () => { it('shows selected hero details', async () => {
await element(by.cssContainingText('li', targetHero.name)).click(); await element(by.cssContainingText('li', targetHero.name)).click();
let page = getPageElts(); const page = getPageElts();
let hero = await heroFromDetail(page.heroDetail); const hero = await heroFromDetail(page.heroDetail);
expect(hero.id).toEqual(targetHero.id); expect(hero.id).toEqual(targetHero.id);
expect(hero.name).toEqual(targetHero.name); expect(hero.name).toEqual(targetHero.name);
}); });
it(`shows updated hero name in details`, async () => { it(`shows updated hero name in details`, async () => {
let input = element.all(by.css('input')).first(); const input = element.all(by.css('input')).first();
input.sendKeys(nameSuffix); input.sendKeys(nameSuffix);
let page = getPageElts(); const page = getPageElts();
let hero = await heroFromDetail(page.heroDetail); const hero = await heroFromDetail(page.heroDetail);
let newName = targetHero.name + nameSuffix; const newName = targetHero.name + nameSuffix;
expect(hero.id).toEqual(targetHero.id); expect(hero.id).toEqual(targetHero.id);
expect(hero.name).toEqual(newName); expect(hero.name).toEqual(newName);
}); });
} }
function salesTaxTests() { function salesTaxTests() {
it('has no sales tax initially', function () { it('has no sales tax initially', () => {
let page = getPageElts(); const page = getPageElts();
expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info'); expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info');
}); });
it('shows sales tax', async function () { it('shows sales tax', async () => {
let page = getPageElts(); const page = getPageElts();
page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER); page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER);
expect(page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00'); expect(page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00');
}); });
@ -88,13 +86,11 @@ function getPageElts() {
async function heroFromDetail(detail: ElementFinder): Promise<Hero> { async function heroFromDetail(detail: ElementFinder): Promise<Hero> {
// Get hero id from the first <div> // Get hero id from the first <div>
// let _id = await detail.all(by.css('div')).first().getText(); const id = await detail.all(by.css('div')).first().getText();
let _id = await detail.all(by.css('div')).first().getText();
// Get name from the h2 // Get name from the h2
// let _name = await detail.element(by.css('h4')).getText(); const name = await detail.element(by.css('h4')).getText();
let _name = await detail.element(by.css('h4')).getText();
return { return {
id: +_id.substr(_id.indexOf(' ') + 1), id: +id.substr(id.indexOf(' ') + 1),
name: _name.substr(0, _name.lastIndexOf(' ')) name: name.substr(0, name.lastIndexOf(' ')),
}; };
} }

View File

@ -1,15 +1,15 @@
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
// #docregion imports // #docregion imports
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
// #enddocregion imports // #enddocregion imports
import { HeroDetailComponent } from './hero-detail.component'; import { HeroDetailComponent } from './hero-detail.component';
import { HeroListComponent } from './hero-list.component'; import { HeroListComponent } from './hero-list.component';
import { SalesTaxComponent } from './sales-tax.component'; import { SalesTaxComponent } from './sales-tax.component';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
import { BackendService } from './backend.service'; import { BackendService } from './backend.service';
import { Logger } from './logger.service'; import { Logger } from './logger.service';
@NgModule({ @NgModule({
imports: [ imports: [

View File

@ -18,7 +18,7 @@ export class BackendService {
// TODO: get from the database // TODO: get from the database
return Promise.resolve<Hero[]>(HEROES); return Promise.resolve<Hero[]>(HEROES);
} }
let err = new Error('Cannot get object of this type'); const err = new Error('Cannot get object of this type');
this.logger.error(err); this.logger.error(err);
throw err; throw err;
} }

View File

@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
// #docregion metadata, providers // #docregion metadata, providers
@Component({ @Component({

View File

@ -22,7 +22,7 @@ export class AppComponent {
} }
// #docregion module // #docregion module
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
// #docregion import-browser-module // #docregion import-browser-module
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
// #enddocregion import-browser-module // #enddocregion import-browser-module

View File

@ -1,7 +1,7 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { SalesTaxService } from './sales-tax.service'; import { SalesTaxService } from './sales-tax.service';
import { TaxRateService } from './tax-rate.service'; import { TaxRateService } from './tax-rate.service';
@Component({ @Component({
selector: 'app-sales-tax', selector: 'app-sales-tax',

View File

@ -7,7 +7,7 @@ export class SalesTaxService {
constructor(private rateService: TaxRateService) { } constructor(private rateService: TaxRateService) { }
getVAT(value: string | number) { getVAT(value: string | number) {
let amount = (typeof value === 'string') ? const amount = (typeof value === 'string') ?
parseFloat(value) : value; parseFloat(value) : value;
return (amount || 0) * this.rateService.getRate('VAT'); return (amount || 0) * this.rateService.getRate('VAT');
} }

View File

@ -1,34 +1,32 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Attribute binding example', function () { describe('Attribute binding example', () => {
beforeEach(function () { beforeEach(() => {
browser.get(''); browser.get('');
}); });
it('should display Property Binding with Angular', function () { it('should display Property Binding with Angular', () => {
expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings'); expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings');
}); });
it('should display a table', function() { it('should display a table', () => {
expect(element.all(by.css('table')).isPresent()).toBe(true); expect(element.all(by.css('table')).isPresent()).toBe(true);
}); });
it('should display an Aria button', function () { it('should display an Aria button', () => {
expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria'); expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria');
}); });
it('should display a blue background on div', function () { it('should display a blue background on div', () => {
expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)'); expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)');
}); });
it('should display a blue div with a red border', function () { it('should display a blue div with a red border', () => {
expect(element.all(by.css('div')).get(1).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)'); expect(element.all(by.css('div')).get(1).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
}); });
it('should display a div with many classes', function () { it('should display a div with many classes', () => {
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('special'); expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('special');
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('clearance'); expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('clearance');
}); });

View File

@ -1,16 +1,16 @@
import { Component } from '@angular/core'; import { Component, HostBinding } from '@angular/core';
@Component({ @Component({
selector: 'comp-with-host-binding', selector: 'comp-with-host-binding',
template: 'I am a component!', template: 'I am a component!',
host: {
'[class.special]': 'isSpecial',
'[style.color]': 'color',
'[style.width]': 'width'
}
}) })
export class CompWithHostBindingComponent { export class CompWithHostBindingComponent {
@HostBinding('class.special')
isSpecial = false; isSpecial = false;
@HostBinding('style.color')
color = 'green'; color = 'green';
@HostBinding('style.width')
width = '200px'; width = '200px';
} }

View File

@ -1,17 +1,15 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Attribute directives', () => { describe('Attribute directives', () => {
let _title = 'My First Attribute Directive'; const title = 'My First Attribute Directive';
beforeAll(() => { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it(`should display correct title: ${_title}`, () => { it(`should display correct title: ${title}`, () => {
expect(element(by.css('h1')).getText()).toEqual(_title); expect(element(by.css('h1')).getText()).toEqual(title);
}); });
it('should be able to select green highlight', () => { it('should be able to select green highlight', () => {

View File

@ -3,7 +3,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component.1'; import { AppComponent } from './app.component.1';
import { HighlightDirective as HLD1 } from './highlight.directive.1'; import { HighlightDirective as HLD1 } from './highlight.directive.1';
import { HighlightDirective as HLD2 } from './highlight.directive.2'; import { HighlightDirective as HLD2 } from './highlight.directive.2';
import { HighlightDirective as HLD3 } from './highlight.directive.3'; import { HighlightDirective as HLD3 } from './highlight.directive.3';

View File

@ -3,57 +3,55 @@ import { logging } from 'selenium-webdriver';
describe('Binding syntax e2e tests', () => { describe('Binding syntax e2e tests', () => {
beforeEach(function () { beforeEach(() => browser.get(''));
browser.get('');
});
// helper function used to test what's logged to the console // helper function used to test what's logged to the console
async function logChecker(button, contents) { async function logChecker(button, contents) {
const logs = await browser.manage().logs().get(logging.Type.BROWSER); const logs = await browser.manage().logs().get(logging.Type.BROWSER);
const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false); const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
expect(message.length).toBeGreaterThan(0); expect(messages.length).toBeGreaterThan(0);
} }
it('should display Binding syntax', function () { it('should display Binding syntax', () => {
expect(element(by.css('h1')).getText()).toEqual('Binding syntax'); expect(element(by.css('h1')).getText()).toEqual('Binding syntax');
}); });
it('should display Save button', function () { it('should display Save button', () => {
expect(element.all(by.css('button')).get(0).getText()).toBe('Save'); expect(element.all(by.css('button')).get(0).getText()).toBe('Save');
}); });
it('should display HTML attributes and DOM properties', function () { it('should display HTML attributes and DOM properties', () => {
expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties'); expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
}); });
it('should display 1. Use the inspector...', function () { it('should display 1. Use the inspector...', () => {
expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector'); expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector');
}); });
it('should display Disabled property vs. attribute', function () { it('should display Disabled property vs. attribute', () => {
expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute'); expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
}); });
it('should log a message including Sarah', async () => { it('should log a message including Sarah', async () => {
let attributeButton = element.all(by.css('button')).get(1); const attributeButton = element.all(by.css('button')).get(1);
await attributeButton.click(); await attributeButton.click();
const contents = 'Sarah'; const contents = 'Sarah';
logChecker(attributeButton, contents); logChecker(attributeButton, contents);
}); });
it('should log a message including Sarah for DOM property', async () => { it('should log a message including Sarah for DOM property', async () => {
let DOMPropertyButton = element.all(by.css('button')).get(2); const DOMPropertyButton = element.all(by.css('button')).get(2);
await DOMPropertyButton.click(); await DOMPropertyButton.click();
const contents = 'Sarah'; const contents = 'Sarah';
logChecker(DOMPropertyButton, contents); logChecker(DOMPropertyButton, contents);
}); });
it('should log a message including Sally for DOM property', async () => { it('should log a message including Sally for DOM property', async () => {
let DOMPropertyButton = element.all(by.css('button')).get(2); const DOMPropertyButton = element.all(by.css('button')).get(2);
let input = element(by.css('input')); const input = element(by.css('input'));
input.sendKeys('Sally'); input.sendKeys('Sally');
await DOMPropertyButton.click(); await DOMPropertyButton.click();
const contents = 'Sally'; const contents = 'Sally';
@ -61,14 +59,14 @@ describe('Binding syntax e2e tests', () => {
}); });
it('should log a message that Test Button works', async () => { it('should log a message that Test Button works', async () => {
let testButton = element.all(by.css('button')).get(3); const testButton = element.all(by.css('button')).get(3);
await testButton.click(); await testButton.click();
const contents = 'Test'; const contents = 'Test';
logChecker(testButton, contents); logChecker(testButton, contents);
}); });
it('should toggle Test Button disabled', async () => { it('should toggle Test Button disabled', async () => {
let toggleButton = element.all(by.css('button')).get(4); const toggleButton = element.all(by.css('button')).get(4);
await toggleButton.click(); await toggleButton.click();
const contents = 'true'; const contents = 'true';
logChecker(toggleButton, contents); logChecker(toggleButton, contents);

View File

@ -26,7 +26,7 @@ export class AppComponent {
toggleDisabled(): any { toggleDisabled(): any {
let testButton = <HTMLInputElement> document.getElementById('testButton'); const testButton = document.getElementById('testButton') as HTMLInputElement;
testButton.disabled = !testButton.disabled; testButton.disabled = !testButton.disabled;
console.warn(testButton.disabled); console.warn(testButton.disabled);
} }

View File

@ -21,11 +21,13 @@ import { ItemDirective } from './item.directive';
ItemDirective ItemDirective
], ],
// #enddocregion declarations // #enddocregion declarations
// #docregion imports
imports: [ imports: [
BrowserModule, BrowserModule,
FormsModule, FormsModule,
HttpClientModule HttpClientModule
], ],
// #enddocregion imports
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -1,21 +1,19 @@
'use strict';
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Built-in Directives', function () { describe('Built-in Directives', () => {
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it('should have title Built-in Directives', function () { it('should have title Built-in Directives', () => {
let title = element.all(by.css('h1')).get(0); const title = element.all(by.css('h1')).get(0);
expect(title.getText()).toEqual('Built-in Directives'); expect(title.getText()).toEqual('Built-in Directives');
}); });
it('should change first Teapot header', async () => { it('should change first Teapot header', async () => {
let firstLabel = element.all(by.css('p')).get(0); const firstLabel = element.all(by.css('p')).get(0);
let firstInput = element.all(by.css('input')).get(0); const firstInput = element.all(by.css('input')).get(0);
expect(firstLabel.getText()).toEqual('Current item name: Teapot'); expect(firstLabel.getText()).toEqual('Current item name: Teapot');
firstInput.sendKeys('abc'); firstInput.sendKeys('abc');
@ -23,49 +21,49 @@ describe('Built-in Directives', function () {
}); });
it('should modify sentence when modified checkbox checked', function () { it('should modify sentence when modified checkbox checked', () => {
let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1); const modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
let modifiedSentence = element.all(by.css('div')).get(1); const modifiedSentence = element.all(by.css('div')).get(1);
modifiedChkbxLabel.click(); modifiedChkbxLabel.click();
expect(modifiedSentence.getText()).toContain('modified'); expect(modifiedSentence.getText()).toContain('modified');
}); });
it('should modify sentence when normal checkbox checked', function () { it('should modify sentence when normal checkbox checked', () => {
let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4); const normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
let normalSentence = element.all(by.css('div')).get(7); const normalSentence = element.all(by.css('div')).get(7);
normalChkbxLabel.click(); normalChkbxLabel.click();
expect(normalSentence.getText()).toContain('normal weight and, extra large'); expect(normalSentence.getText()).toContain('normal weight and, extra large');
}); });
it('should toggle app-item-detail', function () { it('should toggle app-item-detail', () => {
let toggleButton = element.all(by.css('button')).get(3); const toggleButton = element.all(by.css('button')).get(3);
let toggledDiv = element.all(by.css('app-item-detail')).get(0); const toggledDiv = element.all(by.css('app-item-detail')).get(0);
toggleButton.click(); toggleButton.click();
expect(toggledDiv.isDisplayed()).toBe(true); expect(toggledDiv.isDisplayed()).toBe(true);
}); });
it('should hide app-item-detail', function () { it('should hide app-item-detail', () => {
let hiddenMessage = element.all(by.css('p')).get(11); const hiddenMessage = element.all(by.css('p')).get(11);
let hiddenDiv = element.all(by.css('app-item-detail')).get(2); const hiddenDiv = element.all(by.css('app-item-detail')).get(2);
expect(hiddenMessage.getText()).toContain('in the DOM'); expect(hiddenMessage.getText()).toContain('in the DOM');
expect(hiddenDiv.isDisplayed()).toBe(true); expect(hiddenDiv.isDisplayed()).toBe(true);
}); });
it('should have 10 lists each containing the string Teapot', function () { it('should have 10 lists each containing the string Teapot', () => {
let listDiv = element.all(by.cssContainingText('.box', 'Teapot')); const listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
expect(listDiv.count()).toBe(10); expect(listDiv.count()).toBe(10);
}); });
it('should switch case', function () { it('should switch case', () => {
let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3); const tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
let tvDiv = element(by.css('app-lost-item')); const tvDiv = element(by.css('app-lost-item'));
let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4); const fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
let fishbowlDiv = element(by.css('app-unknown-item')); const fishbowlDiv = element(by.css('app-unknown-item'));
tvRadioButton.click(); tvRadioButton.click();
expect(tvDiv.getText()).toContain('Television'); expect(tvDiv.getText()).toContain('Television');

View File

@ -30,6 +30,14 @@ export class AppComponent implements OnInit {
itemsWithTrackByCountReset = 0; itemsWithTrackByCountReset = 0;
itemIdIncrement = 1; itemIdIncrement = 1;
// #docregion setClasses
currentClasses: {};
// #enddocregion setClasses
// #docregion setStyles
currentStyles: {};
// #enddocregion setStyles
ngOnInit() { ngOnInit() {
this.resetItems(); this.resetItems();
this.setCurrentClasses(); this.setCurrentClasses();
@ -41,20 +49,18 @@ export class AppComponent implements OnInit {
this.currentItem.name = name.toUpperCase(); this.currentItem.name = name.toUpperCase();
} }
// #docregion setClasses // #docregion setClasses
currentClasses: {};
setCurrentClasses() { setCurrentClasses() {
// CSS classes: added/removed per current state of component properties // CSS classes: added/removed per current state of component properties
this.currentClasses = { this.currentClasses = {
'saveable': this.canSave, saveable: this.canSave,
'modified': !this.isUnchanged, modified: !this.isUnchanged,
'special': this.isSpecial special: this.isSpecial
}; };
} }
// #enddocregion setClasses // #enddocregion setClasses
// #docregion setStyles // #docregion setStyles
currentStyles: {};
setCurrentStyles() { setCurrentStyles() {
// CSS styles: set per current state of component properties // CSS styles: set per current state of component properties
this.currentStyles = { this.currentStyles = {
@ -70,11 +76,7 @@ export class AppComponent implements OnInit {
} }
giveNullCustomerValue() { giveNullCustomerValue() {
!(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null); this.nullCustomer = 'Kelly';
}
resetNullItem() {
this.nullCustomer = null;
} }
resetItems() { resetItems() {
@ -84,7 +86,7 @@ export class AppComponent implements OnInit {
} }
resetList() { resetList() {
this.resetItems() this.resetItems();
this.itemsWithTrackByCountReset = 0; this.itemsWithTrackByCountReset = 0;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount; this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
} }
@ -107,7 +109,7 @@ export class AppComponent implements OnInit {
trackByItems(index: number, item: Item): number { return item.id; } trackByItems(index: number, item: Item): number { return item.id; }
// #enddocregion trackByItems // #enddocregion trackByItems
trackById(index: number, item: any): number { return item['id']; } trackById(index: number, item: any): number { return item.id; }
} }

View File

@ -1,19 +1,17 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Built Template Functions Example', function () { describe('Built Template Functions Example', () => {
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it('should have title Built-in Template Functions', function () { it('should have title Built-in Template Functions', () => {
let title = element.all(by.css('h1')).get(0); const title = element.all(by.css('h1')).get(0);
expect(title.getText()).toEqual('Built-in Template Functions'); expect(title.getText()).toEqual('Built-in Template Functions');
}); });
it('should display $any( ) in h2', function () { it('should display $any( ) in h2', () => {
let header = element(by.css('h2')); const header = element(by.css('h2'));
expect(header.getText()).toContain('$any( )'); expect(header.getText()).toContain('$any( )');
}); });

View File

@ -0,0 +1,9 @@
/*
* This example project is special in that it is not a cli app. To run tests appropriate for this
* project, the test command is overwritten in `aio/content/examples/observables/example-config.json`.
*
* This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs
* tests for this project.
*
* TODO: Fix our infrastructure/tooling, so that this hack is not necessary.
*/

View File

@ -0,0 +1,12 @@
{
"tests": [
{
"cmd": "yarn",
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
},
{
"cmd": "yarn",
"args": ["jasmine", "out-tsc/**/*.spec.js"]
}
]
}

View File

@ -0,0 +1,26 @@
import { docRegionChain, docRegionObservable, docRegionUnsubscribe } from './observables';
describe('observables', () => {
it('should print 2', (doneFn: DoneFn) => {
const consoleLogSpy = spyOn(console, 'log');
const observable = docRegionObservable(console);
observable.subscribe(() => {
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
expect(consoleLogSpy).toHaveBeenCalledWith(2);
doneFn();
});
});
it('should close the subscription', () => {
const subscription = docRegionUnsubscribe();
expect(subscription.closed).toBeTruthy();
});
it('should chain an observable', (doneFn: DoneFn) => {
const observable = docRegionChain();
observable.subscribe(value => {
expect(value).toBe(4);
doneFn();
});
});
});

View File

@ -1,40 +1,72 @@
import { map } from 'rxjs/operators'; // #docplaster
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
// #docregion observable export function docRegionObservable(console: Console) {
// #docregion observable
// declare a publishing operation // declare a publishing operation
const observable = new Observable<number>(observer => { const observable = new Observable<number>(observer => {
// Subscriber fn... // Subscriber fn...
}); // #enddocregion observable
// The below code is used for unit testing only
observer.next(2);
// #docregion observable
});
// initiate execution // initiate execution
observable.subscribe(() => { observable.subscribe(value => {
// observer handles notifications // observer handles notifications
}); // #enddocregion observable
// The below code is used for unit testing only
console.log(value);
// #docregion observable
});
// #enddocregion observable // #enddocregion observable
return observable;
}
// #docregion unsubscribe export function docRegionUnsubscribe() {
const observable = new Observable<number>(() => {
// Subscriber fn...
});
// #docregion unsubscribe
const subscription = observable.subscribe(() => { const subscription = observable.subscribe(() => {
// observer handles notifications // observer handles notifications
}); });
subscription.unsubscribe(); subscription.unsubscribe();
// #enddocregion unsubscribe // #enddocregion unsubscribe
return subscription;
}
// #docregion error export function docRegionError() {
const observable = new Observable<number>(() => {
// Subscriber fn...
});
observable.subscribe(() => { // #docregion error
throw Error('my error'); observable.subscribe(() => {
}); throw new Error('my error');
});
// #enddocregion error
}
// #enddocregion error export function docRegionChain() {
let observable = new Observable<number>(observer => {
// Subscriber fn...
observer.next(2);
});
// #docregion chain observable =
// #docregion chain
observable.pipe(map(v => 2 * v)); observable.pipe(map(v => 2 * v));
// #enddocregion chain // #enddocregion chain
return observable;
}

View File

@ -0,0 +1,23 @@
import { docRegionError, docRegionPromise } from './promises';
describe('promises', () => {
it('should print 2', (doneFn: DoneFn) => {
const consoleLogSpy = spyOn(console, 'log');
const pr = docRegionPromise(console, 2);
pr.then((value) => {
expect(consoleLogSpy).toHaveBeenCalledTimes(1);
expect(consoleLogSpy).toHaveBeenCalledWith(2);
expect(value).toBe(4);
doneFn();
});
});
it('should throw an error', (doneFn: DoneFn) => {
const promise = docRegionError();
promise
.then(() => {
throw new Error('Promise should be rejected.');
},
() => doneFn());
});
});

View File

@ -1,25 +1,44 @@
// #docregion promise // #docplaster
// initiate execution
const promise = new Promise<number>((resolve, reject) => {
// Executer fn...
});
promise.then(value => { export function docRegionPromise(console: Console, inputValue: number) {
// handle result here // #docregion promise
}); // initiate execution
let promise = new Promise<number>((resolve, reject) => {
// Executer fn...
// #enddocregion promise
// The below is used in the unit tests.
resolve(inputValue);
// #docregion promise
});
// #enddocregion promise
promise =
// #docregion promise
promise.then(value => {
// handle result here
// #enddocregion promise
// The below is used in the unit tests.
console.log(value);
return value;
// #docregion promise
});
// #enddocregion promise
promise =
// #docregion chain
promise.then(v => 2 * v);
// #enddocregion chain
// #enddocregion promise return promise;
}
// #docregion chain export function docRegionError() {
let promise = Promise.resolve();
promise =
// #docregion error
promise.then(v => 2 * v); promise.then(() => {
throw new Error('my error');
});
// #enddocregion chain // #enddocregion error
return promise;
// #docregion error }
promise.then(() => {
throw Error('my error');
});
// #enddocregion error

View File

@ -1,87 +1,85 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Component Communication Cookbook Tests', function () { describe('Component Communication Cookbook Tests', () => {
// Note: '?e2e' which app can read to know it is running in protractor // Note: '?e2e' which app can read to know it is running in protractor
// e.g. `if (!/e2e/.test(location.search)) { ...` // e.g. `if (!/e2e/.test(location.search)) { ...`
beforeAll(function () { beforeAll(() => {
browser.get('?e2e'); browser.get('?e2e');
}); });
describe('Parent-to-child communication', function() { describe('Parent-to-child communication', () => {
// #docregion parent-to-child // #docregion parent-to-child
// ... // ...
let _heroNames = ['Dr IQ', 'Magneta', 'Bombasto']; const heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
let _masterName = 'Master'; const masterName = 'Master';
it('should pass properties to children properly', function () { it('should pass properties to children properly', () => {
let parent = element.all(by.tagName('app-hero-parent')).get(0); const parent = element.all(by.tagName('app-hero-parent')).get(0);
let heroes = parent.all(by.tagName('app-hero-child')); const heroes = parent.all(by.tagName('app-hero-child'));
for (let i = 0; i < _heroNames.length; i++) { for (let i = 0; i < heroNames.length; i++) {
let childTitle = heroes.get(i).element(by.tagName('h3')).getText(); const childTitle = heroes.get(i).element(by.tagName('h3')).getText();
let childDetail = heroes.get(i).element(by.tagName('p')).getText(); const childDetail = heroes.get(i).element(by.tagName('p')).getText();
expect(childTitle).toEqual(_heroNames[i] + ' says:'); expect(childTitle).toEqual(heroNames[i] + ' says:');
expect(childDetail).toContain(_masterName); expect(childDetail).toContain(masterName);
} }
}); });
// ... // ...
// #enddocregion parent-to-child // #enddocregion parent-to-child
}); });
describe('Parent-to-child communication with setter', function() { describe('Parent-to-child communication with setter', () => {
// #docregion parent-to-child-setter // #docregion parent-to-child-setter
// ... // ...
it('should display trimmed, non-empty names', function () { it('should display trimmed, non-empty names', () => {
let _nonEmptyNameIndex = 0; const nonEmptyNameIndex = 0;
let _nonEmptyName = '"Dr IQ"'; const nonEmptyName = '"Dr IQ"';
let parent = element.all(by.tagName('app-name-parent')).get(0); const parent = element.all(by.tagName('app-name-parent')).get(0);
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex); const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
let displayName = hero.element(by.tagName('h3')).getText(); const displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_nonEmptyName); expect(displayName).toEqual(nonEmptyName);
}); });
it('should replace empty name with default name', function () { it('should replace empty name with default name', () => {
let _emptyNameIndex = 1; const emptyNameIndex = 1;
let _defaultName = '"<no name set>"'; const defaultName = '"<no name set>"';
let parent = element.all(by.tagName('app-name-parent')).get(0); const parent = element.all(by.tagName('app-name-parent')).get(0);
let hero = parent.all(by.tagName('app-name-child')).get(_emptyNameIndex); const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
let displayName = hero.element(by.tagName('h3')).getText(); const displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_defaultName); expect(displayName).toEqual(defaultName);
}); });
// ... // ...
// #enddocregion parent-to-child-setter // #enddocregion parent-to-child-setter
}); });
describe('Parent-to-child communication with ngOnChanges', function() { describe('Parent-to-child communication with ngOnChanges', () => {
// #docregion parent-to-child-onchanges // #docregion parent-to-child-onchanges
// ... // ...
// Test must all execute in this exact order // Test must all execute in this exact order
it('should set expected initial values', function () { it('should set expected initial values', () => {
let actual = getActual(); const actual = getActual();
let initialLabel = 'Version 1.23'; const initialLabel = 'Version 1.23';
let initialLog = 'Initial value of major set to 1, Initial value of minor set to 23'; const initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
expect(actual.label).toBe(initialLabel); expect(actual.label).toBe(initialLabel);
expect(actual.count).toBe(1); expect(actual.count).toBe(1);
expect(actual.logs.get(0).getText()).toBe(initialLog); expect(actual.logs.get(0).getText()).toBe(initialLog);
}); });
it('should set expected values after clicking \'Minor\' twice', function () { it('should set expected values after clicking \'Minor\' twice', () => {
let repoTag = element(by.tagName('app-version-parent')); const repoTag = element(by.tagName('app-version-parent'));
let newMinorButton = repoTag.all(by.tagName('button')).get(0); const newMinorButton = repoTag.all(by.tagName('button')).get(0);
newMinorButton.click().then(function() { newMinorButton.click().then(() => {
newMinorButton.click().then(function() { newMinorButton.click().then(() => {
let actual = getActual(); const actual = getActual();
let labelAfter2Minor = 'Version 1.25'; const labelAfter2Minor = 'Version 1.25';
let logAfter2Minor = 'minor changed from 24 to 25'; const logAfter2Minor = 'minor changed from 24 to 25';
expect(actual.label).toBe(labelAfter2Minor); expect(actual.label).toBe(labelAfter2Minor);
expect(actual.count).toBe(3); expect(actual.count).toBe(3);
@ -90,15 +88,15 @@ describe('Component Communication Cookbook Tests', function () {
}); });
}); });
it('should set expected values after clicking \'Major\' once', function () { it('should set expected values after clicking \'Major\' once', () => {
let repoTag = element(by.tagName('app-version-parent')); const repoTag = element(by.tagName('app-version-parent'));
let newMajorButton = repoTag.all(by.tagName('button')).get(1); const newMajorButton = repoTag.all(by.tagName('button')).get(1);
newMajorButton.click().then(function() { newMajorButton.click().then(() => {
let actual = getActual(); const actual = getActual();
let labelAfterMajor = 'Version 2.0'; const labelAfterMajor = 'Version 2.0';
let logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0'; const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
expect(actual.label).toBe(labelAfterMajor); expect(actual.label).toBe(labelAfterMajor);
expect(actual.count).toBe(4); expect(actual.count).toBe(4);
@ -107,14 +105,14 @@ describe('Component Communication Cookbook Tests', function () {
}); });
function getActual() { function getActual() {
let versionTag = element(by.tagName('app-version-child')); const versionTag = element(by.tagName('app-version-child'));
let label = versionTag.element(by.tagName('h3')).getText(); const label = versionTag.element(by.tagName('h3')).getText();
let ul = versionTag.element((by.tagName('ul'))); const ul = versionTag.element((by.tagName('ul')));
let logs = ul.all(by.tagName('li')); const logs = ul.all(by.tagName('li'));
return { return {
label: label, label,
logs: logs, logs,
count: logs.count() count: logs.count()
}; };
} }
@ -123,30 +121,30 @@ describe('Component Communication Cookbook Tests', function () {
}); });
describe('Child-to-parent communication', function() { describe('Child-to-parent communication', () => {
// #docregion child-to-parent // #docregion child-to-parent
// ... // ...
it('should not emit the event initially', function () { it('should not emit the event initially', () => {
let voteLabel = element(by.tagName('app-vote-taker')) const voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText(); .element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 0, Disagree: 0'); expect(voteLabel).toBe('Agree: 0, Disagree: 0');
}); });
it('should process Agree vote', function () { it('should process Agree vote', () => {
let agreeButton1 = element.all(by.tagName('app-voter')).get(0) const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
.all(by.tagName('button')).get(0); .all(by.tagName('button')).get(0);
agreeButton1.click().then(function() { agreeButton1.click().then(() => {
let voteLabel = element(by.tagName('app-vote-taker')) const voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText(); .element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 1, Disagree: 0'); expect(voteLabel).toBe('Agree: 1, Disagree: 0');
}); });
}); });
it('should process Disagree vote', function () { it('should process Disagree vote', () => {
let agreeButton1 = element.all(by.tagName('app-voter')).get(1) const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
.all(by.tagName('button')).get(1); .all(by.tagName('button')).get(1);
agreeButton1.click().then(function() { agreeButton1.click().then(() => {
let voteLabel = element(by.tagName('app-vote-taker')) const voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText(); .element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 1, Disagree: 1'); expect(voteLabel).toBe('Agree: 1, Disagree: 1');
}); });
@ -157,31 +155,31 @@ describe('Component Communication Cookbook Tests', function () {
// Can't run timer tests in protractor because // Can't run timer tests in protractor because
// interaction w/ zones causes all tests to freeze & timeout. // interaction w/ zones causes all tests to freeze & timeout.
xdescribe('Parent calls child via local var', function() { xdescribe('Parent calls child via local var', () => {
countDownTimerTests('countdown-parent-lv'); countDownTimerTests('countdown-parent-lv');
}); });
xdescribe('Parent calls ViewChild', function() { xdescribe('Parent calls ViewChild', () => {
countDownTimerTests('countdown-parent-vc'); countDownTimerTests('countdown-parent-vc');
}); });
function countDownTimerTests(parentTag: string) { function countDownTimerTests(parentTag: string) {
// #docregion countdown-timer-tests // #docregion countdown-timer-tests
// ... // ...
it('timer and parent seconds should match', function () { it('timer and parent seconds should match', () => {
let parent = element(by.tagName(parentTag)); const parent = element(by.tagName(parentTag));
let message = parent.element(by.tagName('app-countdown-timer')).getText(); const message = parent.element(by.tagName('app-countdown-timer')).getText();
browser.sleep(10); // give `seconds` a chance to catchup with `message` browser.sleep(10); // give `seconds` a chance to catchup with `message`
let seconds = parent.element(by.className('seconds')).getText(); const seconds = parent.element(by.className('seconds')).getText();
expect(message).toContain(seconds); expect(message).toContain(seconds);
}); });
it('should stop the countdown', function () { it('should stop the countdown', () => {
let parent = element(by.tagName(parentTag)); const parent = element(by.tagName(parentTag));
let stopButton = parent.all(by.tagName('button')).get(1); const stopButton = parent.all(by.tagName('button')).get(1);
stopButton.click().then(function() { stopButton.click().then(() => {
let message = parent.element(by.tagName('app-countdown-timer')).getText(); const message = parent.element(by.tagName('app-countdown-timer')).getText();
expect(message).toContain('Holding'); expect(message).toContain('Holding');
}); });
}); });
@ -190,39 +188,39 @@ describe('Component Communication Cookbook Tests', function () {
} }
describe('Parent and children communicate via a service', function() { describe('Parent and children communicate via a service', () => {
// #docregion bidirectional-service // #docregion bidirectional-service
// ... // ...
it('should announce a mission', function () { it('should announce a mission', () => {
let missionControl = element(by.tagName('app-mission-control')); const missionControl = element(by.tagName('app-mission-control'));
let announceButton = missionControl.all(by.tagName('button')).get(0); const announceButton = missionControl.all(by.tagName('button')).get(0);
announceButton.click().then(function () { announceButton.click().then(() => {
let history = missionControl.all(by.tagName('li')); const history = missionControl.all(by.tagName('li'));
expect(history.count()).toBe(1); expect(history.count()).toBe(1);
expect(history.get(0).getText()).toMatch(/Mission.* announced/); expect(history.get(0).getText()).toMatch(/Mission.* announced/);
}); });
}); });
it('should confirm the mission by Lovell', function () { it('should confirm the mission by Lovell', () => {
testConfirmMission(1, 2, 'Lovell'); testConfirmMission(1, 2, 'Lovell');
}); });
it('should confirm the mission by Haise', function () { it('should confirm the mission by Haise', () => {
testConfirmMission(3, 3, 'Haise'); testConfirmMission(3, 3, 'Haise');
}); });
it('should confirm the mission by Swigert', function () { it('should confirm the mission by Swigert', () => {
testConfirmMission(2, 4, 'Swigert'); testConfirmMission(2, 4, 'Swigert');
}); });
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) { function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
let _confirmedLog = ' confirmed the mission'; const confirmedLog = ' confirmed the mission';
let missionControl = element(by.tagName('app-mission-control')); const missionControl = element(by.tagName('app-mission-control'));
let confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex); const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
confirmButton.click().then(function () { confirmButton.click().then(() => {
let history = missionControl.all(by.tagName('li')); const history = missionControl.all(by.tagName('li'));
expect(history.count()).toBe(expectedLogCount); expect(history.count()).toBe(expectedLogCount);
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + _confirmedLog); expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog);
}); });
} }
// ... // ...

View File

@ -1,5 +1,5 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { AstronautComponent } from './astronaut.component'; import { AstronautComponent } from './astronaut.component';
@ -15,7 +15,7 @@ import { VersionParentComponent } from './version-parent.component';
import { VoterComponent } from './voter.component'; import { VoterComponent } from './voter.component';
import { VoteTakerComponent } from './votetaker.component'; import { VoteTakerComponent } from './votetaker.component';
let directives: any[] = [ const directives: any[] = [
AppComponent, AppComponent,
AstronautComponent, AstronautComponent,
CountdownTimerComponent, CountdownTimerComponent,
@ -30,7 +30,7 @@ let directives: any[] = [
VoteTakerComponent VoteTakerComponent
]; ];
let schemas: any[] = []; const schemas: any[] = [];
// Include Countdown examples // Include Countdown examples
// unless in e2e tests which they break. // unless in e2e tests which they break.
@ -49,6 +49,6 @@ if (!/e2e/.test(location.search)) {
], ],
declarations: directives, declarations: directives,
bootstrap: [ AppComponent ], bootstrap: [ AppComponent ],
schemas: schemas schemas
}) })
export class AppModule { } export class AppModule { }

View File

@ -2,7 +2,7 @@
import { Component, Input, OnDestroy } from '@angular/core'; import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service'; import { MissionService } from './mission.service';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'app-astronaut', selector: 'app-astronaut',

View File

@ -2,8 +2,8 @@
// #docregion vc // #docregion vc
import { AfterViewInit, ViewChild } from '@angular/core'; import { AfterViewInit, ViewChild } from '@angular/core';
// #docregion lv // #docregion lv
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component'; import { CountdownTimerComponent } from './countdown-timer.component';
// #enddocregion lv // #enddocregion lv
// #enddocregion vc // #enddocregion vc

View File

@ -12,6 +12,6 @@ import { Hero } from './hero';
}) })
export class HeroChildComponent { export class HeroChildComponent {
@Input() hero: Hero; @Input() hero: Hero;
@Input('master') masterName: string; @Input('master') masterName: string; // tslint:disable-line: no-input-rename
} }
// #enddocregion // #enddocregion

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@Injectable() @Injectable()
export class MissionService { export class MissionService {

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { MissionService } from './mission.service'; import { MissionService } from './mission.service';
@Component({ @Component({
selector: 'app-mission-control', selector: 'app-mission-control',
@ -34,7 +34,7 @@ export class MissionControlComponent {
} }
announce() { announce() {
let mission = this.missions[this.nextMission++]; const mission = this.missions[this.nextMission++];
this.missionService.announceMission(mission); this.missionService.announceMission(mission);
this.history.push(`Mission "${mission}" announced`); this.history.push(`Mission "${mission}" announced`);
if (this.nextMission >= this.missions.length) { this.nextMission = 0; } if (this.nextMission >= this.missions.length) { this.nextMission = 0; }

View File

@ -1,3 +1,4 @@
// tslint:disable: variable-name
// #docregion // #docregion
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
@ -6,13 +7,11 @@ import { Component, Input } from '@angular/core';
template: '<h3>"{{name}}"</h3>' template: '<h3>"{{name}}"</h3>'
}) })
export class NameChildComponent { export class NameChildComponent {
private _name = '';
@Input() @Input()
get name(): string { return this._name; }
set name(name: string) { set name(name: string) {
this._name = (name && name.trim()) || '<no name set>'; this._name = (name && name.trim()) || '<no name set>';
} }
private _name = '';
get name(): string { return this._name; }
} }
// #enddocregion // #enddocregion

View File

@ -18,14 +18,14 @@ export class VersionChildComponent implements OnChanges {
changeLog: string[] = []; changeLog: string[] = [];
ngOnChanges(changes: {[propKey: string]: SimpleChange}) { ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
let log: string[] = []; const log: string[] = [];
for (let propName in changes) { for (const propName in changes) {
let changedProp = changes[propName]; const changedProp = changes[propName];
let to = JSON.stringify(changedProp.currentValue); const to = JSON.stringify(changedProp.currentValue);
if (changedProp.isFirstChange()) { if (changedProp.isFirstChange()) {
log.push(`Initial value of ${propName} set to ${to}`); log.push(`Initial value of ${propName} set to ${to}`);
} else { } else {
let from = JSON.stringify(changedProp.previousValue); const from = JSON.stringify(changedProp.previousValue);
log.push(`${propName} changed from ${from} to ${to}`); log.push(`${propName} changed from ${from} to ${to}`);
} }
} }

View File

@ -1,5 +1,5 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-vote-taker', selector: 'app-vote-taker',

View File

@ -1,16 +1,14 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Component Style Tests', function () { describe('Component Style Tests', () => {
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it('scopes component styles to component view', function() { it('scopes component styles to component view', () => {
let componentH1 = element(by.css('app-root > h1')); const componentH1 = element(by.css('app-root > h1'));
let externalH1 = element(by.css('body > h1')); const externalH1 = element(by.css('body > h1'));
// Note: sometimes webdriver returns the fontWeight as "normal", // Note: sometimes webdriver returns the fontWeight as "normal",
// other times as "400", both of which are equal in CSS terms. // other times as "400", both of which are equal in CSS terms.
@ -19,49 +17,49 @@ describe('Component Style Tests', function () {
}); });
it('allows styling :host element', function() { it('allows styling :host element', () => {
let host = element(by.css('app-hero-details')); const host = element(by.css('app-hero-details'));
expect(host.getCssValue('borderWidth')).toEqual('1px'); expect(host.getCssValue('borderWidth')).toEqual('1px');
}); });
it('supports :host() in function form', function() { it('supports :host() in function form', () => {
let host = element(by.css('app-hero-details')); const host = element(by.css('app-hero-details'));
host.element(by.buttonText('Activate')).click(); host.element(by.buttonText('Activate')).click();
expect(host.getCssValue('borderWidth')).toEqual('3px'); expect(host.getCssValue('borderWidth')).toEqual('3px');
}); });
it('allows conditional :host-context() styling', function() { it('allows conditional :host-context() styling', () => {
let h2 = element(by.css('app-hero-details h2')); const h2 = element(by.css('app-hero-details h2'));
expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff
}); });
it('styles both view and content children with /deep/', function() { it('styles both view and content children with /deep/', () => {
let viewH3 = element(by.css('app-hero-team h3')); const viewH3 = element(by.css('app-hero-team h3'));
let contentH3 = element(by.css('app-hero-controls h3')); const contentH3 = element(by.css('app-hero-controls h3'));
expect(viewH3.getCssValue('fontStyle')).toEqual('italic'); expect(viewH3.getCssValue('fontStyle')).toEqual('italic');
expect(contentH3.getCssValue('fontStyle')).toEqual('italic'); expect(contentH3.getCssValue('fontStyle')).toEqual('italic');
}); });
it('includes styles loaded with CSS @import', function() { it('includes styles loaded with CSS @import', () => {
let host = element(by.css('app-hero-details')); const host = element(by.css('app-hero-details'));
expect(host.getCssValue('padding')).toEqual('10px'); expect(host.getCssValue('padding')).toEqual('10px');
}); });
it('processes template inline styles', function() { it('processes template inline styles', () => {
let button = element(by.css('app-hero-controls button')); const button = element(by.css('app-hero-controls button'));
let externalButton = element(by.css('body > button')); const externalButton = element(by.css('body > button'));
expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff
expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)'); expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)');
}); });
it('processes template <link>s', function() { it('processes template <link>s', () => {
let li = element(by.css('app-hero-team li:first-child')); const li = element(by.css('app-hero-team li:first-child'));
let externalLi = element(by.css('body > ul li')); const externalLi = element(by.css('body > ul li'));
expect(li.getCssValue('listStyleType')).toEqual('square'); expect(li.getCssValue('listStyleType')).toEqual('square');
expect(externalLi.getCssValue('listStyleType')).not.toEqual('square'); expect(externalLi.getCssValue('listStyleType')).not.toEqual('square');

View File

@ -1,76 +1,74 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor'; import { browser, element, by } from 'protractor';
describe('Dependency Injection Cookbook', function () { describe('Dependency Injection Cookbook', () => {
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
it('should render Logged in User example', function () { it('should render Logged in User example', () => {
let loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0); const loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
expect(loggedInUser).toBeDefined(); expect(loggedInUser).toBeDefined();
}); });
it('"Bombasto" should be the logged in user', function () { it('"Bombasto" should be the logged in user', () => {
let loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0); const loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
expect(loggedInUser).toBeDefined(); expect(loggedInUser).toBeDefined();
}); });
it('should render sorted heroes', function () { it('should render sorted heroes', () => {
let sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0); const sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
expect(sortedHeroes).toBeDefined(); expect(sortedHeroes).toBeDefined();
}); });
it('Dr Nice should be in sorted heroes', function () { it('Dr Nice should be in sorted heroes', () => {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0); const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
expect(sortedHero).toBeDefined(); expect(sortedHero).toBeDefined();
}); });
it('RubberMan should be in sorted heroes', function () { it('RubberMan should be in sorted heroes', () => {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0); const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
expect(sortedHero).toBeDefined(); expect(sortedHero).toBeDefined();
}); });
it('Magma should be in sorted heroes', function () { it('Magma should be in sorted heroes', () => {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0); const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
expect(sortedHero).toBeDefined(); expect(sortedHero).toBeDefined();
}); });
it('should render Hero of the Month', function () { it('should render Hero of the Month', () => {
let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0); const heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
expect(heroOfTheMonth).toBeDefined(); expect(heroOfTheMonth).toBeDefined();
}); });
it('should render Hero Bios', function () { it('should render Hero Bios', () => {
let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0); const heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
expect(heroBios).toBeDefined(); expect(heroBios).toBeDefined();
}); });
it('should render Magma\'s description in Hero Bios', function () { it('should render Magma\'s description in Hero Bios', () => {
let magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0); const magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
expect(magmaText).toBeDefined(); expect(magmaText).toBeDefined();
}); });
it('should render Magma\'s phone in Hero Bios and Contacts', function () { it('should render Magma\'s phone in Hero Bios and Contacts', () => {
let magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0); const magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
expect(magmaPhone).toBeDefined(); expect(magmaPhone).toBeDefined();
}); });
it('should render Hero-of-the-Month runner-ups', function () { it('should render Hero-of-the-Month runner-ups', () => {
let runnersUp = element(by.id('rups1')).getText(); const runnersUp = element(by.id('rups1')).getText();
expect(runnersUp).toContain('RubberMan, Dr Nice'); expect(runnersUp).toContain('RubberMan, Dr Nice');
}); });
it('should render DateLogger log entry in Hero-of-the-Month', function () { it('should render DateLogger log entry in Hero-of-the-Month', () => {
let logs = element.all(by.id('logs')).get(0).getText(); const logs = element.all(by.id('logs')).get(0).getText();
expect(logs).toContain('INFO: starting up at'); expect(logs).toContain('INFO: starting up at');
}); });
it('should highlight Hero Bios and Contacts container when mouseover', function () { it('should highlight Hero Bios and Contacts container when mouseover', () => {
let target = element(by.css('div[appHighlight="yellow"]')); const target = element(by.css('div[appHighlight="yellow"]'));
let yellow = 'rgba(255, 255, 0, 1)'; const yellow = 'rgba(255, 255, 0, 1)';
expect(target.getCssValue('background-color')).not.toEqual(yellow); expect(target.getCssValue('background-color')).not.toEqual(yellow);
@ -81,25 +79,25 @@ describe('Dependency Injection Cookbook', function () {
browser.wait(() => target.getCssValue('background-color').then(c => c === yellow), 2000); browser.wait(() => target.getCssValue('background-color').then(c => c === yellow), 2000);
}); });
describe('in Parent Finder', function () { describe('in Parent Finder', () => {
let cathy1 = element(by.css('alex cathy')); const cathy1 = element(by.css('alex cathy'));
let craig1 = element(by.css('alex craig')); const craig1 = element(by.css('alex craig'));
let carol1 = element(by.css('alex carol p')); const carol1 = element(by.css('alex carol p'));
let carol2 = element(by.css('barry carol p')); const carol2 = element(by.css('barry carol p'));
it('"Cathy" should find "Alex" via the component class', function () { it('"Cathy" should find "Alex" via the component class', () => {
expect(cathy1.getText()).toContain('Found Alex via the component'); expect(cathy1.getText()).toContain('Found Alex via the component');
}); });
it('"Craig" should not find "Alex" via the base class', function () { it('"Craig" should not find "Alex" via the base class', () => {
expect(craig1.getText()).toContain('Did not find Alex via the base'); expect(craig1.getText()).toContain('Did not find Alex via the base');
}); });
it('"Carol" within "Alex" should have "Alex" parent', function () { it('"Carol" within "Alex" should have "Alex" parent', () => {
expect(carol1.getText()).toContain('Alex'); expect(carol1.getText()).toContain('Alex');
}); });
it('"Carol" within "Barry" should have "Barry" parent', function () { it('"Carol" within "Barry" should have "Barry" parent', () => {
expect(carol2.getText()).toContain('Barry'); expect(carol2.getText()).toContain('Barry');
}); });
}); });

View File

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
const routes: Routes = []; const routes: Routes = [];

View File

@ -2,9 +2,9 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
// #docregion import-services // #docregion import-services
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
import { UserContextService } from './user-context.service'; import { UserContextService } from './user-context.service';
import { UserService } from './user.service'; import { UserService } from './user.service';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',

View File

@ -1,26 +1,26 @@
// #docregion // #docregion
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
// import { AppRoutingModule } from './app-routing.module'; // import { AppRoutingModule } from './app-routing.module';
import { LocationStrategy, import { LocationStrategy,
HashLocationStrategy } from '@angular/common'; HashLocationStrategy } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { HeroData } from './hero-data'; import { HeroData } from './hero-data';
import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { HeroBioComponent } from './hero-bio.component'; import { HeroBioComponent } from './hero-bio.component';
import { HeroBiosComponent, import { HeroBiosComponent,
HeroBiosAndContactsComponent } from './hero-bios.component'; HeroBiosAndContactsComponent } from './hero-bios.component';
import { HeroOfTheMonthComponent } from './hero-of-the-month.component'; import { HeroOfTheMonthComponent } from './hero-of-the-month.component';
import { HeroContactComponent } from './hero-contact.component'; import { HeroContactComponent } from './hero-contact.component';
import { HeroesBaseComponent, import { HeroesBaseComponent,
SortedHeroesComponent } from './sorted-heroes.component'; SortedHeroesComponent } from './sorted-heroes.component';
import { HighlightDirective } from './highlight.directive'; import { HighlightDirective } from './highlight.directive';
import { ParentFinderComponent, import { ParentFinderComponent,
AlexComponent, AlexComponent,
AliceComponent, AliceComponent,
@ -30,8 +30,8 @@ import { ParentFinderComponent,
CathyComponent, CathyComponent,
BarryComponent, BarryComponent,
BethComponent, BethComponent,
BobComponent } from './parent-finder.component'; BobComponent } from './parent-finder.component';
import { StorageComponent } from './storage.component'; import { StorageComponent } from './storage.component';
const declarations = [ const declarations = [
AppComponent, AppComponent,
@ -42,11 +42,11 @@ const declarations = [
ParentFinderComponent, ParentFinderComponent,
]; ];
const a_components = [AliceComponent, AlexComponent ]; const componentListA = [ AliceComponent, AlexComponent ];
const b_components = [ BarryComponent, BethComponent, BobComponent ]; const componentListB = [ BarryComponent, BethComponent, BobComponent ];
const c_components = [ const componentListC = [
CarolComponent, ChrisComponent, CraigComponent, CarolComponent, ChrisComponent, CraigComponent,
CathyComponent CathyComponent
]; ];
@ -61,9 +61,9 @@ const c_components = [
], ],
declarations: [ declarations: [
declarations, declarations,
a_components, componentListA,
b_components, componentListB,
c_components, componentListC,
StorageComponent, StorageComponent,
], ],
bootstrap: [ AppComponent ], bootstrap: [ AppComponent ],

View File

@ -1,6 +1,6 @@
/* tslint:disable:one-line*/ /* tslint:disable:one-line*/
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { HeroCacheService } from './hero-cache.service'; import { HeroCacheService } from './hero-cache.service';
// #docregion component // #docregion component
@Component({ @Component({

View File

@ -1,9 +1,9 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
//////// HeroBiosComponent //// //////// HeroBiosComponent ////
// #docregion simple // #docregion simple

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
// #docregion service // #docregion service

View File

@ -3,7 +3,7 @@
import { Component, Host, Optional } from '@angular/core'; import { Component, Host, Optional } from '@angular/core';
import { HeroCacheService } from './hero-cache.service'; import { HeroCacheService } from './hero-cache.service';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
// #docregion component // #docregion component
@Component({ @Component({

View File

@ -3,7 +3,7 @@ import { Hero } from './hero';
export class HeroData { export class HeroData {
createDb() { createDb() {
let heroes = [ const heroes = [
new Hero(1, 'Windstorm'), new Hero(1, 'Windstorm'),
new Hero(2, 'Bombasto'), new Hero(2, 'Bombasto'),
new Hero(3, 'Magneta'), new Hero(3, 'Magneta'),

View File

@ -1,8 +1,8 @@
// Illustrative (not used), mini-version of the actual HeroOfTheMonthComponent // Illustrative (not used), mini-version of the actual HeroOfTheMonthComponent
// Injecting with the MinimalLogger "interface-class" // Injecting with the MinimalLogger "interface-class"
import { Component, NgModule } from '@angular/core'; import { Component, NgModule } from '@angular/core';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
import { MinimalLogger } from './minimal-logger.service'; import { MinimalLogger } from './minimal-logger.service';
// #docregion // #docregion
@Component({ @Component({

View File

@ -10,12 +10,12 @@ export const TITLE = new InjectionToken<string>('title');
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';
import { DateLoggerService } from './date-logger.service'; import { DateLoggerService } from './date-logger.service';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
import { MinimalLogger } from './minimal-logger.service'; import { MinimalLogger } from './minimal-logger.service';
import { RUNNERS_UP, import { RUNNERS_UP,
runnersUpFactory } from './runners-up'; runnersUpFactory } from './runners-up';
// #enddocregion hero-of-the-month // #enddocregion hero-of-the-month
// #docregion some-hero // #docregion some-hero

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'

View File

@ -1,5 +1,4 @@
/* tslint:disable:no-unused-variable component-selector-name one-line check-open-brace */ // tslint:disable: component-selector space-before-function-paren
/* tslint:disable:*/
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, forwardRef, Optional, SkipSelf } from '@angular/core'; import { Component, forwardRef, Optional, SkipSelf } from '@angular/core';
@ -20,8 +19,7 @@ const DifferentParent = Parent;
// The `parentType` defaults to `Parent` when omitting the second parameter. // The `parentType` defaults to `Parent` when omitting the second parameter.
// #docregion provide-the-parent // #docregion provide-the-parent
export function provideParent export function provideParent
// #enddocregion provide-parent, provide-the-parent // #enddocregion provide-the-parent
// #docregion provide-parent
(component: any, parentType?: any) { (component: any, parentType?: any) {
return { provide: parentType || Parent, useExisting: forwardRef(() => component) }; return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
} }

View File

@ -2,7 +2,7 @@
// #docregion // #docregion
import { InjectionToken } from '@angular/core'; import { InjectionToken } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
// #docregion runners-up // #docregion runners-up
@ -22,5 +22,5 @@ export function runnersUpFactory(take: number) {
.join(', '); .join(', ');
// #docregion factory-synopsis // #docregion factory-synopsis
}; };
}; }
// #enddocregion factory-synopsis // #enddocregion factory-synopsis

View File

@ -2,8 +2,8 @@
// #docregion // #docregion
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
/////// HeroesBaseComponent ///// /////// HeroesBaseComponent /////
// #docregion heroes-base, injection // #docregion heroes-base, injection

View File

@ -1,9 +1,9 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
import { UserService } from './user.service'; import { UserService } from './user.service';
// #docregion injectables, injectable // #docregion injectables, injectable
@Injectable({ @Injectable({
@ -24,7 +24,7 @@ export class UserContextService {
// #enddocregion ctor, injectables // #enddocregion ctor, injectables
loadUser(userId: number) { loadUser(userId: number) {
let user = this.userService.getUserById(userId); const user = this.userService.getUserById(userId);
this.name = user.name; this.name = user.name;
this.role = user.role; this.role = user.role;

View File

@ -1,202 +1,196 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by, ElementFinder } from 'protractor'; import { browser, element, by, ElementFinder } from 'protractor';
describe('Dependency Injection Tests', function () { describe('Dependency Injection Tests', () => {
let expectedMsg: string; let expectedMsg: string;
let expectedMsgRx: RegExp; let expectedMsgRx: RegExp;
beforeAll(function () { beforeAll(() => {
browser.get(''); browser.get('');
}); });
describe('Cars:', function() { describe('Cars:', () => {
it('DI car displays as expected', function () { it('DI car displays as expected', () => {
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.'; expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#di')).getText()).toEqual(expectedMsg); expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
}); });
it('No DI car displays as expected', function () { it('No DI car displays as expected', () => {
expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.'; expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg); expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
}); });
it('Injector car displays as expected', function () { it('Injector car displays as expected', () => {
expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.'; expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#injector')).getText()).toEqual(expectedMsg); expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
}); });
it('Factory car displays as expected', function () { it('Factory car displays as expected', () => {
expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.'; expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#factory')).getText()).toEqual(expectedMsg); expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
}); });
it('Simple car displays as expected', function () { it('Simple car displays as expected', () => {
expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.'; expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#simple')).getText()).toEqual(expectedMsg); expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
}); });
it('Super car displays as expected', function () { it('Super car displays as expected', () => {
expectedMsg = 'Super car with 12 cylinders and Flintstone tires.'; expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
expect(element(by.css('#super')).getText()).toEqual(expectedMsg); expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
}); });
it('Test car displays as expected', function () { it('Test car displays as expected', () => {
expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.'; expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
expect(element(by.css('#test')).getText()).toEqual(expectedMsg); expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
}); });
}); });
describe('Other Injections:', function() { describe('Other Injections:', () => {
it('DI car displays as expected', function () { it('DI car displays as expected', () => {
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.'; expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#car')).getText()).toEqual(expectedMsg); expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
}); });
it('Hero displays as expected', function () { it('Hero displays as expected', () => {
expectedMsg = 'Dr Nice'; expectedMsg = 'Dr Nice';
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg); expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
}); });
it('Optional injection displays as expected', function () { it('Optional injection displays as expected', () => {
expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!'; expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg); expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
}); });
}); });
describe('Tests:', function() { describe('Tests:', () => {
it('Tests display as expected', function () { it('Tests display as expected', () => {
expectedMsgRx = /Tests passed/; expectedMsgRx = /Tests passed/;
expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx); expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx);
}); });
}); });
describe('Provider variations:', function() { describe('Provider variations:', () => {
it('P1 (class) displays as expected', function () { it('P1 (class) displays as expected', () => {
expectedMsg = 'Hello from logger provided with Logger class'; expectedMsg = 'Hello from logger provided with Logger class';
expect(element(by.css('#p1')).getText()).toEqual(expectedMsg); expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
}); });
it('P3 (provide) displays as expected', function () { it('P3 (provide) displays as expected', () => {
expectedMsg = 'Hello from logger provided with useClass:Logger'; expectedMsg = 'Hello from logger provided with useClass:Logger';
expect(element(by.css('#p3')).getText()).toEqual(expectedMsg); expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
}); });
it('P4 (useClass:BetterLogger) displays as expected', function () { it('P4 (useClass:BetterLogger) displays as expected', () => {
expectedMsg = 'Hello from logger provided with useClass:BetterLogger'; expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
expect(element(by.css('#p4')).getText()).toEqual(expectedMsg); expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
}); });
it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', function () { it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', () => {
expectedMsg = 'Message to Bob: Hello from EvenBetterlogger'; expectedMsg = 'Message to Bob: Hello from EvenBetterlogger';
expect(element(by.css('#p5')).getText()).toEqual(expectedMsg); expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
}); });
it('P6a (no alias) displays as expected', function () { it('P6a (no alias) displays as expected', () => {
expectedMsg = 'Hello OldLogger (but we want NewLogger)'; expectedMsg = 'Hello OldLogger (but we want NewLogger)';
expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg); expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
}); });
it('P6b (alias) displays as expected', function () { it('P6b (alias) displays as expected', () => {
expectedMsg = 'Hello from NewLogger (via aliased OldLogger)'; expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg); expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
}); });
it('P7 (useValue) displays as expected', function () { it('P7 (useValue) displays as expected', () => {
expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"'; expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
expect(element(by.css('#p7')).getText()).toEqual(expectedMsg); expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
}); });
it('P8 (useFactory) displays as expected', function () { it('P8 (useFactory) displays as expected', () => {
expectedMsg = 'Hero service injected successfully via heroServiceProvider'; expectedMsg = 'Hero service injected successfully via heroServiceProvider';
expect(element(by.css('#p8')).getText()).toEqual(expectedMsg); expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
}); });
it('P9 (InjectionToken) displays as expected', function () { it('P9 (InjectionToken) displays as expected', () => {
expectedMsg = 'APP_CONFIG Application title is Dependency Injection'; expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
expect(element(by.css('#p9')).getText()).toEqual(expectedMsg); expect(element(by.css('#p9')).getText()).toEqual(expectedMsg);
}); });
it('P10 (optional dependency) displays as expected', function () { it('P10 (optional dependency) displays as expected', () => {
expectedMsg = 'Optional logger was not available'; expectedMsg = 'Optional logger was not available';
expect(element(by.css('#p10')).getText()).toEqual(expectedMsg); expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
}); });
}); });
describe('User/Heroes:', function() { describe('User/Heroes:', () => {
it('User is Bob - unauthorized', function () { it('User is Bob - unauthorized', () => {
expectedMsgRx = /Bob, is not authorized/; expectedMsgRx = /Bob, is not authorized/;
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx); expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
}); });
it('should have button', function () { it('should have button', () => {
expect(element.all(by.cssContainingText('button', 'Next User')) expect(element.all(by.cssContainingText('button', 'Next User'))
.get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed'); .get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed');
}); });
it('unauthorized user should have multiple unauthorized heroes', function () { it('unauthorized user should have multiple unauthorized heroes', () => {
let heroes = element.all(by.css('#unauthorized app-hero-list div')); const heroes = element.all(by.css('#unauthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0); expect(heroes.count()).toBeGreaterThan(0);
}); });
it('unauthorized user should have no secret heroes', function () { it('unauthorized user should have no secret heroes', () => {
let heroes = element.all(by.css('#unauthorized app-hero-list div')); const heroes = element.all(by.css('#unauthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0); expect(heroes.count()).toBeGreaterThan(0);
let filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => { const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
return elem.getText().then((text: string) => { return elem.getText().then((text: string) => /secret/.test(text));
return /secret/.test(text);
});
}); });
expect(filteredHeroes.count()).toEqual(0); expect(filteredHeroes.count()).toEqual(0);
}); });
it('unauthorized user should have no authorized heroes listed', function () { it('unauthorized user should have no authorized heroes listed', () => {
expect(element.all(by.css('#authorized app-hero-list div')).count()).toEqual(0); expect(element.all(by.css('#authorized app-hero-list div')).count()).toEqual(0);
}); });
describe('after button click', function() { describe('after button click', () => {
beforeAll(function (done: any) { beforeAll((done: any) => {
let buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0); const buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
buttonEle.click().then(done, done); buttonEle.click().then(done, done);
}); });
it('User is Alice - authorized', function () { it('User is Alice - authorized', () => {
expectedMsgRx = /Alice, is authorized/; expectedMsgRx = /Alice, is authorized/;
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx); expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
}); });
it('authorized user should have multiple authorized heroes ', function () { it('authorized user should have multiple authorized heroes ', () => {
let heroes = element.all(by.css('#authorized app-hero-list div')); const heroes = element.all(by.css('#authorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0); expect(heroes.count()).toBeGreaterThan(0);
}); });
it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', function () { it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', () => {
let heroes = element.all(by.css('#tspAuthorized app-hero-list div')); const heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0); expect(heroes.count()).toBeGreaterThan(0);
}); });
it('authorized user should have secret heroes', function () { it('authorized user should have secret heroes', () => {
let heroes = element.all(by.css('#authorized app-hero-list div')); const heroes = element.all(by.css('#authorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0); expect(heroes.count()).toBeGreaterThan(0);
let filteredHeroes = heroes.filter(function(elem: ElementFinder, index: number) { const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
return elem.getText().then(function(text: string) { return elem.getText().then((text: string) => /secret/.test(text));
return /secret/.test(text);
});
}); });
expect(filteredHeroes.count()).toBeGreaterThan(0); expect(filteredHeroes.count()).toBeGreaterThan(0);
}); });
it('authorized user should have no unauthorized heroes listed', function () { it('authorized user should have no unauthorized heroes listed', () => {
expect(element.all(by.css('#unauthorized app-hero-list div')).count()).toEqual(0); expect(element.all(by.css('#unauthorized app-hero-list div')).count()).toEqual(0);
}); });
}); });

View File

@ -2,7 +2,7 @@
// #docregion imports // #docregion imports
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';
import { APP_CONFIG, AppConfig } from './app.config'; import { APP_CONFIG, AppConfig } from './app.config';
// #enddocregion imports // #enddocregion imports
@Component({ @Component({

View File

@ -1,8 +1,8 @@
// #docplaster // #docplaster
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { APP_CONFIG, HERO_DI_CONFIG } from './app.config'; import { APP_CONFIG, HERO_DI_CONFIG } from './app.config';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { CarComponent } from './car/car.component'; import { CarComponent } from './car/car.component';
import { HeroesComponent } from './heroes/heroes.component'; import { HeroesComponent } from './heroes/heroes.component';

View File

@ -7,7 +7,7 @@ import { Car, Engine, Tires } from './car';
export function simpleCar() { export function simpleCar() {
// #docregion car-ctor-instantiation // #docregion car-ctor-instantiation
// Simple car with 4 cylinders and Flintstone tires. // Simple car with 4 cylinders and Flintstone tires.
let car = new Car(new Engine(), new Tires()); const car = new Car(new Engine(), new Tires());
// #enddocregion car-ctor-instantiation // #enddocregion car-ctor-instantiation
car.description = 'Simple'; car.description = 'Simple';
return car; return car;
@ -16,30 +16,31 @@ export function simpleCar() {
///////// example 2 //////////// ///////// example 2 ////////////
// #docregion car-ctor-instantiation-with-param // #docregion car-ctor-instantiation-with-param
class Engine2 { class Engine2 {
constructor(public cylinders: number) { } constructor(public cylinders: number) { }
} }
// #enddocregion car-ctor-instantiation-with-param // #enddocregion car-ctor-instantiation-with-param
export function superCar() { export function superCar() {
// #docregion car-ctor-instantiation-with-param // #docregion car-ctor-instantiation-with-param
// Super car with 12 cylinders and Flintstone tires. // Super car with 12 cylinders and Flintstone tires.
let bigCylinders = 12; const bigCylinders = 12;
let car = new Car(new Engine2(bigCylinders), new Tires()); const car = new Car(new Engine2(bigCylinders), new Tires());
// #enddocregion car-ctor-instantiation-with-param // #enddocregion car-ctor-instantiation-with-param
car.description = 'Super'; car.description = 'Super';
return car; return car;
} }
/////////// example 3 ////////// /////////// example 3 //////////
// #docregion car-ctor-instantiation-with-mocks // #docregion car-ctor-instantiation-with-mocks
class MockEngine extends Engine { cylinders = 8; } class MockEngine extends Engine { cylinders = 8; }
class MockTires extends Tires { make = 'YokoGoodStone'; } class MockTires extends Tires { make = 'YokoGoodStone'; }
// #enddocregion car-ctor-instantiation-with-mocks // #enddocregion car-ctor-instantiation-with-mocks
export function testCar() { export function testCar() {
// #docregion car-ctor-instantiation-with-mocks // #docregion car-ctor-instantiation-with-mocks
// Test car with 8 cylinders and YokoGoodStone tires. // Test car with 8 cylinders and YokoGoodStone tires.
let car = new Car(new MockEngine(), new MockTires()); const car = new Car(new MockEngine(), new MockTires());
// #enddocregion car-ctor-instantiation-with-mocks // #enddocregion car-ctor-instantiation-with-mocks
car.description = 'Test'; car.description = 'Test';
return car; return car;

View File

@ -4,7 +4,7 @@ import { Engine, Tires, Car } from './car';
// BAD pattern! // BAD pattern!
export class CarFactory { export class CarFactory {
createCar() { createCar() {
let car = new Car(this.createEngine(), this.createTires()); const car = new Car(this.createEngine(), this.createTires());
car.description = 'Factory'; car.description = 'Factory';
return car; return car;
} }

View File

@ -1,7 +1,7 @@
import { Injector } from '@angular/core'; import { Injector } from '@angular/core';
import { Car, Engine, Tires } from './car'; import { Car, Engine, Tires } from './car';
import { Logger } from '../logger.service'; import { Logger } from '../logger.service';
// #docregion injector // #docregion injector
export function useInjector() { export function useInjector() {
@ -26,14 +26,14 @@ export function useInjector() {
] ]
}); });
// #docregion injector-call // #docregion injector-call
let car = injector.get(Car); const car = injector.get(Car);
// #enddocregion injector-call, injector-create-and-call // #enddocregion injector-call, injector-create-and-call
car.description = 'Injector'; car.description = 'Injector';
injector = Injector.create({ injector = Injector.create({
providers: [{ provide: Logger, deps: [] }] providers: [{ provide: Logger, deps: [] }]
}); });
let logger = injector.get(Logger); const logger = injector.get(Logger);
logger.log('Injector car.drive() said: ' + car.drive()); logger.log('Injector car.drive() said: ' + car.drive());
return car; return car;
} }

View File

@ -1,15 +1,15 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Car, Engine, Tires } from './car'; import { Car, Engine, Tires } from './car';
import { Car as CarNoDi } from './car-no-di'; import { Car as CarNoDi } from './car-no-di';
import { CarFactory } from './car-factory'; import { CarFactory } from './car-factory';
import { testCar, import { testCar,
simpleCar, simpleCar,
superCar } from './car-creations'; superCar } from './car-creations';
import { useInjector } from './car-injector'; import { useInjector } from './car-injector';
@Component({ @Component({
@ -27,9 +27,9 @@ import { useInjector } from './car-injector';
providers: [Car, Engine, Tires] providers: [Car, Engine, Tires]
}) })
export class CarComponent { export class CarComponent {
factoryCar = (new CarFactory).createCar(); factoryCar = (new CarFactory()).createCar();
injectorCar = useInjector(); injectorCar = useInjector();
noDiCar = new CarNoDi; noDiCar = new CarNoDi();
simpleCar = simpleCar(); simpleCar = simpleCar();
superCar = superCar(); superCar = superCar();
testCar = testCar(); testCar = testCar();

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
@Component({ @Component({
selector: 'app-hero-list', selector: 'app-hero-list',

View File

@ -1,7 +1,7 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
// #enddocregion // #enddocregion
import { HeroService } from './hero.service.1'; import { HeroService } from './hero.service.1';
/* /*

View File

@ -1,7 +1,7 @@
/* tslint:disable:one-line */ /* tslint:disable:one-line */
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
@Component({ @Component({

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
import { Logger } from '../logger.service'; import { Logger } from '../logger.service';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',

View File

@ -1,11 +1,11 @@
/* tslint:disable:one-line */ /* tslint:disable:one-line */
// #docregion // #docregion
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
import { Logger } from '../logger.service'; import { Logger } from '../logger.service';
import { UserService } from '../user.service'; import { UserService } from '../user.service';
// #docregion factory // #docregion factory
let heroServiceFactory = (logger: Logger, userService: UserService) => { const heroServiceFactory = (logger: Logger, userService: UserService) => {
return new HeroService(logger, userService.user.isAuthorized); return new HeroService(logger, userService.user.isAuthorized);
}; };
// #enddocregion factory // #enddocregion factory

Some files were not shown because too many files have changed in this diff Show More