Compare commits

...

484 Commits

Author SHA1 Message Date
b6bc0aeb61 release: cut the v10.0.0-next.6 release 2020-05-07 15:52:58 -07:00
77d8afb7da docs: release notes for the v9.1.5 release 2020-05-07 15:13:17 -07:00
42d1091d6a fix(compiler-cli): don't try to tag non-ts files as shims (#36987)
Some projects include .js source files (via the TypeScript allowJs option).
Previously, the compiler would attempt to tag these files for shims, which
caused errors as the regex used to create shim filenames assumes a .ts file.
This commit fixes the bug by filtering out non-ts files during tagging.

PR Close #36987
2020-05-07 14:45:05 -07:00
d0280a0335 fix(compiler): remove outdated and invalid warning for unresolved DI parameters (#36985)
In past versions of the View Engine compiler, we added a warning that is
printed whenever the compiler comes across an Angular declaration with a
constructor that does not match suitable DI tokens. The warning mentioned
that in `v6.x` it will turn into an actual error.

This actually happened as expected for most cases. e.g. the constructor
of `@NgModule`, `@Component`'s, `@Pipe`'s etc will be checked and an error
will be reported if constructor is not DI compatible.

The warning has never been removed though as it was still relevant for
unprovided injectables, or injectables serialized into summaries of the
Angular compiler.

As of version 10, classes that use Angular features need an Angular decorator.
This includes base classes of services that use the lifecycles Angular feature.
Due to this being a common pattern now, we can remove the warning in
View Engine. The warning is not correct, and also quite confusing as it
mentions the planned removal in `v6.x`.

Resolves FW-2147.

PR Close #36985
2020-05-07 14:44:42 -07:00
97d6d909e7 fix(forms): number input fires valueChanges twice. (#36087)
Prior to this commit, number input fields would to fire valueChanges twice: once for `input` events when typing and second for the `change` event when the field lost focus (both events happen at once when using the increment and decrement buttons on the number field).

Fixes #12540

BREAKING CHANGE: Number inputs no longer listen to the `change` event.
* Tests which trigger `change` events need to be updated to trigger `input` events instead.
* The `change` event was in place to support IE9, as we found that `input` events were not fired with backspace or cut actions. If you need to maintain IE9 support, you will need to add a change event listener to number inputs and call the `onChange` method of `NumberValueAccessor` manually.
* Lastly, old versions of WebDriver would synthetically trigger the `change` event on `WebElement.clear` and `WebElement.sendKeys`. If you are using an old version of WebDriver, you may need to update tests to ensure `input` events are triggered. For example, you could use `element.sendKeys(Keys.chord(Keys.CONTROL, "a"), Keys.BACK_SPACE);` in place of `element.clear()`.

PR Close #12540

PR Close #36087
2020-05-07 10:20:26 -07:00
f7815cf96d test(compiler-cli): ensure reflection tests are not brittle to case-sensitivity (#36859)
These tests were matching file-paths against what is retrieved from the
TS compiler. But the TS compiler paths have been canonicalised, so the
tests were brittle on case-insensitive file-systems.

PR Close #36859
2020-05-06 15:23:16 -07:00
9e43e4900e test(compiler-cli): ensure partial-evaluator tests are not brittle to case-sensitivity (#36859)
These tests were matching file-paths against what is retrieved from the
TS compiler. But the TS compiler paths have been canonicalised, so the
tests were brittle on case-insensitive file-systems.

PR Close #36859
2020-05-06 15:23:16 -07:00
8ce38cac0d test(compiler-cli): ensure indexer tests are not brittle to case-sensitivity (#36859)
These tests were matching file-paths against what is retrieved from the
TS compiler. But the TS compiler paths have been canonicalised, so the
tests were brittle on case-insensitive file-systems.

PR Close #36859
2020-05-06 15:23:16 -07:00
a10c126692 fix(compiler-cli): use CompilerHost to ensure canonical file paths (#36859)
The type checking infrastrure uses file-paths that may come from the
TS compiler. Such paths will have been canonicalized, and so the type
checking classes must also canonicalize paths when matching.

PR Close #36859
2020-05-06 15:23:16 -07:00
b682bd1916 fix(compiler-cli): normalize mock Windows file paths correctly (#36859)
Since the `MockFileSystemWindows` is case-insensitive, any
drive path that must be added to a normalized path should be lower
case to make the path canonical.

PR Close #36859
2020-05-06 15:23:16 -07:00
26eacd4fcb fix(compiler-cli): ensure MockFileSystem handles case-sensitivity (#36859)
Previously this class used the file passed in directly to look up files in the
in-memory mock file-system. But this doesn't match the behaviour of
case-insensitive file-systems. Now the look up is done on the canonical
file paths.

PR Close #36859
2020-05-06 15:23:16 -07:00
fc4741f638 fix(compiler-cli): isCaseSensitive() returns correct value (#36859)
Previously this method was returning the exact opposite value
than the correct one.
Also, calling `this.exists()` causes an infinite recursions,
so the actual file-system `fs.existsSync()` method is used
to ascertain the case-sensitivity of the file-system.

PR Close #36859
2020-05-06 15:23:16 -07:00
3f3e9b7555 fix(compiler-cli): ensure getRootDirs() handles case-sensitivity (#36859)
Previously the `getRootDirs()` function was not converting
the root directory paths to their canonical form, which can
cause problems on case-insensitive file-systems.

PR Close #36859
2020-05-06 15:23:16 -07:00
53a8459d5f fix(compiler-cli): ensure LogicalFileSystem handles case-sensitivity (#36859)
The `LogicalFileSystem` was not taking into account the
case-sensitivity of the file-system when caching logical
file paths.

PR Close #36859
2020-05-06 15:23:16 -07:00
0ec0ff3bce fix(compiler-cli): fix case-sensitivity issues in NgtscCompilerHost (#36859)
The `getCanonicalFileName()` method was not actually
calling the  `useCaseSensitiveFileNames()` method. So
it always returned a case-sensitive canonical filename.

PR Close #36859
2020-05-06 15:23:15 -07:00
f930e75a80 ci: update components-repo-unit-tests job commit (#36921)
Updates the `components-repo-unit-tests` job to
d3a9ac67d2.

We need to update since we added a new diagnostic in ngtsc, and
the given commit in the components repo fixes failures caused by
the new diagnostic.

Note: This commit currently points to a PR as it's unlikely that
this fix lands soon, but we want to move forward. There is no
downside to doing that as the PR is based on top of the latest
components repo `master`.

PR Close #36921
2020-05-06 15:06:11 -07:00
854bd7d0c8 build(docs-infra): do not require abstract directives to declare a @ngModule (#36921)
Abstract directives cannot be part of a `@NgModule`, but the AIO dgeni
setup currently enforces this. This commit updates the logic so that
abstract directives are skipped.

PR Close #36921
2020-05-06 15:06:10 -07:00
e17fe90aaa refactor: fix undecorated classes with angular features in repo (#36921)
A few instances of undecorated classes with Angular features
have been discovered in the framework repo. This commit fixes
those.

PR Close #36921
2020-05-06 15:06:10 -07:00
0577bf0e3e refactor: enable ng update migrations for v10 (#36921)
Enables the `ng update` migrations for v10. Status for individual
migrations:

**undecorated-classes-with-di**.

This migration dealt exlusively with inherited constructors and
cases where a derived component was undecorated. In those cases,
the migration added `@Directive()` or copied the inherited decorator
to the derived class.

We don't need to run this migration again because ngtsc throws if
constructor is inherited from an undecorated class. Also ngtsc will
throw if a NgModule references an undecorated class in the declarations.

***undecorated-classes-with-decorated-fields***

This migration exclusively deals with undecorated classes that use
Angular features but are not decorated. Angular features include
the use of lifecycle hooks or class fields with Angular decorators,
such as `@Input()`.

We want to re-run this migration in v10 as we will disable the
compatibility code in ngtsc that detects such undecorated classes
as `@Directive`.

**module-with-providers**:

This migration adds an explicit generic type to `ModuleWithProviders`.
As of v10, the generic type is required, so we need to re-run the
migration again.

**renderer-to-renderer2**:

We don't need to re-run that migration again as the
renderer has been already removed in v9.

**missing-injectable**:

This migration is exclusively concerned with undecorated
providers referenced in an `NgModule`. We should re-run
that migration again as we don't have proper backsliding
prevention for this yet. We can consider adding an error
in ngtsc for v10, or v11. In either way, we should re-run
the migration.

**dynamic-queries**:

We ran this one in v9 to reduce code complexity in projects. Instead
of explicitly passing `static: false`, not passing any object literal
has the same semantics. We don't need to re-run the migration again
since there is no good way to prevent backsliding and we cannot always
run this migration for future versions (as some apps might actually
intentionally use the explicit `static: false` option).

PR Close #36921
2020-05-06 15:06:10 -07:00
4c92cf43cf feat(compiler-cli): report error if undecorated class with Angular features is discovered (#36921)
Previously in v9, we deprecated the pattern of undecorated base classes
that rely on Angular features. We ran a migration for this in version 9
and will run the same on in version 10 again.

To ensure that projects do not regress and start using the unsupported
pattern again, we report an error in ngtsc if such undecorated classes
are discovered.

We keep the compatibility code enabled in ngcc so that libraries
can be still be consumed, even if they have not been migrated yet.

Resolves FW-2130.

PR Close #36921
2020-05-06 15:06:10 -07:00
c6ecdc9a81 feat(core): undecorated-classes-with-decorated-fields migration should handle classes with lifecycle hooks (#36921)
As of v10, undecorated classes using Angular features are no longer
supported. In v10, we plan on removing the undecorated classes
compatibility code in ngtsc. This means that old patterns for
undecorated classes will result in compilation errors.

We had a migration for this in v9 already, but it looks like
the migration does not handle cases where classes uses lifecycle
hooks. This is handled in the ngtsc compatibility code, and we
should handle it similarly in migrations too.

This has not been outlined in the migration plan initially,
but an appendix has been added for v10 to the plan document.

https://hackmd.io/vuQfavzfRG6KUCtU7oK_EA?both.

Note: The migration is unable to determine whether a given undecorated
class that only defines `ngOnDestroy` is a directive or an actual
service. This means that in some cases the migration cannot do
more than adding a TODO and printing an failure.

Certainly there are more ways to determine the type of such classes,
but it would involve metadata and NgModule analysis. This is out of
scope for this migration.

PR Close #36921
2020-05-06 15:06:10 -07:00
20cc3ab37e refactor(core): make generic mandatory for ModuleWithProviders (#36892)
In v9, we deprecated the use of ModuleWithProviders
without a generic. In v10, we will be requiring the
generic when using ModuleWithProviders. You can read
more about the reasoning behind this change in the
migration guide:
http://v9.angular.io/guide/migration-module-with-providers

PR Close #36892
2020-05-06 15:01:34 -07:00
420b9be1c1 refactor: disable sanitization for [style] and [style.prop] bindings (#35621)
This patch is the first of many commits to disable sanitization for
[stlye.prop] and [style] bindings in Angular.

Historically, style-based sanitization has only been required for old
IE browsers (IE6 and IE7). Since Angular does not support these old
browsers at all, there is no reason for the framework to support
style-based sanitization.

PR Close #35621
2020-05-06 15:00:22 -07:00
3c6c00d1d4 docs: remove the note about @angular/http from the deprecations guide (#36944)
We stopped publishing @angular/http to npm a while back (v7?), so from the perspective of our
customer @angular/http has been removed a long time ago and mentioninig it now that we actually
removed the code from our repo is just confusing.

PR Close #36944
2020-05-06 13:54:27 -07:00
6fa36e387f test(docs-infra): temporarily disable the 'upgrade-phonecat-2-hybrid' docs example test (#36944)
This is due to issue described in: https://github.com/angular/angular/issues/36957

This commit works around the problem rather than trying to solve it in order to unblock the big APF v10 change.

PR Close #36944
2020-05-06 13:54:27 -07:00
9bde1be5a4 test: disable ng_package tests in ivy test jobs (#36944)
Since we no longer hardcode the `package.json` for
entry-points, a bug has appeared for `ng_package` in Ivy.

The `package.json` files are populated incorrectly with Ivy
as the flat module bundle name is not propagated from `ng_module`
to the `ng_package` rule. The rule then guesses the index file
to `index.js` and does not respect the flat module bundle shim.

PR Close #36944
2020-05-06 13:54:27 -07:00
040253c426 build: update side-effects integration test to not expect esm5 output (#36944)
As mentioned in previous commits, as of v10 the release output
does no longer contain ESM5 output due to an update to the APF.

This means that the side-effect integration test needs to be
updated as it currently expects/tests esm5 output.

PR Close #36944
2020-05-06 13:54:27 -07:00
c98a4d6ddd feat(ngcc): support for new APF where module points to esm2015 output (#36944)
As of version 10, libraries following the APF will no longer contain
ESM5 output. Hence, tests in ngcc need to be updated as they currently
rely on the release output of `@angular/core`.

Additionally, we'd need to support in ngcc that the `module`
property of entry-points no longer necessarily refers to
`esm5` output, but instead can also target `esm2015`.

We currently achieve this by checking the path the `module`
property points to. We can do this because as per APF, the
folder name is known for the esm2015 output. Long-term for
more coverage, we want to sniff the format by looking for
known ES2015 constructs in the file `module` refers to.

PR Close #36944
2020-05-06 13:54:26 -07:00
d5293d2aa3 fix(bazel): ng_package rule should update "package.json" of ts_library targets (#36944)
In the past we added support for `ts_library` to `ng_package`. For those
targets we never can determine the "index" file. Unlike `ng_module`,
there is no provider data for flat module bundles, so the `ng_package`
rule assumes that the index file is simply called `index`.

This works as expected, but we also added logic in the past that doesn't
allow `ng_package` to add format properties (e.g. `main`, `module`) to a
`package.json` if a package json is handwritten for such a `ts_library` target.

This has been done that way because we assumed that such `package.json` files
might want to set format properties explicitly to different paths due to a
faulty "index" guess.

We want to change this behavior as most of the time a `package.json`
file already exists with just the module name. In those cases, the
packager should still set the format properties. We should only warn
and skip automatic insertion of the format properties if such a
`package.json` explicitly sets format properties.

PR Close #36944
2020-05-06 13:54:26 -07:00
d578ab8f3c build: simplify package.jsons for all of our packages (#36944)
We can remove all of the entry point resolution configuration from the package.json
in our source code as ng_package rule adds the properties automatically and correctly
configures them.

This change simplifies our code base but doesn't have any impact on the package.json
in the distributed npm_packages.

PR Close #36944
2020-05-06 13:54:26 -07:00
9dbb30f884 feat(bazel): simplify ng_package by dropping esm5 and fesm5 (#36944)
esm5 and fesm5 are no longer needed and have been deprecated in the past.

https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages

This commit modifies ng_package to no longer distribute these two formats in npm packages
built by ng_package (e.g. @angular/core).

This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5 and fems5
build artifacts as that is a bigger cleanup and currently we are narrowing down the scope of this change
to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5' into the npm packages.

More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143

BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in
Angular's npm packages e.g. @angular/core

If you are not using Angular CLI to build your application or library,
and you need to be able to build es5 artifacts, then you will need to
downlevel the distributed Angular code to es5 on your own.

Angular CLI will automatically downlevel the code to es5 if differential
loading is enabled in the Angular project, so no action is required from
Angular CLI users.

PR Close #36944
2020-05-06 13:54:26 -07:00
fafa50d97f fix(ngcc): support ModuleWithProviders functions that delegate (#36948)
In #36892 the `ModuleWithProviders` type parameter becomes required.
This exposes a bug in ngcc, where it can only handle functions that have a
specific form:

```
function forRoot() {
  return { ... };
}
```

In other words, it only accepts functions that return an object literal.

In some libraries, the function instead returns a call to another function.
For example in `angular-in-memory-web-api`:

```
InMemoryWebApiModule.forFeature = function (dbCreator, options) {
  return InMemoryWebApiModule_1.forRoot(dbCreator, options);
};
```

This commit changes the parsing of such functions to use the
`PartialEvaluator`, which can evaluate these more complex function
bodies.

PR Close #36948
2020-05-06 13:35:48 -07:00
e010f2ca54 refactor(ngcc): move getModuleWithProvidersFunctions() into the analyzer (#36948)
Previously this method was implemented on the `NgccReflectionHost`,
but really it is asking too much of the host, since it actually needs to do
some static evaluation of the code to be able to support a wider range
of function shapes. Also there was only one implementation of the method
in the `Esm2015ReflectionHost` since it has no format specific code in
in.

This commit moves the whole function (and supporting helpers) into the
`ModuleWithProvidersAnalyzer`, which is the only place it was being used.
This class will be able to do further static evaluation of the function bodies
in order to support more function shapes than the host can do on its own.

The commit removes a whole set of reflection host tests but these are
already covered by the tests of the analyzer.

PR Close #36948
2020-05-06 13:35:48 -07:00
c9e0db55f7 refactor(core): deprecate WrappedValue (#36819)
The purpose of the `WrappedValue` is to allow same object instance to be treated as different for the purposes of change detection. It is currently used with `async` pipe and only with `Observables`. The use case which it covers is if the `Observable` produces the same instance of the value but it is desirable to still try to mark it as changed for the purposes of change detection.

We believe tha the above use case is too rare to warrant special handling in the framework. (Having special handling causes application slowdown for the users and mental load for the developers.) No replacement is planned for this deprecation.

PR Close #36819
2020-05-06 11:49:57 -07:00
ecffc3557f perf(compiler-cli): perform template type-checking incrementally (#36211)
This optimization builds on a lot of prior work to finally make type-
checking of templates incremental.

Incrementality requires two main components:
- the ability to reuse work from a prior compilation.
- the ability to know when changes in the current program invalidate that
  prior work.

Prior to this commit, on every type-checking pass the compiler would
generate new .ngtypecheck files for each original input file in the program.

1. (Build #1 main program): empty .ngtypecheck files generated for each
   original input file.

2. (Build #1 type-check program): .ngtypecheck contents overridden for those
   which have corresponding components that need type-checked.

3. (Build #2 main program): throw away old .ngtypecheck files and generate
   new empty ones.

4. (Build #2 type-check program): same as step 2.

With this commit, the `IncrementalDriver` now tracks template type-checking
_metadata_ for each input file. The metadata contains information about
source mappings for generated type-checking code, as well as some
diagnostics which were discovered at type-check analysis time. The actual
type-checking code is stored in the TypeScript AST for type-checking files,
which is now re-used between programs as follows:

1. (Build #1 main program): empty .ngtypecheck files generated for each
   original input file.

2. (Build #1 type-check program): .ngtypecheck contents overridden for those
   which have corresponding components that need type-checked, and the
   metadata registered in the `IncrementalDriver`.

3. (Build #2 main program): The `TypeCheckShimGenerator` now reuses _all_
   .ngtypecheck `ts.SourceFile` shims from build #1's type-check program in
   the construction of build #2's main program. Some of the contents of
   these files might be stale (if a component's template changed, for
   example), but wholesale reuse here prevents unnecessary changes in the
   contents of the program at this point and makes TypeScript's job a lot
   easier.

4. (Build #2 type-check program): For those input files which have not
   "logically changed" (meaning components within are semantically the same
   as they were before), the compiler will re-use the type-check file
   metadata from build #1, and _not_ generate a new .ngtypecheck shim.
   For components which have logically changed or where the previous
   .ngtypecheck contents cannot otherwise be reused, code generation happens
   as before.

PR Close #36211
2020-05-05 18:40:42 -07:00
b861e9c0ac perf(compiler-cli): split Ivy template type-checking into multiple files (#36211)
As a performance optimization, this commit splits the single
__ngtypecheck__.ts file which was previously added to the user's program as
a container for all template type-checking code into multiple .ngtypecheck
shim files, one for each original file in the user's program.

In larger applications, the generation, parsing, and checking of this single
type-checking file was a huge performance bottleneck, with the file often
exceeding 1 MB in text content. Particularly in incremental builds,
regenerating this single file for the entire application proved especially
expensive.

This commit introduces a new strategy for template type-checking code which
makes use of a new interface, the `TypeCheckingProgramStrategy`. This
interface abstracts the process of creating a new `ts.Program` to type-check
a particular compilation, and allows the mechanism there to be kept separate
from the more complex logic around dealing with multiple .ngtypecheck files.

A new `TemplateTypeChecker` hosts that logic and interacts with the
`TypeCheckingProgramStrategy` to actually generate and return diagnostics.
The `TypeCheckContext` class, previously the workhorse of template type-
checking, is now solely focused on collecting and generating type-checking
file contents.

A side effect of implementing the new `TypeCheckingProgramStrategy` in this
way is that the API is designed to be suitable for use by the Angular
Language Service as well. The LS also needs to type-check components, but
has its own method for constructing a `ts.Program` with type-checking code.

Note that this commit does not make the actual checking of templates at all
_incremental_ just yet. That will happen in a future commit.

PR Close #36211
2020-05-05 18:40:42 -07:00
4213e8d5f0 fix(compiler): switch to 'referencedFiles' for shim generation (#36211)
Shim generation was built on a lie.

Shims are files added to the program which aren't original files authored by
the user, but files authored effectively by the compiler. These fall into
two categories: files which will be generated (like the .ngfactory shims we
generate for View Engine compatibility) as well as files used internally in
compilation (like the __ng_typecheck__.ts file).

Previously, shim generation was driven by the `rootFiles` passed to the
compiler as input. These are effectively the `files` listed in the
`tsconfig.json`. Each shim generator (e.g. the `FactoryGenerator`) would
examine the `rootFiles` and produce a list of shim file names which it would
be responsible for generating. These names would then be added to the
`rootFiles` when the program was created.

The fatal flaw here is that `rootFiles` does not always account for all of
the files in the program. In fact, it's quite rare that it does. Users don't
typically specify every file directly in `files`. Instead, they rely on
TypeScript, during program creation, starting with a few root files and
transitively discovering all of the files in the program.

This happens, however, during `ts.createProgram`, which is too late to add
new files to the `rootFiles` list.

As a result, shim generation was only including shims for files actually
listed in the `tsconfig.json` file, and not for the transitive set of files
in the user's program as it should.

This commit completely rewrites shim generation to use a different technique
for adding files to the program, inspired by View Engine's shim generator.
In this new technique, as the program is being created and `ts.SourceFile`s
are being requested from the `NgCompilerHost`, shims for those files are
generated and a reference to them is patched onto the original file's
`ts.SourceFile.referencedFiles`. This causes TS to think that the original
file references the shim, and causes the shim to be included in the program.
The original `referencedFiles` array is saved and restored after program
creation, hiding this little hack from the rest of the system.

The new shim generation engine differentiates between two kinds of shims:
top-level shims (such as the flat module entrypoint file and
__ng_typecheck__.ts) and per-file shims such as ngfactory or ngsummary
files. The former are included via `rootFiles` as before, the latter are
included via the `referencedFiles` of their corresponding original files.

As a result of this change, shims are now correctly generated for all files
in the program, not just the ones named in `tsconfig.json`.

A few mitigating factors prevented this bug from being realized until now:

* in g3, `files` does include the transitive closure of files in the program
* in CLI apps, shims are not really used

This change also makes use of a novel technique for associating information
with source files: the use of an `NgExtension` `Symbol` to patch the
information directly onto the AST object. This is used in several
circumstances:

* For shims, metadata about a `ts.SourceFile`'s status as a shim and its
  origins are held in the extension data.
* For original files, the original `referencedFiles` are stashed in the
  extension data for later restoration.

The main benefit of this technique is a lot less bookkeeping around `Map`s
of `ts.SourceFile`s to various kinds of data, which need to be tracked/
invalidated as part of incremental builds.

This technique is based on designs used internally in the TypeScript
compiler and is serving as a prototype of this design in ngtsc. If it works
well, it could have benefits across the rest of the compiler.

PR Close #36211
2020-05-05 18:40:42 -07:00
bab90a7709 fix(compiler-cli): fix bug tracking indirect NgModule dependencies (#36211)
The compiler needs to track the dependencies of a component, including any
NgModules which happen to be present in a component's scope. If an upstream
NgModule changes, any downstream components need to have their templates
re-compiled and re-typechecked.

Previously, the compiler handled this well for the A -> B -> C case where
module A imports module B which re-exports module C. However, it fell apart
in the A -> B -> C -> D case, because previously tracking focused on changes
to components/directives in the scope, and not NgModules specifically.

This commit introduces logic to track which NgModules contributed to a given
scope, and treat them as dependencies of any components within.

This logic also contains a bug, which is intentional for now. It
purposefully does not track transitive dependencies of the NgModules which
contribute to a scope. If it did, using the current dependency system, this
would treat all components and directives (even those not exported into the
scope) as dependencies, causing a major performance bottleneck. Only those
dependencies which contributed to the module's export scope should be
considered, but the current system is incapable of making this distinction.
This will be fixed at a later date.

PR Close #36211
2020-05-05 18:40:42 -07:00
da79e0433f test(language-service): [ivy] Add mock service to overwrite files (#36923)
Add a mechanism to replace file contents for a specific file. This
allows us to write custom test scenarios in code without modifying the
test project.

Since we are no longer mocking the language service host, the file
overwrite needs to happen via the project service.
Project service manages a set of script infos, and overwriting the files
is a matter of updating the relevant script infos.

Note that the actual project service is wrapped inside a Mock Service.
Tests should not have direct access to the project service. All
manipulations should take place via the Mock Service.

The MockService provides a `reset()` method to undo temporary overwrites
after each test.

PR Close #36923
2020-05-05 17:52:12 -07:00
1b8752e595 refactor(docs-infra): take advantage of latest Jasmine features in preview server tests (#36837)
This commit updates the preview server tests to take advantage of
features supported in the latest version of Jasmine that were not
supported when the rests were first written.

Changes include:

- Use [async/await] in tests.
- Use the new [toBeInstanceOf()] and [toHaveBeenCalledBefore()] matchers.
- Use the new [toBeResolved()] and [toBeRejected()] async matchers (and
  their variants).
- Use the new [withArgs()] method of `Spy` to simplify "trained"
  responses.
- Use the new [resolveTo()]/[rejectWith()] methods of `SpyStrategy` (and
  their variants) to simplify promise-based spies.
- Implement custom async matchers (via [addAsyncMatchers()]) to simplify
  certain tests.

[addAsyncMatchers()]: https://jasmine.github.io/api/3.5/jasmine.html#.addAsyncMatchers
[async/await]: https://jasmine.github.io/tutorials/async
[rejectWith()]: https://jasmine.github.io/api/3.5/SpyStrategy.html#rejectWith
[resolveTo()]: https://jasmine.github.io/api/3.5/SpyStrategy.html#resolveTo
[toBeInstanceOf()]: https://jasmine.github.io/api/3.5/matchers.html#toBeInstanceOf
[toBeRejected()]: https://jasmine.github.io/api/3.5/async-matchers.html#toBeRejected
[toBeResolved()]: https://jasmine.github.io/api/3.5/async-matchers.html#toBeResolved
[toHaveBeenCalledBefore()]: https://jasmine.github.io/api/3.5/matchers.html#toHaveBeenCalledBefore
[withArgs()]: https://jasmine.github.io/api/3.5/Spy.html#withArgs

PR Close #36837
2020-05-05 17:46:46 -07:00
b3cf5b246f test(docs-infra): enable accidentally disabled preview server tests (#36837)
Previously, some preview server tests were only running for public
builds. In the past, these tests were run for both public and non-public
builds. The non-public builds tests were disabled in #23576, probably
during debugging some failure.

This commit fixes it by ensuring the tests are run for both public and
non-public builds.

PR Close #36837
2020-05-05 17:46:46 -07:00
0a695e181e test(docs-infra): remove incorrect preview server test (#36837)
The test was introduced in #23576, but the behavior the test was
verifying does not match the actual behavior of
`BuildCleaner#getOpenPrNumbers()`.

The reason that the test did not fail is that the verification happened
asynchronously, but the test completed synchronously (by accident).

PR Close #36837
2020-05-05 17:46:46 -07:00
a5d1d1161b fix(docs-infra): exit with an error when cleaning up the preview server fails (#36837)
Previously, when the preview server `build-cleanup` script failed, the
error was logged but not reflected to the commands exit code. This seems
to have been accidentally broken in #23576.

This commit fixes it by ensuring the error is re-thrown from the
`BuildCleaner#cleanUp()` method to allow the process to exit with an
error exit code.

PR Close #36837
2020-05-05 17:46:46 -07:00
a25c3c5c3b build(docs-infra): remove linting from the preview server dev npm script (#36837)
Previously, the `dev` npm script in `aio/aio-builds-setup/scripts-js/`
(the PR preview server implementation) would run both linting and unit
tests. This was slow and delayed the feedback loop on each change.

Since the `dev` script should be run during development and give
feedback as fast as possible, this commit removes the linting from the
`dev` script and only keeps the unit tests. Linting is still run in the
`test` npm script (which is more comprehensive). Also, in most cases the
developer's IDE will show linting errors in real time in the editor.

PR Close #36837
2020-05-05 17:46:46 -07:00
d1a8afbbd0 refactor(docs-infra): update argument order for update-preview-server.sh script (#36837)
Update the order in which the `update-preview-server.sh` script expects
its arguments (and the associated docs) to be consistent with the order
of arguments in other commands/docs (such as
`vm-setup--start-docker-container.md`).

PR Close #36837
2020-05-05 17:46:46 -07:00
f4fcb0c54c docs(docs-infra): update preview server setup instructions (#36837)
I recently went through the process of setting up a preview server VM
again and updated the instructions and references based on the latest
docs for Debian, Docker, Google Compute Engine, etc.

PR Close #36837
2020-05-05 17:46:46 -07:00
e92b81351b build(docs-infra): unpin certain dependencies of the preview server (#36837)
Previously, in order to remain as deterministic as possible, the
Dockerfile for the preview server Docker image had all dependencies
pinned to specific versions. It turns out that some packages (such as
`nginx`, `nodejs`, and `openssl` - potentially others too) make older
versions unavailable on the repositories once a newer version is
available.

See for example:
- https://github.com/nodesource/distributions/issues/33
- https://askubuntu.com/questions/715104/how-can-i-downgrade-openssl-via-apt-get

This commit, therefore, removes the exact versions for these packages.
The latest versions will be installed everytime the Docker image is
built (subject to Docker caching).

PR Close #36837
2020-05-05 17:46:45 -07:00
53805f07ba test(docs-infra): check TLS certificates as part of preview server's health check (#36837)
In order to ease local development, self-signed SSL/TLS certificates are
created when building the preview server Docker image. These
certificates are valid for 365 days. Thus, it is possible for an old
certificate to be re-used past its expiration date due to Docker's
caching intermediate layers.

Previously, this would lead to hard-to-debug failures in the
`aio-health-check` and `aio-verify-setup` checks. Even after finding out
that the failures were caused by an expired certificate, it was not
obvious why that would be the case.

This commit adds an additional check to the `aio-health-check` command
that checks the certificates' expiration dates. This helps surface such
errors. It also prints a more helpful message, prompting the user to
build the Docker image with the `--no-cache` option to fix the problem
with self-signed certificates.

PR Close #36837
2020-05-05 17:46:45 -07:00
e73daa3736 build(docs-infra): upgrade preview server Docker image to Debian 10 (buster) (#36837)
Previously, the preview server Docker image was based on Debian 9
(stretch).

This commit upgrades the preview server Docker image to Debian 10
(buster) and also upgrades all dependencies to latest versions
(including upgrading Node.js from v10 to v12).

(The GCE VM running the preview server Docker container was also
upgraded from Debian 9 to 10 on 2020-04-27.)

---
Other changes:
- Pinned the installed version of `curl` to make the `aio-health-check`
  and `aio-verify-setup` checks (which use `curl`) more deterministic.
- Dropped the `*-backports` Debian repositories, since they are no
  longer needed. The `*-backports` repositories were introduced in
  593fe5ed25 to install `nginx` from, but
  became obsolete in 2f1a862b83, which
  switched to installing `nginx` from the regular repositories again.
- Added `vim` to the list of installed dependencies (for convenience
  during debugging).

PR Close #36837
2020-05-05 17:46:45 -07:00
eef01160f4 build(docs-infra): upgrade all JS dependencies to latest versions (#36837)
This commit upgrades all dependencies in `scripts-js/` to latest
versions and also includes all necessary code changes to ensure the
tests are passing with the new dependency versions.

PR Close #36837
2020-05-05 17:46:45 -07:00
333abf16e4 build: fix typo in PullApprove group name (server-worker --> service-worker) (#36325)
PR Close #36325
2020-05-05 17:46:06 -07:00
388dc93cee feat: remove @angular/http (#27038)
The legacy HTTP package was deprecated in v5 with the launch of
@angular/common/http. The legacy package hasn't been published
since v7, and will therefore not include a migration.

PR Close #27038
2020-05-05 17:42:01 -07:00
fbd281c26e build: remove typescript 3.6 and 3.7 support (#36329)
Remove TypeScript 3.6 and 3.7 support from Angular along with tests that
ensure those TS versions work.

BREAKING CHANGE: typescript 3.6 and 3.7 are no longer supported, please
update to typescript 3.8

PR Close #36329
2020-05-05 16:52:43 -07:00
420c179b39 build: update dependencies to use typescript 3.8 and angular 9.1 (#36329)
Update the typescript version to 3.8 as well as the Angular version to
9.1, which is the one which added TS 3.8 support.

PR Close #36329
2020-05-05 16:52:43 -07:00
35d61c11fd test(core): Add benchmark for transplanted views when insertion is dirty (#36722)
The current benchmark for transplanted views only exercises the path
when the declaration location is dirty and the insertion is not. This
test adds a benchmark for when both insertion and declaration are dirty.

PR Close #36722
2020-05-05 12:20:32 -07:00
e30e1325f3 fix(core): properly get root nodes from embedded views with <ng-content> (#36051)
This commit fixes 2 separate issues related to root nodes retrieval from
embedded views with `<ng-content>`:

1) we did not account for the case where there were no projectable nodes
for a given `<ng-content>`;

2) we did not account for the case where projectable nodes for a given
`<ng-content>` were represented as an array of native nodes (happens in
the case of dynamically created components with projectable nodes);

Fixes #35967

PR Close #36051
2020-05-05 12:15:52 -07:00
fc6c3ae97d ci: removing CI environment variable caching setup (#36936)
A caching mechanism was put in place to prevent repeated calls to
the Github API.  As the CI setup no longer relies on calls to the
Github API, this caching is no longer necessary.

It was discovered that this caching was causing a contention issue
for saucelabs testing as the same tunnel was being reused for
multiple jobs simultaneously.  With this caching mechanism removed
the jobs will once again run via separate tunnels.

PR Close #36936
2020-05-05 12:08:17 -07:00
63a28d6805 build(docs-infra): upgrade cli command docs sources to b7d7ee9bd (#36933)
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](c1cf42fd4...b7d7ee9bd):

**Modified**
- help/deploy.json
- help/generate.json
- help/new.json

PR Close #36933
2020-05-05 12:06:17 -07:00
b95a336f12 build: fix and re-enable elements tests on saucelabs (#36929)
The `elements` tests were disabled on Saucelabs, because they were failing on IE10. The problem was that we were loading an es2015 file from npm directly, causing a syntax error. These changes transpile the file to es5.

PR Close #36929
2020-05-05 12:04:48 -07:00
b4df19c029 build: update release precheck to rely on ng-dev for bazel stamping (#36925)
Migrate from using tools/bazel_stamp_vars.js to ng-dev to obtain
the current version name in the pre-check script.

PR Close #36925
2020-05-05 12:03:21 -07:00
dbd0f8e699 feat(language-service): [ivy] Parse Angular compiler options (#36922)
Parse Angular compiler options in Angular language service.

In View Engine, only TypeScript compiler options are read, Angular
compiler options are not. With Ivy, there could be different modes of
compilation, most notably how strict the templates should be checked.
This commit makes the behavior of language service consistent with the
Ivy compiler.

PR Close #36922
2020-05-05 12:01:00 -07:00
b7fb92a048 build: do not build runfile trees unnecessarily (#36914)
Disables Bazel runfile tree creation. Only if a given
execution strategy relies on runfile tree creation, the
runfile tree is created lazily. This helps as currently
Bazel spends unnecessary time on CI building runfile trees
for tests which are cached and aren't re-run.

The goal is to spend less time on CI for cached test/build
targets. We can't measure impact yet as there are targets
for the integration tests that hide the potential benefits.
on the components repo a 80% time reduction could be observed.

PR Close #36914
2020-05-05 12:00:04 -07:00
2ff4b357d7 fix(core): handle pluralize functions that expect a number (#36901)
Previously we were passing a string form of the value to pluralize
to the `getLocalePluralCase()` function that is extracted from the
locale data. But some locales have functions that rely upon this
value being a number not a string.

Now we convert the value to a number before passing it to the
locale data function.

Fixes #36888

PR Close #36901
2020-05-05 11:59:04 -07:00
1c26f40cd4 refactor(localize): use the new workspaces API for ng-add schematic (#36897)
Updates the @angular/localize ng-add schematic to use the new workspaces API and removes dependency on private APIs.

PR Close #36897
2020-05-05 11:58:27 -07:00
2de34770c4 docs: update deprecation guide to move deprecated APIs to removals (#36891)
Previously, using undecorated base classes and using
ModuleWithProviders without a generic were listed
as deprecated features.

In v10, these features will be removed and an error
will be thrown instead. This commit updates the
deprecation guide to reflect this change.

PR Close #36891
2020-05-05 11:55:58 -07:00
0fc6ed3c4a docs: update likely deprecation version in deprecation guide (#36891)
The index of the deprecation guide contains a list
of deprecated APIs and when they can be removed.
This commit updates the likely removal version for
APIs that were previously listed as v10, as we are
not removing them in this version.

PR Close #36891
2020-05-05 11:55:57 -07:00
63455b839a docs: list IE 9 and 10 as deprecated (#36887)
Add documentation in the deprecations markdown file about the deprecation of IE 9 and 10.
Additionally, add note in browser support document about deprecation.

PR Close #36887
2020-05-05 11:55:17 -07:00
70b25a3d4f fix(localize): ensure getLocation() works (#36853)
The `getLocation()` method was not working as there were typos in the
properties it was reading. This was not picked up because there were
neither typings for these properties nor unit tests to check it worked.

PR Close #36853
2020-05-05 11:51:46 -07:00
2200c8a87b docs: Add new section, tutorials, to left nav, and a tutorial on routing (#36545)
This PR adds a new section, tutorials, to the left navigation. It also
adds a new, basic tutorial for routing.

PR Close #36545
2020-05-05 11:51:19 -07:00
306f46ce92 build(docs-infra): upgrade docs examples to latest Angular CLI and framework (#36145)
This commit also updates the projects to more closely match what a newly
generated app would look like with the exception of `tslint.json` files,
which would create too many linting failures. These will be updated in a
follow-up PR.

PR Close #36145
2020-05-05 11:50:30 -07:00
1b2d6ea11b ci(docs-infra): remove redundant standalone ngcc run (#36145)
Previously, in the `test_aio` CI job, we ran ngcc before building the
app with `yarn build`. This was supposed to have the benefit of taking
advantage of the parallel capabilities of standalone ngcc (vs implicitly
running it via `ng build`).

It turns out that the work done by the standalone ngcc was thrown away
before the `ng build`, resulting in `ng build` having to run ngcc all
over again. This happened because the `yarn build` script (run after the
standalone ngcc step) also runs `yarn install`, which essentially cleans
up `node_modules/`, thus discarding all the work already done by ngcc.

Here is an [example CI job][1], where this can be seen in action:
One can see the "Compiling <some-package> : es2015 as esm2015" logs in
the `yarn --cwd aio ngcc --properties es2015` step (as the standalone
ngcc processes the various entry-points) and then see the same logs in
the `yarn --cwd aio build --progress=false` step (as ngcc has to process
the entry-points all over again).

This commit removes the redundant standalone ngcc run and lets the CLI
handle ngcc via `ng build`. It is possible to instrument the build
process in a way that we can run the standalone ngcc after
`yarn install` and thus take advantage of the performance gains in
parallel mode, but the latest version of the CLI can already run ngcc in
parallel mode as a pre-build step, so this is unnecessary.

[1]: https://circleci.com/gh/angular/angular/658691

PR Close #36145
2020-05-05 11:50:30 -07:00
03198de73a build(docs-infra): update TypeScript to 3.8 (#36145)
Update TypeScript for angular.io to the latest stable version: 3.8.3

Jira issue: [FW-1970](https://angular-team.atlassian.net/browse/FW-1970)

PR Close #36145
2020-05-05 11:50:30 -07:00
bb0e57eccb build(docs-infra): update @angular/material to 9.2.2 (#36145)
This commit updates the Angular Material packages (`@angular/cdk` and
`@angular/material`) to latest versions.

PR Close #36145
2020-05-05 11:50:30 -07:00
a468f11c7c build(docs-infra): update @angular/cli to 10.0.0-next.3 (#36145)
Update the Angular CLI and Angular framework packages to latest `@next`
versions. Also, update the app to look more closely to how a newly
generated app with the latest CLI would look like.

PR Close #36145
2020-05-05 11:50:29 -07:00
9d2241b901 build(docs-infra): update angular.io payload sizes for reference (#36145)
This commit updates all payload sizes for angular.io to make it easier
to compare payload size changes as a result of upgrading Angular
packages and other dependencies in subsequent commits.

PR Close #36145
2020-05-05 11:50:29 -07:00
88a235de3a fix(forms): handle numeric values properly in the validator (#36157)
Previously, the behavior of the `minLength` and `maxLength` validators
caused confusion, as they appeared to work with numeric values but
did not in fact produce consistent results. This commit fixes the issue
by skipping validation altogether when a numeric value is used.

BREAKING CHANGES:

* The `minLength` and `maxLength` validators now verify that a value has
numeric `length` property and invoke validation only if that's the case.
Previously, falsey values without the length property (such as `0` or
`false` values) were triggering validation errors. If your code relies on
the old behavior, you can include other validators such as [min][1] or
[requiredTrue][2] to the list of validators for a particular field.

[1]: https://angular.io/api/forms/Validators#min
[2]: https://angular.io/api/forms/Validators#requiredTrue

Closes #35591

PR Close #36157
2020-05-05 11:50:00 -07:00
7bd9e09c78 release: cut the v10.0.0-next.5 release 2020-05-04 14:48:09 -07:00
42c58d9fe8 docs(dev-infra): update format commands described in DEVELOPER.md (#36910)
This commit updates DEVELOPER.md to describe the latest formatting
command 'ng-dev' and removed deprecated 'gulp' command.

Fixes #36909

PR Close #36910
2020-05-04 12:51:21 -07:00
b3713a112f test(language-service): Add method to override inline template (#36890)
This commit adds a method `overrideInlineTemplate` to the
`MockTypescriptHost`. This allows us to override an inline template
in a Component without changing the TypeScript parts. This methods works
in a similar way as `MockTypescriptHost.override()`, which is used for
overriding external template.

PR Close #36890
2020-05-04 12:50:47 -07:00
e037840b88 perf(ngcc): speed up the getBasePaths() computation (#36881)
This function needs to deduplicate the paths that are found from the
paths mappings. Previously this deduplication was not linear and also
called the expensive `relative()` function many times.

This commit, suggested by @JoostK, reduces the complexity of the deduplication
by using a tree structure built from the segments of each path.

PR Close #36881
2020-05-04 12:50:02 -07:00
ec6b9cc17d perf(ngcc): only compute basePaths in TargetedEntryPointFinder when needed (#36881)
Previously the `basePaths` were computed when the finder was instantiated.
This was a waste of effort in the case that the targeted entry-point is already
processed.

This change makes the computation of `basePaths` lazy, so that the work is
only done if they are actually needed.

Fixes #36874

PR Close #36881
2020-05-04 12:50:02 -07:00
db4c59dad9 fix(ngcc): support TS 3.9 wrapped ES2015 classes (#36884)
In TS 3.9 the compiler will start to wrap ES2015 classes in an IIFE to help with
tree-shaking when the class has "associated" statements.

E.g.

```ts
let PlatformLocation = /** @class */ (() => {
    ...
    class PlatformLocation {
    }
    ...
    return PlatformLocation;
})();
```

This commit updates `Esm2015ReflectionHost` to support this format.

PR Close #36884
2020-05-04 12:48:26 -07:00
58ea040570 test(language-service): add new mock host for testing ivy (#36879)
This commit adds a new mock host for testing the ivy language service.

Unlike the existing mock_host which mocks the LanguageServiceHost, the
Ivy mock host mocks just the filesystem interface, aka ts.ServerHost.

This is because Ivy language service requires an actual Project to
perform operations like adding synthetic typecheck files to the project,
and by extension, to the ts.Program. These requirements make the existing
mock host unsuitable to be reused.

This new testing structure also improves test performance, because the
old mock host copies (it actually creates symlinks, but still that's
relatively expensive due to the sheer number of files involved) all
@angular/* packages along with the typescript package to a temporary
node_modules directory. This is done every time setup() is called.
Instead, this new mock host just loads them from a pre-determined path
in Bazel runfiles.

PR Close #36879
2020-05-04 12:47:15 -07:00
6046e86506 build: update setup-rbe.sh script to accept non google.com/angular.io (#36846)
Previously the setup-rbe.sh script did not allow accounts that did
have domains of angular.io or google.com.  Since we add emails from
other domains into everyone@angular.io, we are unable to be certain
in the script that the account is not actually a member of the
required group.  This change adds the option to choose to continue
with an email account logged in which we cannot verify by domain.

PR Close #36846
2020-05-04 12:45:48 -07:00
297dab845d build: migrate bazel related formatting/linting to ng-dev format (#36842)
Migrates away from inline searching for files and running buildifier
directly, instead using ng-dev for formatting.  Additionally, provides
a deprecation message for any usages of the previous commands.

PR Close #36842
2020-05-04 12:45:00 -07:00
2cb5f59acc feat(dev-infra): run buildifier formatting and linting via ng-dev (#36842)
In an effort to centralize formatting and linting enforcement into one
location, buildifier is being added as a formatter for ng-dev's format
command.  Allowing for format enforcement for all .bzl, .bazel, WORKSPACE
and BUILD files.

PR Close #36842
2020-05-04 12:45:00 -07:00
0f3831b105 build: create macro for transpiling javascript file to es5 (#36802)
For testing on IE, shims must be served in es5.  Because the shims
served in these tests come from node_modules and are not part of
the angular/angular source code, they must be transpiled to es5 if
they are published as es6. This macro allows for a uniform method
for running this transpilation during the build process.

PR Close #36802
2020-05-04 12:43:50 -07:00
9d9d46f52b fix(core): log error instead of warning for unknown properties and elements (#36399)
Changes the Ivy unknown element/property messages from being logged with `console.warn` to `console.error`. This should make them a bit more visible without breaking existing apps. Furthermore, a lot of folks filter out warning messages in the dev tools' console, whereas errors are usually still shown.

BREAKING CHANGE:
Warnings about unknown elements are now logged as errors. This won't break your app, but it may trip up tools that expect nothing to be logged via `console.error`.

Fixes #35699.

PR Close #36399
2020-05-04 12:37:42 -07:00
d9c4840a9c fix(router): cancel navigation when at least one resolver completes with no "next" emission (#24621)
This change aligns behavior for resolvers which return EMPTY. Currently EMPTY resolvers have inconsistent behavior:
- One resolver that returns EMPTY => won't navigate and just ends on ResolveStart router event.
- Two resolvers where both return EMPTY => throws "Error: Uncaught (in promise): EmptyError: no elements in sequence"
- Two resolvers where one returns a value and the other one returns EMPTY => Navigates successfully.
With this change any EMPTY resolver will cancel navigation.

BREAKING CHANGE: Any resolver which return EMPTY will cancel navigation.
If you want to allow the navigation to continue, you will need to update the resolvers to emit
some value, (i.e. defaultIfEmpty(...), of(...), etc).
PR Close #24195

PR Close #24621
2020-05-04 12:36:49 -07:00
12fcc7cafe build(language-service): make test project a filegroup (#36865)
This commit makes the test project a filegroup so that it could be
shared with the Ivy tests.
Also removed `project/foo.ts` since it is no longer used.

PR Close #36865
2020-05-01 10:02:34 -07:00
95a407d9dd build: Add entry point for Ivy language service (#36864)
This commit adds a new entry point for the Ivy version of language
service. The entry point is just a shell for now, implementation will be
added in subsequent PRs.

The Ivy version of language service could be loaded from the NPM package
via `require(@angular/language-service/bundles/ivy.umd.js)`

PR Close #36864
2020-05-01 10:02:03 -07:00
e9300c979e build: use @angular/dev-infra-private for bazel stamping (#36844)
Migrate to using new common environment stamping script for stamping
during bazel build/release tasks.

PR Close #36844
2020-05-01 10:00:04 -07:00
df274b478e feat(dev-infra): create environment stamping script in ng-dev (#36844)
Create a common environment stamping script in the ng-dev tooling
as to be used in common release tasks.  This is the first step in
consolidating pieces of the release scripting process into a single
location to develop a release tool.

PR Close #36844
2020-05-01 10:00:04 -07:00
f8941a5b6b refactor(ngcc): change async locker timeout to 250 secs (#36838)
Previously the `AsyncLocker` was configured to only wait
50x500ms before timing out. This is 25secs, which is often
less than a normal run of ngcc, so the chance of a timeout
flake was quite high.

The default is now 500x500ms, which is 250secs. If this is
too high for some projects then it can be changed via the
`ngcc.config.js` project file.

PR Close #36838
2020-05-01 09:52:10 -07:00
38f805cd06 feat(ngcc): allow async locking timeouts to be configured (#36838)
The commit adds support to the ngcc.config.js file for setting the
`retryAttempts` and `retryDelay` options for the `AsyncLocker`.

An integration test adds a new check for a timeout and actually uses the
ngcc.config.js to reduce the timeout time to prevent the test from taking
too long to complete.

PR Close #36838
2020-05-01 09:52:10 -07:00
98931bf9b5 refactor(ngcc): rename Configuration.getConfig() (#36838)
Strictly this method only returns config for packages. So this commit
renames it to `getPackageConfig()`, which frees us up to add other
"getXxxxConfig()` methods later.

PR Close #36838
2020-05-01 09:52:09 -07:00
9b85b533ff test(ngcc): remove duplicate test (#36838)
This test is basically duplicated (and slightly enhanced) in the
following test. So it is superfluous. (I suspect it was the result
of a broken rebase.)

PR Close #36838
2020-05-01 09:52:09 -07:00
d805526659 fix(ngcc): provide a unique exit code for timeouts (#36838)
When ngcc fails due to a timeout waiting for another process
to complete, it was not failing with a unique exit code, so that it
was not possible to know if the process can be restarted; compared to
ngcc failing for some more fatal reason.

Now if ngcc exits because of a timeout, the exit code will be 177.

PR Close #36838
2020-05-01 09:52:09 -07:00
ee435761fd refactor(ngcc): improve locker pausing message (#36838)
When ngcc is having to pause and wait for another process
it provides a message to the user. This commit adds the extra
information about how to remove the lockfile if desired, since
this message is not shown if you Ctrl-C out of the process before
the timeout period ends.

PR Close #36838
2020-05-01 09:52:09 -07:00
35c6ed2675 docs(di): fix typo in advanced di doc (#36634)
PR Close #36634
2020-05-01 09:50:28 -07:00
72f534f7f8 feat(localize): support merging multiple translation files (#36792)
Previously only one translation file per locale could be loaded.

Now the user can specify multiple files per locale, and the translations
from each of these files will be merged together by message id.
The merging is on a first-wins approach. So if to you have three files
to be merged:

```
['a.xlf', 'b.xmb', 'c.json']
```

Then any message from `a.xlf` will be used rather than a message from `b.xmb`
or `c.json` and so on. In practice this means that you should put the files
in order of most important first, with "fallback" translations later.

PR Close #36792
2020-05-01 09:46:12 -07:00
3cb9b43851 refactor(localize): hide merging diagnostics messages behind a method (#36792)
This commit introduces `Diagnostics.merge(other)` which will take the messages from
`other` and append them to the messages of `this`.

The translation loader is updated to use this new method.

PR Close #36792
2020-05-01 09:46:12 -07:00
bf0c520f2e refactor(localize): simplify adding condition diagnostics (#36792)
Previously the `missingTranslation` option had to be checked before calling
`warn` or `error` on the `diagnostics` object.

Now this boilerplate is hidden inside the `Diagnostics.add()` method, which
will open it up to being used for other conditional diagnostics.

PR Close #36792
2020-05-01 09:46:11 -07:00
ee35e223a7 feat(service-worker): use ignoreVary: true when retrieving responses from cache (#34663)
The Angular ServiceWorker always uses a copy of the request without
headers for caching assets (in order to avoid issues with opaque
responses). Therefore, it was previously not possible to retrieve
resources from the cache if the response contained [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary) headers.

In addition to that, `Vary` headers do not work in all browsers (or work
differently) and may not work as intended with ServiceWorker caches. See
[this article](https://www.smashingmagazine.com/2017/11/understanding-vary-header) and the linked resources for more info.

This commit avoids the aforementioned issues by making sure the Angular
ServiceWorker always sets the `ignoreVary` option passed to
[Cache#match()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) to `true`. This allows the ServiceWorker to correctly
retrieve cached responses with `Vary` headers, which was previously not
possible.

Fixes #36638

BREAKING CHANGE:

Previously, [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)
headers would be taken into account when retrieving resources from the
cache, completely preventing the retrieval of cached assets (due to
ServiceWorker implementation details) and leading to unpredictable
behavior due to inconsistent/buggy implementations in different
browsers.

Now, `Vary` headers are ignored when retrieving resources from the
ServiceWorker caches, which can result in resources being retrieved even
when their headers are different. If your application needs to
differentiate its responses based on request headers, please make sure
the Angular ServiceWorker is [configured](https://angular.io/guide/service-worker-config)
to avoid caching the affected resources.

PR Close #34663
2020-05-01 09:44:07 -07:00
dc9f4b994e feat(service-worker): include CacheQueryOptions options in ngsw-config (#34663)
Previously it was not possible to provide `CacheQueryOptions` ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Cache)) for querying the Cache.
This commit introduces a new parameter called `cacheQueryOptions` for `DataGroup` and `AssetGroup`.
Currently only `ignoreSearch` is supported as `ignoreVary` and `ignoreMethod` would require using
the complete Request object for matching which is not possible with the current implementation.

Closes #28443

PR Close #34663
2020-05-01 09:44:07 -07:00
49be32c931 refactor(common): remove WrappedValue from AsyncPipe (#36633)
`AsyncPipe` only uses `WrappedValue` when the latest value from the `Promise` or `Observable` is different from the previous one. This is already enough to trigger change detection so the `WrappedValue` is not necessary.

Fixes #29927

BREAKING CHANGE:
This change could result in ExpressionChangedAfterItHasBeenChecked errors that
were not detected before. The error could previously have gone undetected
because two WrappedValues are considered "equal" in all cases for the purposes
of the check, even if their respective unwrapped values are not.

Additionally, `[val]=(observable | async).someProperty` will no longer
trigger change detection if the value of `someProperty` is identical to
the value in the previous emit. If you need to force change detection,
either update the binding to use an object whose reference changes or
subscribe to the observable and call markForCheck as needed.

PR Close #36633
2020-04-30 11:41:49 -07:00
1786586747 fix(core): Refresh transplanted views at insertion point only (#35968)
Only refresh transplanted views at the insertion location in Ivy.
Previously, Ivy would check transplanted views at both the insertion and
declaration points. This is achieved by adding a marker to the insertion
tree when we encounter a transplanted view that needs to be refreshed at
its declaration. We use this marker as an extra indication that we still
need to descend and refresh those transplanted views at their insertion
locations even if the insertion view and/or its parents are not dirty.

This change fixes several issues:

  * Transplanted views refreshed twice if both insertion and declaration
  are dirty. This could be an error if the insertion component changes
  result in data not being available to the transplanted view because it
  is slated to be removed.
  * CheckAlways transplanted views not refreshed if shielded by
  non-dirty OnPush (fixes #35400)
  * Transplanted views still refreshed when insertion tree is detached
  (fixes #21324)

PR Close #35968
2020-04-29 14:31:12 -07:00
45c09416ed refactor(ngcc): move PathMappings to separate file to avoid circular dependency (#36626)
Now that `ngcc/src/ngcc_options` imports `FileWriter` type, there is a
circular dependency detected by the `ts-circular-deps:check` lint check:

```
ngcc/src/ngcc_options.ts
  → ngcc/src/writing/file_writer.ts
  → ngcc/src/packages/entry_point_bundle.ts
  → ngcc/src/ngcc_options.ts
```

This commit moves the `PathMappings` type (and related helpers) to a
separate file to avoid the circular dependency.

NOTE:
The circular dependency was only with taking types into account. There
was no circular dependency for the actual (JS) code.

PR Close #36626
2020-04-29 14:28:26 -07:00
4779c4b94a fix(ngcc): handle ENOMEM errors in worker processes (#36626)
When running in parallel mode, worker processes forward errors thrown
during task processing to the master process, which in turn exits with
an error.

However, there are cases where the error is not directly related to
processing the entry-point. One such case is when there is not enough
memory (for example, due to all the other tasks being processed
simultaneously).

Previously, an `ENOMEM` error thrown on a worker process would propagate
to the master process, eventually causing ngcc to exit with an error.
Example failure: https://circleci.com/gh/angular/angular/682198

This commit improves handling of these low-memory situations by
detecting `ENOMEM` errors and killing the worker process, thus allowing
the master process to decide how to handle that. The master process will
put the task back into the tasks queue and continue processing tasks
with the rest of the worker processes (and thus with lower memory
pressure).

PR Close #36626
2020-04-29 14:28:26 -07:00
793cb328de fix(ngcc): give up re-spawing crashed worker process after 3 attempts (#36626)
Previously, when the last worker process crashed, the master process
would try to re-spawn it indefinitely. This could lead to an infinite
loop (if for some reason the worker process kept crashing).

This commit avoids this by limiting the number of re-spawn attempts to
3, after which ngcc will exit with an error.

PR Close #36626
2020-04-29 14:28:26 -07:00
966598cda7 fix(ngcc): support recovering when a worker process crashes (#36626)
Previously, when running in parallel mode and a worker process crashed
while processing a task, it was not possible for ngcc to continue
without risking ending up with a corrupted entry-point and therefore it
exited with an error. This, for example, could happen when a worker
process received a `SIGKILL` signal, which was frequently observed in CI
environments. This was probably the result of Docker killing processes
due to increased memory pressure.

One factor that amplifies the problem under Docker (which is often used
in CI) is that it is not possible to distinguish between the available
CPU cores on the host machine and the ones made available to Docker
containers, thus resulting in ngcc spawning too many worker processes.

This commit addresses these issues in the following ways:

1. We take advantage of the fact that files are written to disk only
   after an entry-point has been fully analyzed/compiled. The master
   process can now determine whether a worker process has not yet
   started writing files to disk (even if it was in the middle of
   processing a task) and just put the task back into the tasks queue if
   the worker process crashes.

2. The master process keeps track of the transformed files that a worker
   process will attempt to write to disk. If the worker process crashes
   while writing files, the master process can revert any changes and
   put the task back into the tasks queue (without risking corruption).

3. When a worker process crashes while processing a task (which can be a
   result of increased memory pressure or too many worker processes),
   the master process will not try to re-spawn it. This way the number
   or worker processes is gradually adjusted to a level that can be
   accomodated by the system's resources.

Examples of ngcc being able to recover after a worker process crashed:
- While idling: https://circleci.com/gh/angular/angular/682197
- While compiling: https://circleci.com/gh/angular/angular/682209
- While writing files: https://circleci.com/gh/angular/angular/682267

Jira issue: [FW-2008](https://angular-team.atlassian.net/browse/FW-2008)

Fixes #36278

PR Close #36626
2020-04-29 14:28:26 -07:00
772ccf0d9f feat(ngcc): support reverting a file written by FileWriter (#36626)
This commit adds a `revertFile()` method to `FileWriter`, which can
revert a transformed file (and its backup - if any) written by the
`FileWriter`.

In a subsequent commit, this will be used to allow ngcc to recover
when a worker process crashes in the middle of processing a task.

PR Close #36626
2020-04-29 14:28:26 -07:00
ff6e93163f refactor(ngcc): keep track of transformed files per task (#36626)
With this commit, the master process will keep track of the transformed
files that each worker process is intending to write to disk.

In a subsequent commit, this info will be used to allow ngcc to recover
when a worker process crashes in the middle of processing a task.

PR Close #36626
2020-04-29 14:28:26 -07:00
dff5129661 refactor(ngcc): notify master process about transformed files before writing (#36626)
With this commit, worker processes will notify the master process about
the transformed files they are about to write to disk before starting
writing them.

In a subsequent commit, this will be used to allow ngcc to recover when
a worker process crashes in the middle of processing a task.

PR Close #36626
2020-04-29 14:28:26 -07:00
e367593a26 refactor(ngcc): support running callback before writing transformed files (#36626)
This commit enhances the `CompileFn`, which is used to process each
entry-point, to support running a passed-in callback (and wait for it to
complete) before proceeding with writing the transformed files to disk.

This functionality is currently not used. In a subsequent commit, it
will be used for passing info from worker processes to the master
process that will allow ngcc to recover when a worker process crashes in
the middle of processing a task.

PR Close #36626
2020-04-29 14:28:26 -07:00
16039d837e refactor(ngcc): rename TaskQueue#markTaskCompleted() to markAsCompleted() (#36626)
Rename the `markTaskCompleted()` method to be consistent with the other
similar methods of `TaskQueue` (`markAsFailed()` and
`markAsUnprocessed()`).

PR Close #36626
2020-04-29 14:28:26 -07:00
4665c35453 feat(ngcc): support marking an in-progress task as unprocessed (#36626)
This commit adds support for stopping processing an in-progress task
and moving it back to the list of pending tasks.

In a subsequent commit, this will be used to allow ngcc to recover when
a worker process crashes in the middle of processing a task.

PR Close #36626
2020-04-29 14:28:25 -07:00
4c63241b34 fix(ngcc): do not run in parallel mode if there are less than 3 CPU cores (#36626)
Previously, ngcc would run in parallel mode (using the
`ClusterExecutor`) when there were at least 2 CPU cores (and all other
requirements where met). On systems with just 2 CPU cores, this meant
there would only be one worker process (since one CPU core is always
reserved for the master process). In these cases, the tasks would still
be processed serially (on the one worker process), but we would also pay
the overhead of communicating between the master and worker processes.

This commit fixes this by only running in parallel mode if there are
more than 2 CPU cores (i.e. at least 2 worker processes).

PR Close #36626
2020-04-29 14:28:25 -07:00
9aa778e843 refactor(ngcc): move "Compiling" log message before starting work on a task (#36626)
Previously, the "Compiling <entryPoint>" log message was printed before
starting to analyze and transform files, but after creating the
`EntryPointBundle` (which includes creating the TS program).

Since creating the `EntryPointBundle` involves some work, it is more
accurate to move the log message before creating the bundle.

PR Close #36626
2020-04-29 14:28:25 -07:00
62ba0acfb5 test(language-service): do not invalidate @angular/core (#36845)
Fix typo and add test cases for https://github.com/angular/angular/pull/36783

PR closes https://github.com/angular/vscode-ng-language-service/issues/713

PR Close #36845
2020-04-29 14:27:33 -07:00
52d2e46700 release: cut the v10.0.0-next.4 release 2020-04-29 14:07:45 -07:00
c89421bfa8 docs: release notes for the v9.1.4 release 2020-04-29 13:59:31 -07:00
cebd4fada7 build: use sh instead of exec for release scripts (#36862)
Previously the exec command was used, however the exec command would
exit the original calling script regardless of the whether exit was
called.  This caused the release script to always exit after the
pre-check phase.

PR Close #36862
2020-04-29 13:04:43 -07:00
3d82aa781d fix(core): attempt to recover from user errors during creation (#36381)
If there's an error during the first creation pass of a `TView`, the data structure may be corrupted which will cause framework assertion failures downstream which can mask the user's error. These changes add a new flag to the `TView` that indicates whether the first creation pass was successful, and if it wasn't we try re-create the `TView`.

Fixes #31221.

PR Close #36381
2020-04-29 08:36:42 -07:00
89c589085d fix(ngcc): recognize enum declarations emitted in JavaScript (#36550)
An enum declaration in TypeScript code will be emitted into JavaScript
as a regular variable declaration, with the enum members being declared
inside an IIFE. For ngcc to support interpreting such variable
declarations as enum declarations with its members, ngcc needs to
recognize the enum declaration emit structure and extract all member
from the statements in the IIFE.

This commit extends the `ConcreteDeclaration` structure in the
`ReflectionHost` abstraction to be able to capture the enum members
on a variable declaration, as a substitute for the original
`ts.EnumDeclaration` as it existed in TypeScript code. The static
interpreter has been extended to handle the extracted enum members
as it would have done for `ts.EnumDeclaration`.

Fixes #35584
Resolves FW-2069

PR Close #36550
2020-04-28 15:59:57 -07:00
a6a7e1bb99 build: enable platform-browser tests on Saucelabs (#36797)
Enables some passing `platform-browser` tests on Saucelabs. The reason they were disabled was an error log which doesn't actually fail the test run and has been there for a long time.

PR Close #36797
2020-04-28 15:10:27 -07:00
70dd27ffd8 fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.

In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.

This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.

In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.

The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.

There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.

Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.

Closes #36725

PR Close #36741
2020-04-28 12:22:40 -07:00
7bc5bcde34 test(compiler): check extracted translations for line endings (#36741)
When there are `CRLF` line endings some translations get different
message ids. This commit adds tests to track this in ViewEngine.

PR Close #36741
2020-04-28 12:22:40 -07:00
aa0dd0d5ff test(compiler): fix unwanted ! operators (#36741)
The `I18nComponent` was using `!` for some of its properties
because it had not initialized them. This is now resolved by explictly
marking them as optional.

PR Close #36741
2020-04-28 12:22:40 -07:00
e0aa39929b refactor(compiler): simplify tokenizer and parser results (#36741)
Move the creation of the results objects into the wrapper functions.
This makes it easier to reason about what the parser and lexer classes
are responsible for - you create a new object for each tokenization or
parsing activity and they hold the state of the activity.

PR Close #36741
2020-04-28 12:22:39 -07:00
4172707346 refactor(compiler): tighten type of TemplateParser._console (#36741)
This property can actually be `null` when called from the language-service.
This change allows us to remove the use of `!` to subvert the type system.

PR Close #36741
2020-04-28 12:22:39 -07:00
7c8c41353b build(docs-infra): upgrade cli command docs sources to c1cf42fd4 (#36832)
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](9459c8519...c1cf42fd4):

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

PR Close #36832
2020-04-28 11:52:52 -07:00
1d9375d115 ci: fix bad reference to head property in rebase-pr script (#36825)
Update rebase-pr script to properly reference a property on
the refs object using `target` rather than the previously
named `head`.

PR Close #36825
2020-04-28 09:13:35 -07:00
f27deea003 fix(core): handle synthetic props in Directive host bindings correctly (#35568)
Prior to this change, animations-related runtime logic assumed that the @HostBinding and @HostListener with synthetic (animations) props are used for Components only. However having @HostBinding and @HostListener with synthetic props on Directives is also supported by View Engine. This commit updates the logic to select correct renderer to execute instructions (current renderer for Directives and sub-component renderer for Components).

This PR resolves #35501.

PR Close #35568
2020-04-27 14:55:16 -07:00
00e6cb1d62 feat(router): allow CanLoad guard to return UrlTree (#36610)
A CanLoad guard returning UrlTree cancels current navigation and redirects.
This matches the behavior available to `CanActivate` guards added in #26521.

Note that this does not affect preloading. A `CanLoad` guard blocks any
preloading. That is, any route with a `CanLoad` guard is not preloaded
and the guards are not executed as part of preloading.

fixes #28306

PR Close #36610
2020-04-27 12:53:49 -07:00
cae2a893f2 docs: fix typo (#36786)
Correct typo in the router docs, changing "as your app growns" to "as your app grows". Previously the wrong spelling was used and this commit rectifies this.

PR Close #36786
2020-04-27 12:50:42 -07:00
b34fb04cbf build(docs-infra): upgrade cli command docs sources to 9459c8519 (#36808)
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](730657c86...9459c8519):

**Modified**
- help/analytics.json

PR Close #36808
2020-04-27 12:11:18 -07:00
2365bb89d7 build: migrate from gulp to ng-dev for running formatting (#36726)
Migrates away from gulp to ng-dev for running our formatter.
Additionally, provides a deprecation warning for any attempted
usage of the previous `gulp format:*` tasks.

PR Close #36726
2020-04-24 12:32:18 -07:00
7b5a0ba8c3 feat(dev-infra): create format tool in @angular/dev-infra-private (#36726)
Previously we used gulp to run our formatter, currently clang-format,
across our repository.  This new tool within ng-dev allows us to
migrate away from our gulp based solution as our gulp solution had
issue with memory pressure and would cause OOM errors with too large
of change sets.

PR Close #36726
2020-04-24 12:32:18 -07:00
ad8c4cdd75 revert: "feat(dev-infra): exposed new rule 'component_benchmark' via dev_infra (#36434)" (#36798)
This reverts commit b7f2a033df.

PR Close #36798
2020-04-24 11:03:38 -07:00
f5ff2068a4 revert: "build(dev-infra): update package.json and :npm_package (#36434)" (#36798)
This reverts commit d6f6cd0cb1.

PR Close #36798
2020-04-24 11:03:37 -07:00
90a2796a7e revert: "build(core): use dev-infra's component_benchmark to show PoC (#36434)" (#36798)
This reverts commit e6161ca307.

PR Close #36798
2020-04-24 11:03:37 -07:00
76190c71fc ci: migrate payload size tracking goldens to the golden directory (#36455)
This change is part of a larger effort to migrate all golden type
tracking files to a single location.  Additionally, this makes it
a bit easier to manage file ownership in pullapprove.

PR Close #36455
2020-04-24 09:05:11 -07:00
dd049caf0a fix(language-service): disable update the @angular/core module (#36783)
After the user edits the file `core.d.ts`, the symbol from the core module will be invalided, which only is created when init the language service. Then the language-service will crash.

PR Close #36783
2020-04-24 09:04:25 -07:00
bcd31cb857 build(docs-infra): upgrade cli command docs sources to 730657c86 (#36790)
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](56c648827...730657c86):

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

PR Close #36790
2020-04-24 09:03:56 -07:00
e6161ca307 build(core): use dev-infra's component_benchmark to show PoC (#36434)
This change demonstrates how to use the newly created
rule in one of our performance tests.

Future commits and PRs will migrate the remaining tests to this new bazel rule.

PR Close #36434
2020-04-23 13:31:53 -07:00
d6f6cd0cb1 build(dev-infra): update package.json and :npm_package (#36434)
* Set up dev-infra's :npm_package to also contain benchmarking suite
* Add benchmarking deps to dev-infra's package.json
* Add a bazel workspace to dev-infra's package.json. This is so that when a
  project wants to use dev-infra's code and macros, they can just import the
  macros from their node_modules instead of loading it separately

PR Close #36434
2020-04-23 13:31:53 -07:00
b7f2a033df feat(dev-infra): exposed new rule 'component_benchmark' via dev_infra (#36434)
* Move tools/brotli-cli, tools/browsers, tools/components,
  tools/ng_rollup_bundle, and modules/e2e_util to dev-infra/benchmarking
* Fix imports and references to moved folders and files
* Set up BUILD.bazel files for moved folders so they can be packaged with
  dev-infra's :npm_package

PR Close #36434
2020-04-23 13:31:53 -07:00
e37f2663c2 build: require a commit body in commit messages (#36632)
Enforces a requirement that all PR commit messages contain a body
of at least 100 characters.  This is meant to encourage commits
within the repo to be more descriptive of each change.

PR Close #36632
2020-04-23 12:18:56 -07:00
5e579c4dc9 fix(dev-infra): properly handle multiline regex of commit body (#36632)
Previously, the commit message body regex only matched the first line
of the body.  This change corrects the regex to match the entire line.

PR Close #36632
2020-04-23 12:18:56 -07:00
f0ec4ae941 ci: fix pullapprove incorrectly skipping fw-compiler as owner (#36661)
Currently, if changes are made to `compiler-cli/ngcc` and to other
compiler-related files, then only the `fw-ngcc` group is requested
for review. This is because the `not contains_any_globs` condition
will be false for `fw-compiler` and the group will never become active.

We fix this by removing the incorrect condition and filtering out ngcc
files before checking `contains_any_globs` in the primary fw-compiler
condition.

PR Close #36661
2020-04-23 12:17:10 -07:00
b80b43ddae ci: add codeowner group for migrations (#36661)
Adds a new codeowner group that is dedicated for changes
to the migrations stored in `packages/core/schematics`.

PR Close #36661
2020-04-23 12:17:10 -07:00
f0c570bd41 feat(dev-infra): pullapprove verify should handle files in conditions (#36661)
Currently, when verifying our pullapprove configuration, we don't
respect modifications to the set of files in a condition.

e.g. It's not possible to do the following:

```
contains_any_globs(files.exclude(...), [
```

This prevents us from having codeowner groups which match a directory,
but want to filter out specific sub directories. For example, `fw-core`
matches all files in the core package. We want to exclude the schematics
from that glob. Usually we do this by another exclude condition.

This has a *significant* downside though. It means that fw-core will not
be requested if a PR changes schematic code, _and_ actual fw-core code.

To support these conditions, the pullapprove verification tool is
refactored, so that it no longer uses Regular expressions for parsing,
but rather evaluates the code through a dynamic function. This is
possible since the conditions are written in simple Python that can
be run in NodeJS too (with small modifications/transformations).

PR Close #36661
2020-04-23 12:17:10 -07:00
e5d2853070 docs: correct ngSwitch definition (#35489)
PR Close #35489
2020-04-23 12:13:39 -07:00
152293d3cf test(router): fix router test failing on IE (#36742)
This was originally fixed in #35976, but one of the window.scrollY
assertions was missed. Also updated tests to use toBeGreater/LessThan
to improve failure messages.

PR Close #36742
2020-04-23 12:13:27 -04:00
ceb61d10c1 test(router): add canDeactivate test for forChild route (#36699)
This PR adds test case to cover a failure that was detected after
merging #36302. That commit will be reverted and will need a new PR that
does not cause this test to fail.

PR Close #36699
2020-04-23 12:08:44 -04:00
dd806b0d99 docs: add Annie Wang to contributors.json (#36612)
PR Close #36612
2020-04-23 12:08:09 -04:00
113c75dd27 refactor(localize): remove unused code (#36745)
PR Close #36745
2020-04-23 12:07:33 -04:00
b7acf07a70 refactor(localize): consolidate message/translation metadata (#36745)
PR Close #36745
2020-04-23 12:07:33 -04:00
519f2baff0 test(localize): tidy up translation parser tests (#36745)
There was a lot of duplication and multiline backtick
strings that made it hard to maintain.

PR Close #36745
2020-04-23 12:07:33 -04:00
3962908d36 refactor(localize): tighten up recognition of simple JSON translations (#36745)
PR Close #36745
2020-04-23 12:07:33 -04:00
afd2cbc3c4 refactor(localize): move source_file_utils.ts up (#36745)
This will allow the utilities in this file to be shared outside
`translate` code.

PR Close #36745
2020-04-23 12:07:33 -04:00
4275b3412f build: add AndrewKushnir to the fw-testing group (#36744)
This commit update the PullApprove config to add AndrewKushnir to the `fw-testing` group. The reason for this change is that I was involved into TestBed rewrite (for Ivy) and it belongs to the `fw-testing` group ownership.

PR Close #36744
2020-04-22 17:12:10 -04:00
1b3ee17888 build: move circular deps golden to a subfolder (#36630)
Moves the circular deps golden for packages into a subfolder of goldens,
`/goldens/circular-deps/` to more easily target the files for
ownership.

PR Close #36630
2020-04-22 17:11:20 -04:00
8306da5ce1 release(benchpress): bump version of benchpress to 0.2.0 (#36457)
Bumping the version of benchpress as a new version needs to be released
as part of the effort to set up more benchmarking accross the
angular/angular and angular/components repos.

PR Close #36457
2020-04-22 17:10:28 -04:00
75dff8a93a docs: improve startup nav, naming, and terminology (#35533)
PR Close #35533
2020-04-22 17:08:29 -04:00
fc1b557d98 build: run pre-check before publishing (#36527)
Previously, our process included running the pre-check script before
releasing.  With our new publishing process this was dropped.  This
change adds in automatically executing this check before publish for
both next and latest

PR Close #36527
2020-04-22 17:07:49 -04:00
47f98673c7 fix(localize): include legacy ids when describing messages (#36761)
Previously, we only displayed the new `$localize` id, which is not
currently what most people have in their translation files.
Until people migrate to the new message id system it is confusing
not to display the legacy ids.

PR Close #36761
2020-04-22 16:31:47 -04:00
781f5611d1 build: update to @bazel/bazelisk@^1.4.0 (#36729)
Upgrading @bazel/bazelisk to version 1.4.0 as this introduces the
bazel binary.  This prevents the need to have a `bazel` script defined
in package.json to point to `bazelisk`, instead it is just available
on install.

PR Close #36729
2020-04-22 16:31:17 -04:00
deea6da0e0 release: cut the v10.0.0-next.3 release 2020-04-22 11:59:44 -07:00
43622d32e4 docs: release notes for the v9.1.3 release 2020-04-22 11:56:11 -07:00
5db8d93fe5 build: fix the compare master and patch script output (#36749)
Currently the commit message and corresponding version are flipped, which makes it hard to review the changes. This commit updates the script to properly recognize the order of arguments.

PR Close #36749
2020-04-22 00:23:57 -04:00
535c249f3a build: update REQUIRED_BASE_SHA in merge script to commit-message script update commit (#36750)
Updating `REQUIRED_BASE_SHA` for master and patch branches to make sure PRs that we merge are rebased after `commit-message` validation script update (to make sure the `lint` CI job fails in case a PR contains commits with invalid commit messages).

PR Close #36750
2020-04-21 21:58:23 -04:00
942b986ef3 fix(core): properly identify modules affected by overrides in TestBed (#36649)
When module overrides (via `TestBed.overrideModule`) are present, it might affect all modules that import (even transitively) an overridden one. For all affected modules we need to recalculate their scopes for a given test run and restore original scopes at the end. Prior to this change, we were recalculating module scopes only for components that are used in a test, without taking into account module hierarchy. This commit updates Ivy TestBed logic to calculate all potentially affected modules are reset cached scopes information for them (so that scopes are recalculated as needed).

Resolves #36619.

PR Close #36649
2020-04-21 21:57:48 -04:00
acf6075ca9 fix(core): do not use unbound attributes as inputs to structural directives (#36441)
Prior to this commit unbound attributes were treated as possible inputs to structural directives. Since structural directives can only accepts inputs defined using microsyntax expression (e.g. `<div *dir="exp">`), such unbound attributes should not be considered as inputs. This commit aligns Ivy and View Engine behavior and avoids using unbound attributes as inputs to structural directives.

PR Close #36441
2020-04-21 13:30:25 -04:00
28995dba19 fix(core): missing-injectable migration should not migrate @NgModule classes (#36369)
Based on the migration guide, provided classes which don't have
either `@Injectable`, `@Directive`, `@Component` or `@Pipe` need
to be migrated.

This is not correct as provided classes with an `@NgModule` also
have a factory function that can be read by the r3 injector. It's
unclear in which cases the `@NgModule` decorator is used for
provided classes, but this scenario has been reported.

Either we fix this in the migration, or we make sure to report
this as unsupported in the Ivy compiler.

Fixes #35700.

PR Close #36369
2020-04-21 12:54:24 -04:00
f186c32245 docs: place download section in architecture to the top (#36565)
link is very deep down on architecture page this commit is part of a larger effort to standardise ownload sections on angular.io

This commit partially addresses #35459

PR Close #36565
2020-04-21 12:50:29 -04:00
d7c77cb175 refactor(docs-infra): refactors autoLinkCode (#36686)
PR Close #36686
2020-04-21 12:49:55 -04:00
51b09244ff fix(dev-infra): extract commit headers before checking commit message validity (#36733)
This commit fixes an issue where adding `fixup` commits was triggering a lint error. The problem was caused by the fact that we used the entire message body while checking whether `fixup` commit has a corresponding "parent" commit in a range. This issue was found after enforcing a check that exits the process if there is an invalid commit message found (4341743b4a).

PR Close #36733
2020-04-21 12:49:27 -04:00
458dc10ddc docs: place download section in accessibility to the top (#36561)
link is very deep down on acessibility page this commit is part of a larger effort to standardise ownload sections on angular.io

This commit partially addresses #35459

PR Close #36561
2020-04-20 16:20:26 -04:00
4341743b4a fix(dev-infra): exit non-zero if commit message validation failed (#36723)
Currently the `commit-message` validation script does not exit
with a non-zero exit code if the commit message validation failed.

This means that invalid commit messages are currently not
causing CI to be red. See: https://circleci.com/gh/angular/angular/686008

PR Close #36723
2020-04-20 14:28:17 -04:00
b5e92b9a5d Revert "fix(router): pass correct component to canDeactivate checks when using two or more sibling router-outlets (#36302)" (#36697)
This reverts commit 80e6c07d89.

PR Close #36697
2020-04-20 13:42:45 -04:00
28ff02b116 docs: remove version ^7.0.0 from LTS support (#36708)
Version 7.0.0 is under LTS until 18-4-2020 removed it from the table which showed it as LTS  and added to versions that are no longer under support.
PR Close #36708
2020-04-20 13:38:04 -04:00
f4ef8a92f8 docs: fix typo (#36665)
PR Close #36665
2020-04-20 13:36:40 -04:00
d7e9d8746a build: list feat commits in patch branch in relase review script (#36651)
PR Close #36651
2020-04-17 18:16:36 -04:00
351759906b refactor(compiler): remove unused CachedFileSystem (#36687)
This was only being used by ngcc but not any longer.

PR Close #36687
2020-04-17 16:33:48 -04:00
0c2ed4c3e5 fix(ngcc): do not use cached file-system (#36687)
The cached file-system was implemented to speed up ngcc
processing, but in reality most files are not accessed many times
and there is no noticeable degradation in speed by removing it.

Benchmarking `ngcc -l debug` for AIO on a local machine
gave a range of 196-236 seconds with the cache and 197-224
seconds without the cache.

Moreover, when running in parallel mode, ngcc has a separate
file cache for each process. This results in excess memory usage.
Notably the master process, which only does analysis of entry-points
holds on to up to 500Mb for AIO when using the cache compared to
only around 30Mb when not using the cache.

Finally, the file-system cache being incorrectly primed with file
contents before being processed has been the cause of a number
of bugs. For example https://github.com/angular/angular-cli/issues/16860#issuecomment-614694269.

PR Close #36687
2020-04-17 16:33:48 -04:00
37bfb14956 docs(dev-infra): document limitation in ts-circular-deps tool (#36659)
Adds documentation on discovered limitations in the ts-circular-deps
tool, so that we can reference it when needed.

PR Close #36659
2020-04-17 16:25:00 -04:00
81d23b33ef fix(core): pipes injecting viewProviders when used on a component host node (#36512)
The flag that determines whether something should be able to inject from `viewProviders` is opt-out and the pipes weren't opted out, resulting in them being able to see the viewProviders if they're placed on a component host node.

Fixes #36146.

PR Close #36512
2020-04-17 16:15:10 -04:00
bb150c2704 fixup!: build(docs-infra): Ensures that only member docs are linked (#36316)
PR Close #36316
2020-04-17 12:33:56 -04:00
46ff673192 fixup!: build(docs-infra): Ensures that only member docs are linked (#36316)
PR Close #36316
2020-04-17 12:33:55 -04:00
7842f73e8b fixup!: build(docs-infra): add _ to ignored ignoreGenericWords (#36316)
PR Close #36316
2020-04-17 12:33:55 -04:00
e5f9e3d018 build(docs-infra): add _ to ignored ignoreGenericWords (#36316)
Previously, when a document included `_`, the autoLinker will try to
generate a link, e.g from `core/ɵComponentDef._`. This commit adds it
to the ignored words to prevent that.

PR Close #36316
2020-04-17 12:33:55 -04:00
aebd5f9af6 build(docs-infra): Ensures that only member docs are linked (#36316)
This commit ensures that `member` docs are only linked if the linking
text contains `.`.

PR Close #36316
2020-04-17 12:33:55 -04:00
4fb034aeec build(docs-infra): fix autoLinkCode to ignore docs without a path (#36316)
Previously, the auto linker generated links without an `href` when the
API was private. This commit fixes this by making sure that the `path`
of the document is not empty.

Closes #36260

PR Close #36316
2020-04-17 12:33:55 -04:00
4da901f8c0 docs: add tony bove to about page (#36335)
PR Close #36335
2020-04-17 12:33:16 -04:00
39b043646b docs: add example to illustrate binding order differences in ivy (#36643)
Adds some examples and an explanation about the differences in binding order between Ivy and ViewEngine.

PR Close #36643
2020-04-17 12:29:58 -04:00
4480ba3e29 ci: remove reliance on Github API for CI setup (#36500)
Previously our CI during the setup process has made requests
to the Github API to determine the target branch and shas.
With this change, this information is now determined via git
commands using pipeline parameters from CircleCI.

PR Close #36500
2020-04-16 17:14:34 -04:00
5e79799b89 chore: update saucelabs README with some more details on local testing (#36625)
PR Close #36625
2020-04-16 16:36:50 -04:00
1fa1dd5aaa docs: getting started guide use pipe before introduction (#36584)
In "Getting started" guide pipes are not intoduced anywhere but are used in the guide.
Added refrence to pipes for better consistency in the tutorial.

Fixes #36375

PR Close #36584
2020-04-16 16:09:20 -04:00
8be0972836 fix(language-service): properly evaluate types in comparable expressions (#36529)
This commit fixes how the language service evaluates the compatibility
of types to work with arbitrary union types. As a result, compatibility
checks are now more strict and can catch similarities or differences
more clearly.

```
number|string == string|null  // OK
number|string == number       // OK
number|string == null         // not comparable
number == string              // not comparable
```

Using Ivy as a backend should provide these diagnoses for free, but we
can backfill them for now.

Closes https://github.com/angular/vscode-ng-language-service/issues/723

PR Close #36529
2020-04-16 16:07:47 -04:00
78840e59a7 docs: remove rob (#36285)
PR Close #36285
2020-04-16 16:07:07 -04:00
c332d4d916 refactor(ngcc): moved shared setup into a single function (#36637)
The `main.ts` and `worker.ts` had duplicate logic, which has now been
moved to a single function called `getSharedSetup()`.

PR Close #36637
2020-04-16 16:05:12 -04:00
bb944eecd6 refactor(ngcc): simplify cluster PackageJsonUpdater (#36637)
PR Close #36637
2020-04-16 16:05:12 -04:00
443f5eee85 refactor(ngcc): create new entry-point for cluster workers (#36637)
PR Close #36637
2020-04-16 16:05:12 -04:00
7e5e60b757 refactor(ngcc): move pathMapping processing to utils (#36637)
PR Close #36637
2020-04-16 16:05:12 -04:00
33df4b74da refactor(ngcc): move analyze and compile functions into their own files (#36637)
PR Close #36637
2020-04-16 16:05:12 -04:00
3c14e9612f refactor(ngcc): move command line option parsing to its own file (#36637)
PR Close #36637
2020-04-16 16:05:12 -04:00
cabf997933 fix(ngcc): display unlocker process output in sync mode (#36637)
The change in e041ac6f0d
to support sending unlocker process output to the main ngcc
console output prevents messages require that the main process
relinquishes the event-loop to allow the `stdout.on()` handler to
run.  This results in none of the messages being written when ngcc
is run in `--no-async` mode, and some messages failing to be
written if the main process is killed (e.g. ctrl-C).

It appears that the problem with Windows and detached processes
is known - see https://github.com/nodejs/node/issues/3596#issuecomment-250890218.
But in the meantime, this commit is a workaround, where non-Windows
`inherit` the main process `stdout` while on Windows it reverts
to the async handler approach, which is better than nothing.

PR Close #36637
2020-04-16 16:05:12 -04:00
2ed7146393 Revert "fix(ngcc): do not spawn unlocker processes on cluster workers (#36569)" (#36637)
This reverts commit 66effde9f3.

PR Close #36637
2020-04-16 16:05:12 -04:00
bfda7ca5bd docs(changelog): Add new line between changes (#36653)
PR Close #36653
2020-04-16 11:06:02 -07:00
305b059809 docs: refactor routing doc (#35566)
This rewrite changes headings to focus on user tasks rather than features,
verifies that content is up-to-date and complete, removes colloquial phrases,
adds prerequisites, and expands on a task-based section in the beginning
(a quick reference).

PR Close #35566
2020-04-16 10:36:01 -07:00
297b7da166 docs: add string-union type note (#35859)
PR Close #35859
2020-04-16 09:47:21 -07:00
6aac91743b docs: style edit (#35859)
PR Close #35859
2020-04-16 09:47:21 -07:00
f06d5f02b3 docs: update http guide (#35859)
PR Close #35859
2020-04-16 09:47:21 -07:00
4a9f0bebc3 fix(core): prevent unknown property check for AOT-compiled components (#36072)
Prior to this commit, the unknown property check was unnecessarily invoked for AOT-compiled components (for these components, the check happens at compile time). This commit updates the code to avoid unknown property verification for AOT-compiled components by checking whether schemas information is present (as a way to detect whether this is JIT or AOT compiled component).

Resolves #35945.

PR Close #36072
2020-04-16 09:45:16 -07:00
88b0985bad fix(compiler): avoid generating i18n attributes in plain form (#36422)
Prior to this change, there was a problem while matching template attributes, which mistakenly took i18n attributes (that might be present in attrs array after template ones) into account. This commit updates the logic to avoid template attribute matching logic from entering the i18n section and as a result this also allows generating proper i18n attributes sections instead of keeping these attribute in plain form (with their values) in attribute arrays.

PR Close #36422
2020-04-16 09:44:10 -07:00
1e3b8a1354 docs: remove unneeded code from universal example/guide (#36483)
In the past, server-side rendered apps needed to convert URLs used in
API requests to absolute when rendering on the server. Originally, this
was handled in the `universal` guide and corresponding example app by
modifying the `HeroService` to use `APP_BASE_HREF` to derive the
absolute URL.

In #28956, the guide was updated to show an improved method: Specifying
an `HttpInterceptor` that took care of converting the URLs to absolute.
That interceptor was only provided when rendering the app on the server.
By mistake, the corresponding example app was not updated along with the
guide.

Since `@nguniversal/*` v7.1.0, it is no longer necessary to convert the
URLs to absolute inside the app. This is handled in the `@nguniversal`
libs (see angular/universal#897).

This commit updates the example app to remove unnecessary code and
modifies the guide to mention the issue with absolute URLs, but explain
that developers only need to worry about it when not using one of the
`@nguniversal/*-engine` packages.

PR Close #36483
2020-04-16 09:43:42 -07:00
5a09753e07 docs: minor fixes/improvements in the universal guide (#36483)
PR Close #36483
2020-04-16 09:43:41 -07:00
02bfa9e0e0 test(docs-infra): add tests for universal docs example (#36483)
Previously, there were no tests for the `universal` docs example. This
meant that the project was not tested at all (not even ensuring that it
can be built successfully).

This commit adds e2e tests for the `universal` example (ported from
`toh-pt6` and cleaned up) and also verifies that the project can be
built successfully (including the server).

PR Close #36483
2020-04-16 09:43:41 -07:00
306ff3cd54 build(docs-infra): update @types/express-serve-static-core to avoid error in universal example (#36483)
Previously, building the `universal` example failed with:
```
node_modules/@types/express/index.d.ts(90,50): error TS2694: Namespace '".../@types/express-serve-static-core/index"' has no exported member 'Params'.
node_modules/@types/express/index.d.ts(90,64): error TS2694: Namespace '".../@types/express-serve-static-core/index"' has no exported member 'ParamsDictionary'.
```

This commit fixes the error by upgrading
`@types/express-serve-static-core` to a newer version.
See DefinitelyTyped/DefinitelyTyped#40905 for more details.

PR Close #36483
2020-04-16 09:43:41 -07:00
ec5c108b60 refactor(docs-infra): update universal example to match latest CLI (#36483)
Update the `universal` example (and related files) to match what would
be generated by the latest CLI.

Fixes #35289

PR Close #36483
2020-04-16 09:43:41 -07:00
4d9da9b0a1 fix(docs-infra): align universal example with toh-pt6 (#36483)
As mentioned in the `universal` guide, the `toh-pt6` examples is the
starting poitn for the `universal` example. However, the two examples
had become out-of-sync, because some fixes/changes were made to the
Tour-of-Heroes examples.

This commit ports these changes to the `universal` example.

PR Close #36483
2020-04-16 09:43:41 -07:00
3ce7c87cbd refactor(docs-infra): update main.ts in Tour-of-Heroes examples to match latest CLI (#36483)
Update the `main.ts` files in Tour-of-Heroes examples to match what
would be generated by the latest CLI.

PR Close #36483
2020-04-16 09:43:41 -07:00
061107c5f6 style(docs-infra): clean up Tour-of-Heroes examples (#36483)
I noticed these minor styling issues while aligning the `universal`
examples with the `toh-pt6` example (in a subsequent commit).

PR Close #36483
2020-04-16 09:43:41 -07:00
9f039d40c1 build(docs-infra): add missing build npm script for universal docs example ZIP archive (#36483)
Previously, the `package.json` template used in the ZIP archive of the
`universal` example that we offer for download missed the `build` npm
script.

This commit updates the template for the `universal` docs example to
include the `build` npm script.

NOTE:
The `build` npm script is already included in
`aio/tools/examples/shared/boilerplate/universal/package.json`, but it
was removed by the example zipper.

PR Close #36483
2020-04-16 09:43:41 -07:00
b1f1d3ffd2 fix(core): handle empty translations correctly (#36499)
In certain use-cases it's useful to have an ability to use empty strings as translations. Currently Ivy fails at runtime if empty string is used as a translation, since some parts of internal data structures are not created properly. This commit updates runtime i18n logic to handle empty translations and avoid unnecessary extra processing for such cases.

Fixes #36476.

PR Close #36499
2020-04-16 09:42:05 -07:00
03ff380e13 docs: add " in architecture page (#36564)
after alert is helpful " is missing added it to the architecture page

PR Close #36564
2020-04-16 09:41:32 -07:00
c6e5fc4fbe fix(common): format day-periods that cross midnight (#36611)
When formatting a time with the `b` or `B` format codes, the rendered
string was not correctly handling day periods that spanned midnight.
Instead the logic was falling back to the default case of `AM`.

Now the logic has been updated so that it matches times that are within
a day period that spans midnight, so it will now render the correct
output, such as `at night` in the case of English.

Applications that are using either `formatDate()` or `DatePipe` and any
of the `b` or `B` format codes will be affected by this change.

Fixes #36566

PR Close #36611
2020-04-16 09:40:40 -07:00
074266b896 release: cut the v10.0.0-next.2 release 2020-04-15 16:09:35 -07:00
c4dc642f99 docs: release notes for the v9.1.2 release 2020-04-15 16:04:09 -07:00
e041ac6f0d fix(ngcc): display output from the unlocker process on Windows (#36569)
On Windows, the output of a detached process (such as the unlocker
process used by `LockFileWithChildProcess`) is not shown in the parent
process' stdout.

This commit addresses this by piping the spawned process' stdin/stdout
and manually writing to the parent process' stdout.

PR Close #36569
2020-04-15 09:25:27 -07:00
66effde9f3 fix(ngcc): do not spawn unlocker processes on cluster workers (#36569)
The current ngcc lock-file strategy spawns a new process in order to
capture a potential `SIGINT` and remove the lock-file. For more
information see #35861.

Previously, this unlocker process was spawned as soon as the `LockFile`
was instantiated in order to have it available as soon as possible
(given that spawning a process is an asynchronous operation). Since the
`LockFile` was instantiated and passed to the `Executor`, this meant
that an unlocker process was spawned for each cluster worker, when
running ngcc in parallel mode. These processes were not needed, since
the `LockFile` was not used in cluster workers, but we still had to pay
the overhead of each process' own memory and V8 instance.
(NOTE: This overhead was small compared to the memory consumed by ngcc's
normal operations, but still unnecessary.)

This commit avoids the extra processes by only spawning an unlocker
process when running on the cluster master process and not on worker
processes.

PR Close #36569
2020-04-15 09:25:27 -07:00
663b768780 fix(ngcc): force ngcc to exit on error (#36622)
For some reason (possibly related to async/await promises)
the ngcc process is not exiting when spawned from the CLI
when there has been an error (such as when it timesout waiting
for a lockfile to become free).

Calling `process.exit()` directly fixes this.

Fixes #36616

PR Close #36622
2020-04-15 09:24:54 -07:00
0147de9044 build: fix circular deps failure (#36629)
With the large scale refactoring of the repo to the new version of clang-format, some import orders were changed.

Specifically the imports found in this range.

The file previously read:

import {TestBed} from './test_bed';
import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBedStatic, TestComponentRenderer, TestModuleMetadata} from './test_bed_common';
import {R3TestBedCompiler} from './r3_test_bed_compiler';
and now reads:

import {R3TestBedCompiler} from './r3_test_bed_compiler';
import {TestBed} from './test_bed';
import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBedStatic, TestComponentRenderer, TestModuleMetadata} from './test_bed_common';
This change in order cause the circular dependency to be entered earlier and changed the golden file for our circular deps discovery.

PR Close #36629
2020-04-14 13:56:55 -07:00
b010849102 build: update to latest version of yarn (#36464)
PR Close #36464
2020-04-14 12:47:30 -07:00
698b0288be build: reformat repo to new clang@1.4.0 (#36613)
PR Close #36613
2020-04-14 12:08:36 -07:00
5e80e7e216 refactor(language-service): clean up and exports and consolidate types (#36533)
PR Close #36533
2020-04-14 10:17:43 -07:00
d50cb30443 test: disable failing saucelabs tests (#36620)
PR Close #36620
2020-04-14 10:13:33 -07:00
29122c518b style: lint (#36580)
PR Close #36580
2020-04-14 10:12:59 -07:00
58e175318c build: update to rules_nodejs 1.6.0 (#36580)
Lots of bug fixes and stability fixes. Last 1.x release for rules_nodejs.

PR Close #36580
2020-04-14 10:12:59 -07:00
f88e63519a docs: edit to setup-local (#36168)
PR Close #36168
2020-04-13 17:33:35 -07:00
0cc53fb398 fix(upgrade): update $locationShim to handle Location changes before initialization (#36498)
Updates the $locationShim to receive the most recent Location change
made, even if it happened before initialize() is called. This is
important when AngularJS bootstrapping is deferred and there is a delay
between when $locationShim is constructed and when it is initialized.
With this change, the $locationShim will correctly reflect any redirects
that occurred between construction and initialization.

Closes #36492

PR Close #36498
2020-04-13 17:33:00 -07:00
713bce19f4 docs: move ng-conf 2020 to the already presented section (#36413)
PR Close #36413
2020-04-13 08:20:03 -07:00
d972821889 fix(docs-infra): contribute page not visible correctly on mobile devices (#36573)
on mobile devices screen size < 600px the contribute page is not visible in correct form changed styles to make it visible correctly

PR Close #36573
2020-04-13 08:19:01 -07:00
2d16b4711e fix(docs-infra): fix About page button text being truncated on small screens (#36576)
On small screens (e.g. on mobile), the text on some of the buttons in
the About page was truncated. Changed the text size, margin and
padding so that the the whole text is visible on such screens (320px to
480px).

PR Close #36576
2020-04-13 08:18:11 -07:00
9181b73e5a docs: fix typo in Tests guide (#36592)
PR Close #36592
2020-04-13 08:17:27 -07:00
5737e65700 docs(zone.js): fix typos in NgZone guide code example (#36597)
Fixes #36594

PR Close #36597
2020-04-13 08:16:59 -07:00
ca677481a2 fix(core): undecorated-classes-with-decorated-fields migration should avoid error if base class has no value declaration (#36543)
The undecorated-classes-with-decorated-fields migration relies on
the type checker to resolve base classes of individual classes.

It could happen that resolved base classes have no value declaration.
e.g. if they are declared through an interface in the default types.
Currently the migration will throw in such situations because it assumes
that `ts.Symbol#valueDeclaration` is always present. This is not the
case, but we don't get good type-checking here due to a bug in the
TypeScript types. See:
https://github.com/microsoft/TypeScript/issues/24706.

Fixes #36522.

PR Close #36543
2020-04-10 13:53:15 -07:00
6ab43d7335 fix(ngcc): correctly detect external files from nested node_modules/ (#36559)
Previously, when we needed to detect whether a file is external to a
package, we only checked whether the relative path to the file from the
package's root started with `..`. This would detect external imports
when the packages were siblings (e.g. peer dependencies or hoisted to
the top of `node_modules/` by the package manager), but would fail to
detect imports from packages located in nested `node_modules/` as
external. For example, importing `node_modules/foo/node_modules/bar`
from a file in `node_modules/foo/` would be considered internal to the
`foo` package.

This could result in processing/analyzing more files than necessary.
More importantly it could lead to errors due to trying to analyze
non-Angular packages that were direct dependencies of Angular packages.

This commit fixes it by also verifying that the relative path to a file
does not start with `node_modules/`.

Jira issue: [FW-2068](https://angular-team.atlassian.net/browse/FW-2068)

Fixes #36526

PR Close #36559
2020-04-10 09:10:26 -07:00
fee316161d build: update REQUIRED_BASE_SHA in merge script to clang 1.4.0 upgrade commit (#36547)
Updating `REQUIRED_BASE_SHA` for master and patch branches to make sure PRs that we merge are rebased after clang 1.4.0 upgrade.

PR Close #36547
2020-04-09 16:00:31 -07:00
2e4244d521 fix(docs-infra): fix elements example when used with ES5 (#36536)
Previously, the `elements` docs example only worked in browsers that
natively supported Custom Elements and ES2015 modules. Furthermore, it
didn't work on StackBlitz, because StackBlitz ignores the specified
`target` in `tsconfig.json` and uses the UMD bundles (i.e. ES5 code)
even on browsers that do support ES2015.
(NOTE: In the past, this was not a problem, because we explicitly did
not provide a StackBlitz example. This has changed in #36067.)

This commit ensures the example works on all browsers and also on
StackBlitz by providing the necessary Custom Elements polyfills.

Fixes #36532

PR Close #36536
2020-04-09 13:35:27 -07:00
3bedfdac9d perf(ngcc): only load if it is needed (#36486)
PR Close #36486
2020-04-09 11:33:28 -07:00
ec0ce6005a perf(ngcc): reduce the size of the entry-point manifest file (#36486)
The base path for package and entry-points is known so there is
no need to store these in the file. Also this commit avoids storing
empty arrays unnecessarily.

PR Close #36486
2020-04-09 11:33:28 -07:00
a185efbd60 perf(ngcc): read dependencies from entry-point manifest (#36486)
Previously, even if an entry-point did not need to be processed,
ngcc would always parse the files of the entry-point to compute
its dependencies. This can take a lot of time for large node_modules.

Now these dependencies are cached in the entry-point manifest,
and read from there rather than computing them every time.

See https://github.com/angular/angular/issues/36414\#issuecomment-608401834
FW-2047

PR Close #36486
2020-04-09 11:33:28 -07:00
4aa4e6fd03 fix(compiler): handle type references to namespaced symbols correctly (#36106)
When the compiler needs to convert a type reference to a value
expression, it may encounter a type that refers to a namespaced symbol.
Such namespaces need to be handled specially as there's various forms
available. Consider a namespace named "ns":

1. One can refer to a namespace by itself: `ns`. A namespace is only
   allowed to be used in a type position if it has been merged with a
   class, but even if this is the case it may not be possible to convert
   that type into a value expression depending on the import form. More
   on this later (case a below)
2. One can refer to a type within the namespace: `ns.Foo`. An import
   needs to be generated to `ns`, from which the `Foo` property can then
   be read.
3. One can refer to a type in a nested namespace within `ns`:
   `ns.Foo.Bar` and possibly even deeper nested. The value
   representation is similar to case 2, but includes additional property
   accesses.

The exact strategy of how to deal with these cases depends on the type
of import used. There's two flavors available:

a. A namespaced import like `import * as ns from 'ns';` that creates
   a local namespace that is irrelevant to the import that needs to be
   generated (as said import would be used instead of the original
   import).

   If the local namespace "ns" itself is referred to in a type position,
   it is invalid to convert it into a value expression. Some JavaScript
   libraries publish a value as default export using `export = MyClass;`
   syntax, however it is illegal to refer to that value using "ns".
   Consequently, such usage in a type position *must* be accompanied by
   an `@Inject` decorator to provide an explicit token.

b. An explicit namespace declaration within a module, that can be
   imported using a named import like `import {ns} from 'ns';` where the
   "ns" module declares a namespace using `declare namespace ns {}`.
   In this case, it's the namespace itself that needs to be imported,
   after which any qualified references into the namespace are converted
   into property accesses.

Before this change, support for namespaces in the type-to-value
conversion was limited and only worked  correctly for a single qualified
name using a namespace import (case 2a). All other cases were either
producing incorrect code or would crash the compiler (case 1a).

Crashing the compiler is not desirable as it does not indicate where
the issue is. Moreover, the result of a type-to-value conversion is
irrelevant when an explicit injection token is provided using `@Inject`,
so referring to a namespace in a type position (case 1) could still be
valid.

This commit introduces logic to the type-to-value conversion to be able
to properly deal with all type references to namespaced symbols.

Fixes #36006
Resolves FW-1995

PR Close #36106
2020-04-09 11:32:21 -07:00
078b0be4dc fix(common): locales/global/*.js are not ES5 compliant (#36342)
Although this code has been part of Angular 9.x I only noticed this
error when upgrading to Angular 9.1.x because historically the source
locale data was not injected when localizing, but as of
angular/angular-cli#16394 (9.1.0) it is now included. This tipped me off
that my other bundles were not being built properly, and this change
allows me to build a valid ES5 bundle (I have also added a verification
step to my build pipeline to alert me if this error appears again in any
of my bundles).

I found the `locales/global/*.js` file paths being referenced by the
`I18nOptions` in
@angular-devkit/build-angular/src/utils/i18n-options.ts,
and following that it looks like it is actually loaded and used in
@angular-devkit/build-angular/src/utils/process-bundle.ts. I saw the
function `terserMangle` does appear that it is likely aware of the build
being ES5, but I'm not sure why this is not producing a valid ES5
bundle.

This change updates `tools/gulp-tasks/cldr/extract.js` to produce ES5
compliant `locales/global/*.js` and that fixes my issue. However, I am
not sure if @angular-devkit/build-angular should be modified to produce
a valid ES5 bundle instead or if the files could be TypeScript rather
than JavaScript files.

A test that a valid ES5 bundle is produced would be helpful, and I hope
this is reproducible and not some issue with my config.

PR Close #36342
2020-04-09 11:30:32 -07:00
13ae2d7271 style: format forms validators to fix lint error (#36546)
PR Close #36546
2020-04-09 11:18:22 -07:00
99b93e55cb docs(forms): clarify the description of minLength and maxLength (#36297)
Previously, it was not clear that the `minLength` and `maxLength` validators
can only be used with objects that contain a `length` property. This commit
clarifies this.

PR Close #36297
2020-04-09 10:31:03 -07:00
80e6c07d89 fix(router): pass correct component to canDeactivate checks when using two or more sibling router-outlets (#36302)
fixes #34614

There's an edge case where if I use two (or more) sibling <router-outlet>s in two (or more) child routes where their parent route doesn't have a component then preactivation will trigger all canDeactivate checks with the same component because it will use wrong OutletContext.

PR Close #36302
2020-04-09 10:09:43 -07:00
34aa5570ed fix(dev-infra): fix commit message validation in git worktrees (#36507)
Previously, the `pre-commit-validate` command (used in the `commit-msg`
git hook) assumed that the commit message was stored in
`.git/COMMIT_EDITMSG` file. This is usually true, but not when using
[git worktrees](https://git-scm.com/docs/git-worktree), where `.git` is
a file containing the path to the actual git directory.

This commit fixes it by taking advantage of the fact that git passes the
actual path of the file holding the commit message to the `commit-msg`
hook and husky exposes the arguments passed by git as
`$HUSKY_GIT_PARAMS`.

NOTE:
We cannot use the environment variable directly in the `commit-msg` hook
command, because environment variables need to be referenced differently
on Windows (`%VAR_NAME%`) vs macOS/Linux (`$VAR_NAME`). Instead, we pass
the name of the environment variable and the validation script reads the
variable's value off of `process.env`.

PR Close #36507
2020-04-09 09:46:18 -07:00
e526f74dfd refactor(compiler): create a new root BindingScope for each template (#36362)
Previously we had a singleton `ROOT_SCOPE` object, from
which all `BindingScope`s derived. But this caused ngcc to
produce non-deterministic output when running multiple workers
in parallel, since each process had its own `ROOT_SCOPE`.

In reality there is no need for `BindingScope` reference names
to be unique across an entire application (or in the case of ngcc
across all the libraries). Instead we just need uniqueness within
a template.

This commit changes the compiler to create a new root `BindingScope`
each time it compiles a component's template.

Resolves #35180

PR Close #36362
2020-04-09 09:44:56 -07:00
9e78f55c32 style: typescript lint fix (#36531)
PR Close #36531
2020-04-09 00:59:21 +00:00
f1731d807e Revert "refactor(bazel): use runfiles helper in ts-api-guardian (#36471)" (#36531)
This reverts commit 92c4f3d508.

PR Close #36531
2020-04-09 00:59:21 +00:00
92c4f3d508 refactor(bazel): use runfiles helper in ts-api-guardian (#36471)
Pre-fractor for future rules_nodejs release when require.resolve patches are removed.

PR Close #36471
2020-04-08 15:57:52 -07:00
e92fce1c27 fix(language-service): remove circular dependency instance (#36463)
PR Close #36463
2020-04-08 15:29:09 -07:00
83a9159063 style(compiler): reformat of codebase with new clang-format version (#36520)
This commit reformats the packages/compiler tree using the new version of
clang-format.

PR Close #36520
2020-04-08 14:51:08 -07:00
0a69a2832b style(compiler-cli): reformat of codebase with new clang-format version (#36520)
This commit reformats the packages/compiler-cli tree using the new version
of clang-format.

PR Close #36520
2020-04-08 14:51:08 -07:00
717df13207 fix(ngcc): do not warn if paths mapping does not exist (#36525)
In cc4b813e75 the `getBasePaths()`
function was changed to log a warning if a `basePath()` computed from
the `paths` mappings did not exist. It turns out this is a common and
accepted scenario, so we should not log warnings in this case.

Fixes #36518

PR Close #36525
2020-04-08 14:29:57 -07:00
b40b5576df release: cut the v10.0.0-next.1 release 2020-04-08 12:28:12 -07:00
03f2f1ae47 build(bazel): fix runfiles resolve in karma-saucelabs.js after $location => $rootpath cleanup (#36511)
This wasn't caught by CI on the PR as this binary is only run once daily via a monitor job.

PR Close #36511
2020-04-08 12:13:27 -07:00
a8978ebf8e build: ts-circular-deps tool should normalize golden (#36505)
Currently the golden output of the circular-deps tool is purely
based on the order of source files passed to the tool, and on the
amount of imports inside source files.

This is actually resulting in deterministic output as running
the tool multiple times without any changes to source files,
results in the same output.

Though it seems like the tool is too strict and we can avoid
unnecessary golden changes if:

1. A source file that is part of a cycle is imported earlier (in terms
of how the analyzer visits them). This could result in the cycle path
starting with a different source file.

2. Source files which are not part of a cycle are imported earlier
(in terms of how the analyzer visits them). This could result in moved
items in the golden if re-approved (even though the cycles remain the same)

To fix this, we normalize the cycle path array that serves as
serializable data structure for the text-based goldens. Since
the paths represents a cycle, the path can be shifted in a
deterministic way so that cycles don't change unnecessarily
in the golden, and to simplify comparison of cycles.

Additionally, we sort the cycles in a deterministic way so
that the golden doesn't change unnecessarily (as explained above).

PR Close #36505
2020-04-08 12:12:58 -07:00
7d7b59efa5 docs: update the Support policy and schedule (#35390)
PR Close #35359

PR Close #35390
2020-04-08 12:12:32 -07:00
4cf89d4bd7 docs: replace browserslist with .browserslistrc (#36504)
In version 10, this file has been changed.

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

PR Close #36504
2020-04-08 12:12:03 -07:00
d47b318fee build: remove fullTemplateTypeCheck from aio tsconfig (#36502)
`fullTemplateTypeCheck` is no longer required since we now use `strictTemplates` which is a superset of the former option.

Follow-up on: 04f61c0c3e (r38354112)

PR Close #36502
2020-04-08 12:11:28 -07:00
e485236502 test(language-service): Inline test cases in parsing-cases.ts (#36495)
This commit removes individual components from parsing-cases.ts and
colocate them with the actual tests. This makes the tests more readable.

PR Close #36495
2020-04-08 12:11:04 -07:00
41667de778 fix(zone.js): add issue numbers of @types/jasmine to the test cases (#34625)
Some cases will still need to use `spy as any` cast, because `@types/jasmine` have some issues,
1. The issue jasmine doesn't handle optional method properties, https://github.com/DefinitelyTyped/DefinitelyTyped/issues/43486
2. The issue jasmine doesn't handle overload method correctly, https://github.com/DefinitelyTyped/DefinitelyTyped/issues/42455

PR Close #34625
2020-04-08 12:10:34 -07:00
ef4736d052 build: update jasmine to 3.5 (#34625)
1. update jasmine to 3.5
2. update @types/jasmine to 3.5
3. update @types/jasminewd2 to 2.0.8

Also fix several cases, the new jasmine 3 will help to create test cases correctly,
such as in the `jasmine 2.x` version, the following case will pass

```
expect(1 == 2);
```

But in jsamine 3, the case will need to be

```
expect(1 == 2).toBeTrue();
```

PR Close #34625
2020-04-08 12:10:34 -07:00
db4a448439 release: cut the v10.0.0-next.0 release 2020-04-08 11:08:01 -07:00
7549c65502 build: update matching regex for bazel stamping (#36523)
Previously, the bazel stamping regex only matched on versions
0-9 for major and minor numbers, this update allows for matching
on any number for major, minor or patch.

PR Close #36523
2020-04-08 11:04:08 -07:00
1beccc1a6c docs: release notes for the v9.1.1 release 2020-04-07 16:37:55 -07:00
0075017b43 docs: update reactive forms page (#35969)
PR Close #35969
2020-04-07 15:24:17 -07:00
4374931b0e fix(zone.js): zone.js patch jest should handle done correctly (#36022)
`zone.js` supports jest `test.each()` methods, but it
introduces a bug, which is the `done()` function will not be handled correctly.

```
it('should work with done', done => {
  // done will be undefined.
});
```

The reason is the logic of monkey patching `test` method is different from `jasmine` patch

// jasmine patch
```
return testBody.length === 0
   ? () => testProxyZone.run(testBody, null)
   : done => testProxyZone.run(testBody, null, [done]);
```

// jest patch
```
 return function(...args) {
   return testProxyZone.run(testBody, null, args);
 };
```

the purpose of this change is to handle the following cases.

```
test.each([1, 2])('test.each', (arg1, arg2) => {
  expect(arg1).toBe(1);
  expect(arg2).toBe(2);
});
```

so in jest, it is a little complex, because the `testBody`'s parameter may be bigger than 1, so the
logic in `jasmine`

```
return testBody.length === 0
   ? () => testProxyZone.run(testBody, null)
   : done => testProxyZone.run(testBody, null, [done]);
```
will not work for `test.each` in jest.

So in this PR, I created a dynamic `Function` to return the correct length of paramters (which is required by jest core), to handle
1. normal `test` with or without `done`.
2. each with parameters with or without done.

PR Close #36022
2020-04-07 15:22:16 -07:00
64022f51d4 fix(compiler): resolve enum values in binary operations (#36461)
During static evaluation of expressions, the partial evaluator
may come across a binary + operator for which it needs to
evaluate its operands. Any of these operands may be a reference
to an enum member, in which case the enum member's value needs
to be used as literal value, not the enum member reference
itself. This commit fixes the behavior by resolving an
`EnumValue` when used as a literal value.

Fixes #35584
Resolves FW-1951

PR Close #36461
2020-04-07 15:21:51 -07:00
f9f6e2e1b3 style(compiler): reformat partial evaluator source tree (#36461)
PR Close #36461
2020-04-07 15:21:51 -07:00
aecf9de738 fix(ngcc): correctly identify relative Windows-style import paths (#36372)
Previously, `isRelativePath()` assumed paths are *nix-style. This caused
Windows-style paths (such as `C:\foo\some-package\some-file.js`) to not
be recognized as "relative" imports.

This commit fixes this by using the OS-agnostic `isRooted()` helper and
also accounting for both styles of path delimiters: `/` and `\`

PR Close #36372
2020-04-07 15:21:27 -07:00
81195a238b fix(language-service): use the HtmlAst to get the span of HTML tag (#36371)
The HTML tag may include `-` (e.g. `app-root`), so use the `HtmlAst` to get the span.

PR Close #36371
2020-04-07 15:10:33 -07:00
96a3de6364 style(docs-infra): removed extra , from _resources.scss file (#35935)
there was a typo in _resourcess.scss file there was an extra comma added some spaces too that were needed for proper styling of the code

PR Close #35935
2020-04-07 15:08:57 -07:00
00027130ea fix(docs-infra): fix resources page tabs text which is not visible on small screens (#35935)
on small mobile screens the top tab bar contains text which was not visible on small screens changed text size, margin and padding so that the text could be contained in these screens (320px to 480px)

PR Close #35935
2020-04-07 15:08:57 -07:00
4a18428de6 docs(forms): Remove unnecessary repeating periods (#36474)
PR Close #36474
2020-04-07 11:35:43 -07:00
7f28845f58 test(language-service): remove ng-for-cases.ts (#36470)
This commit removes ng-for-cases.ts and moves all test cases to
inline expressions in TEST_TEMPLATE.

PR Close #36470
2020-04-07 11:34:38 -07:00
1dd0b6cc18 test(language-service): remove ng-if-cases.ts (#36470)
This commit removes ng-if-cases.ts and moves all test cases to inline
expressions in TEST_TEMPLATE.

PR Close #36470
2020-04-07 11:34:38 -07:00
e0415dbf16 fix(router): state data missing in routerLink (#36462)
fixes #33173 - router state data is missing on routerLink when used
with non-anchor elements.

PR Close #36462
2020-04-07 11:31:25 -07:00
95fc3d4c5c fix(core): ngOnDestroy on multi providers called with incorrect context (#35840)
Currently destroy hooks are stored in memory as `[1, hook, 5, hook]` where
the numbers represent the index at which to find the context and `hook` is
the function to be invoked. This breaks down for `multi` providers,
because the value at the index will be an array of providers, resulting in
the hook being invoked with an array of all the multi provider values,
rather than the provider that was destroyed. In ViewEngine `ngOnDestroy`
wasn't being called for `multi` providers at all.

These changes fix the issue by changing the structure of the destroy hooks to `[1, hook, 5, [0, hook, 3, hook]]` where the indexes inside the inner array point to the provider inside of the multi provider array. Note that this is slightly different from the original design which called for the structure to be `[1, hook, 5, [hook, hook]`, because in the process of implementing it, I realized that we wouldn't get passing the correct context if only some of the `multi` providers have `ngOnDestroy` and others don't.

I've run the newly-added `view_destroy_hooks` benchmark against these changes and compared it to master. The difference seems to be insignificant (between 1% and 2% slower).

Fixes #35231.

PR Close #35840
2020-04-07 10:31:41 -07:00
e145fa13b1 test(language-service): delete expression-cases.ts (#36468)
This commit deletes `expression-cases.ts` and moves the test cases to
inline expressions in TEST_TEMPLATE.

PR Close #36468
2020-04-07 10:20:27 -07:00
5fa7b8ba56 fix(ngcc): detect non-emitted, non-imported TypeScript helpers (#36418)
When TypeScript downlevels ES2015+ code to ES5, it uses some helper
functions to emulate some ES2015+ features, such as spread syntax. The
TypeScript compiler can be configured to emit these helpers into the
transpiled code (which is controlled by the `noEmitHelpers` option -
false by default). It can also be configured to import these helpers
from the `tslib` module (which is controlled by the `importHelpers`
option - false by default).

While most of the time the helpers will be either emitted or imported,
it is possible that one configures their app to neither emit nor import
them. In that case, the helpers could, for example, be made available on
the global object. This is what `@nativescript/angular`
v9.0.0-next-2019-11-12-155500-01 does. See, for example, [common.js][1].

Ngcc must be able to detect and statically evaluate these helpers.
Previously, it was only able to detect emitted or imported helpers.

This commit adds support for detecting these helpers if they are neither
emitted nor imported. It does this by checking identifiers for which no
declaration (either concrete or inline) can be found against a list of
known TypeScript helper function names.

[1]: https://unpkg.com/browse/@nativescript/angular@9.0.0-next-2019-11-12-155500-01/common.js

PR Close #36418
2020-04-07 10:19:22 -07:00
2c7d366c82 refactor(language-service): provide service for attribute binding type (#36301)
This commit refactors the process for determining the type of an Angular
attribute to be use a function that takes an attribute name and returns
the Angular attribute kind and name, rather than requiring the user to
query match the attribute name with the regex and query the matching
array.

This refactor prepares for a future change that will improve the
experience of completing attributes in `()`, `[]`, or `[()]` contexts.

PR Close #36301
2020-04-07 10:18:32 -07:00
2dd6f25647 ci: manually set available resources for bazel on windows CI (#36458)
PR Close #36458
2020-04-07 10:12:29 -07:00
d2623f13d9 style(zone.js): fix lint errors after clang update (#36487)
Recent ZoneJS-related commit (416c786774) update the `promise.ts` file, but it looks like original PR was not rebased after clang update. As a result, the `lint` CircleCI job started to fail in master after merging that PR (https://github.com/angular/angular/pull/36311). This commit updates the format of the `promise.ts` script according to the new clang rules.

PR Close #36487
2020-04-07 10:10:34 -07:00
7d0af179e3 style(forms): reformat of the forms package after clang update (#36466)
PR Close #36466
2020-04-07 09:47:09 -07:00
416c786774 fix(zone.js): should not try to patch fetch if it is not writable (#36311)
Close #36142

In Firefox extensions, the `window.fetch` is not configurable, that means

```
const desc = Object.getOwnPropertyDescriptor(window, 'fetch');
desc.writable === false;
```

So in this case, we should not try to patch `fetch`, otherwise, it will
throw error ('fetch is ReadOnly`)

PR Close #36311
2020-04-06 15:34:33 -07:00
93302b7fb8 build: update to latest version of husky (#36459)
PR Close #36459
2020-04-06 15:33:26 -07:00
eb8c6c7eff test(language-service): Move pipe tests to TEST_TEMPLATE (#36407)
This commit simplifies the completion tests for pipes by moving them to TEST_TEMPLATE.

PR Close #36407
2020-04-06 15:32:33 -07:00
8660806ddc build(docs-infra): renamed e2e property of example-config.json to tests (#36143)
Each docs example has an `example-config.json` configuration file. Among
other things, this file can be used to specify what commands to run in
order to test the example. (If not specified, the `run-example-e2e.js`
script will run a default `yarn e2e` command.)

Previously, the property specifying the test commands was called `e2e`.
This is because in the past only e2e tests were run for docs examples.
Since recently, some examples may specify commands for other types of
tests (such as unit tests). Therefore, calling the property that holds
the list of test commands `e2e` no longer makes sense and can be
misleading to people looking at the configuration files.

This commit renamed the property to the more generic `tests`. In the
future, the `run-example-e2e.js` script (and corresponding npm script)
should be renamed and refactored to also avoid giving the impression
that only e2e tests are run.

Discussed in:
https://github.com/angular/angular/pull/36143#discussion_r395148379

PR Close #36143
2020-04-06 15:31:07 -07:00
4c5e085c93 build(docs-infra): update docs examples package.json templates wrt core-js (#36143)
The `core-js` dependency is no longer included in `package.json` for
`cli`-type examples, but only for the `systemjs` ones. This commit
updates the `package.json` templates to reflect that (and also updates
the `npm-packages` guide accordingly).

PR Close #36143
2020-04-06 15:31:07 -07:00
d707124fd9 test(docs-infra): fix unit tests and run them for specific docs examples on CI (#36143)
Previously, only e2e tests were run for docs examples on CI. As a
result, unit tests (which are included in the zipped archives we provide
for users to download and play with the examples locally) were often
outdated and broken.

This commit configures specific docs examples that have meaningful unit
tests to run them on CI (via the `run-example-e2e.js` script). Where
necessary, the unit tests are fixed to ensure they pass and reflect the
changes in the corresponding component/service.
This commit also removes some auto-generated unit tests that are not
meaningful (e.g. make trivial assertions, such that a component instance
is truthy) and are often broken anyway (e.g. because the corresponding
component has been changed in ways that make the tests fail).

PR Close #36143
2020-04-06 15:31:07 -07:00
aece3669e5 build(docs-infra): switch docs examples to Ivy (#36143)
The docs examples are switched to Ivy. On CI, the tests are run with
both Ivy and ViewEngine.

Partially addresses:
[FW-1609](https://angular-team.atlassian.net/browse/FW-1609)

PR Close #36143
2020-04-06 15:31:07 -07:00
09c84169d5 docs: fix broken guide link (tutorial/index --> tutorial) (#36453)
Replace broken link (`tutorial/index`) with `tutorial`.

PR Close #36453
2020-04-06 13:56:00 -07:00
d43c30688a fix(core): avoid migration error when non-existent symbol is imported (#36367)
In rare cases a project with configured `rootDirs` that has imports to
non-existent identifiers could fail in the migration.

This happens because based on the application code, the migration could
end up trying to resolve the `ts.Symbol` of such non-existent
identifiers. This isn't a problem usually, but due to a upstream bug
in the TypeScript compiler, a runtime error is thrown.

This is because TypeScript is unable to compute a relative path from the
originating source file to the imported source file which _should_
provide the non-existent identifier. An issue for this has been reported
upstream: https://github.com/microsoft/TypeScript/issues/37731. The
issue only surfaces since our migrations don't provide an absolute base
path that is used for resolving the root directories.

To fix this, we ensure that we never use relative paths when parsing
tsconfig files. More details can be found in the TS issue.

Fixes #36346.

PR Close #36367
2020-04-06 13:21:54 -07:00
ee70a18a75 fix(ngcc): don't crash on cyclic source-map references (#36452)
The source-map flattening was throwing an error when there
is a cyclic dependency between source files and source-maps.
The error was either a custom one describing the cycle, or a
"Maximum call stack size exceeded" one.

Now this is handled more leniently, resulting in a partially loaded
source file (or source-map) and a warning logged.

Fixes #35727
Fixes #35757
Fixes https://github.com/angular/angular-cli/issues/17106
Fixes https://github.com/angular/angular-cli/issues/17115

PR Close #36452
2020-04-06 13:19:53 -07:00
76a8cd57ae fix(ngcc): add process title (#36448)
Add process.title, so it's clearly in the task manager when ngcc is running

See: https://github.com/angular/angular/issues/36414#issuecomment-609644282

PR Close #36448
2020-04-06 13:19:17 -07:00
4c7f89ff6d ci: exclude ngcc directory from fw-compiler pull-approve rule (#35933)
ngcc has its own pull-approve group

PR Close #35933
2020-04-06 13:16:37 -07:00
f9fb8338f5 fix(ngcc): support ignoring deep-imports via package config (#36423)
Recently we added support for ignoring specified deep-import
warnings by providing sets of regular expressions within the
`ngcc.config.js` file. But this was only working for the project
level configuration.

This commit fixes ngcc so that it will also read these regular
expressions from package level configuration too.

Fixes #35750

PR Close #36423
2020-04-06 11:32:09 -07:00
6b3aa60446 fix(ngcc): support simple browser property in entry-points (#36396)
The `browser` package.json property is now supported to the same
level as `main` - i.e. it is sniffed for UMD, ESM5 and CommonJS.

The `browser` property can also contain an object with file overrides
but this is not supported by ngcc.

Fixes #36062

PR Close #36396
2020-04-06 11:31:10 -07:00
2463548fa7 fix(ngcc): sniff main property for ESM5 format (#36396)
Previously, `main` was only checked for `umd` or `commonjs`
formats. Now if there are `import` or `export` statements in the
source file it will be deemed to be in `esm5` format.

Fixes #35788

PR Close #36396
2020-04-06 11:31:10 -07:00
1140bbc25c refactor(language-service): reformat using clang-format (#36426)
clang-format was recently updated and any PRs that touch files in the
language service will have to reformat all the files.

Instead of changing the formatting in those PRs, this PR formats all
files in language-service package once and for all.

PR Close #36426
2020-04-06 09:29:42 -07:00
1b4df6484e docs: add missing command in WebWorker guide (#36397)
The command was accidentally removed in #36383

PR Close #36397
2020-04-06 09:29:17 -07:00
f40d51733a fix(dev-infra): use commit message validation from @angular/dev-infra-private (#36172)
Prior to this change we manage a local version of commit message validation
in addition to the commit message validation tool contained in the ng-dev
tooling.  By adding the ability to validate a range of commit messages
together, the remaining piece of commit message validation that is in the
local version is replicated.

We use both commands provided by the `ng-dev commit-message` tooling:
- pre-commit-validate: Set to automatically run on an git hook to validate
    commits as they are created locally.
- validate-range: Run by CI for every PR, testing that all of the commits
    added by the PR are valid when considered together.  Ensuring that all
    fixups are matched to another commit in the change.

PR Close #36172
2020-04-06 09:28:52 -07:00
e893c5a330 fix(compiler-cli): pass real source spans where they are empty (#31805)
Some consumers of functions that take `ParseSourceSpan`s currently pass
empty and incorrect source spans. This fixes those cases.

PR Close #31805
2020-04-06 09:28:27 -07:00
8be8466a00 style(ngcc): reformat of ngcc after clang update (#36447)
PR Close #36447
2020-04-06 09:26:57 -07:00
c8bef1259c docs: adding Doguhan Uluca as GDE resource (#34789)
PR Close #34789
2020-04-03 14:03:57 -07:00
568e9df1d6 fix(router): allow UrlMatcher to return null (#36402)
The matcher is allowed to return null per
https://angular.io/api/router/UrlMatcher#usage-notes

And run `yarn gulp format` to pick up recent clang format changes.

Closes #29824

BREAKING CHANGE: UrlMatcher's type now reflects that it could always return
    null.

    If you implemented your own Router or Recognizer class, please update it to
    handle matcher returning null.

PR Close #36402
2020-04-03 11:16:23 -07:00
a555fdba32 build: update pullapprove config to better handle global approvals (#36384)
Beginning with this change, global approvals will now require the approver
to include `Reviewed-for: global-approvers`, and a docs global approval
requires `Reviewed-for: global-docs-approvers`.

Historically, providing a review by any member of the global reviewer
groups would automatically be considered a global review.  This change
enforces that global approval should be an intentional, explicit action.

The global-approvers and global-docs-approvers group will not be
requested as reviews by pullapprove.

PR Close #36384
2020-04-03 11:11:30 -07:00
36535e9abd fix(dev-infra): correct pullapprove global approval regex (#36384)
PR Close #36384
2020-04-03 11:11:30 -07:00
6402a9ae2a build: rebuild yarn lock from scratch (#36377)
Rebuild the yarn lock file from scratch to collapse instances where
one package is able to satisfy multiple dependencies.  Currently we
have some situations where we have multiple versions when one would
work.

Example:
```
"@babel/code-frame@^7.0.0":
  version "7.0.0"
  resolved "https://registry.yarnpkg.com/@babel/cod
  integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij
  dependencies:
    "@babel/highlight" "^7.0.0"

"@babel/code-frame@^7.5.5":
  version "7.5.5"
  resolved "https://registry.yarnpkg.com/@babel/cod
  integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQ
  dependencies:
    "@babel/highlight" "^7.0.0"

"@babel/code-frame@^7.8.3":
  version "7.8.3"
  resolved "https://registry.yarnpkg.com/@babel/cod
  integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0j
  dependencies:
    "@babel/highlight" "^7.8.3"
```

becomes

```
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3":
  version "7.8.3"
  resolved "https://registry.yarnpkg.com/@babel/cod
  integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0j
  dependencies:
    "@babel/highlight" "^7.8.3"
```

PR Close #36377
2020-04-03 11:09:17 -07:00
ca25c957bf fix(ngcc): correctly detect imported TypeScript helpers (#36284)
The `NgccReflectionHost`s have logic for detecting certain known
declarations (such as `Object.assign()` and TypeScript helpers), which
allows the `PartialEvaluator` to evaluate expressions it would not be
able to statically evaluate otherwise.

In #36089, `DelegatingReflectionHost` was introduced, which delegates to
a TypeScript `ReflectionHost` when reflecting on TypeScript files, which
for ngcc's case means `.d.ts` files of dependencies. As a result, ngcc
lost the ability to detect TypeScript helpers imported from `tslib`,
because `DelegatingReflectionHost` was not able to apply the known
declaration detection logic while reflecting on `tslib`'s `.d.ts` files.

This commit fixes this by ensuring `DelegatingReflectionHost` calls the
`NgccReflectionHost`'s `detectKnownDeclaration()` method as necessary,
even when using the TypeScript `ReflectionHost`.

NOTE:
The previous commit exposed a bug in ngcc that was hidden due to the
tests' being inconsistent with how the `ReflectionHost`s are used in the
actual program. The changes in this commit are verified by ensuring the
failing tests are now passing (hence no new tests are added).

PR Close #36284
2020-04-03 11:08:46 -07:00
93f07aee6c test(ngcc): use DelegatingReflectionHost for testing NgccReflectionHosts (#36284)
In #36089, `DelegatingReflectionHost` was introduced. Under the hood, it
delegates another `NgccReflectionHost` in order to reflect over the
program's source files, while using a different TypeScript
`ReflectionHost` to reflect over `.d.ts` files (which is how external
dependencies are represented in the program).

Previously, the `NgccReflectionHost`s were used directly in tests. This
does not exercise them in the way they are exercised in the actual
program, because (when used directly) they will also reflect on `.d.ts`
files too (instead of delegating to the TypeScript `ReflectionHost`).
This could hide bugs that would happen on the actual program.

This commit fixes this by using the `DelegatingReflectionHost` in the
various `NgccReflectionHost` tests.

NOTE:
This change will cause some of the existing tests to start failing.
These failures demonstrate pre-existing bugs in ngcc, that were hidden
due to the tests' being inconsistent with how the `ReflectionHost`s are
used in the actual program. They will be fixed in the next commit.

PR Close #36284
2020-04-03 11:08:46 -07:00
0af6e9fcbb refactor(ngcc): move logic for identifying known declarations to method (#36284)
The `NgccReflectionHost`s have logic for detecting certain known
declarations (such as `Object.assign()` and TypeScript helpers), which
allows the `PartialEvaluator` to evaluate expressions it would not be
able to statically evaluate otherwise.

This commit moves the logic for identifying these known declarations to
dedicated methods. This is in preparation of allowing ngcc's
`DelegatingReflectionHost` (introduced in #36089) to also apply the
known declaration detection logic when reflecting on TypeScript sources.

PR Close #36284
2020-04-03 11:08:46 -07:00
008e12edda fix(benchpress): fix typings in lview_debug.ts (#36236)
* Installing & using benchpress was throwing typescript errors because typings were not defined for the getters in lview_debug.ts

PR Close #36236
2020-04-03 11:06:07 -07:00
1927d0c7db docs: place download section in angular forms to the top (#36075)
This commit partially addresses #35459

PR Close #36075
2020-04-03 11:05:31 -07:00
9a0a90feb3 docs: place download section in angular forms validation to the top of the page (#36074)
This commit partially addresses #35459

PR Close #36074
2020-04-03 11:03:36 -07:00
76d86d5a07 docs: place download section in angular pipes to the top (#36073)
This commit partially addresses #35459

PR Close #36073
2020-04-03 11:01:08 -07:00
de7a9a3b93 docs: place download section to the top of the page (#36067)
Previously, the download link to the example for the angular element
guide was in the middle of the page. To make it easier for the user to
find the download link, it has been placed to the top of the page.

This commit partially addresses #35459

PR Close #36067
2020-04-03 11:00:26 -07:00
04f61c0c3e build: enable strictTemplates in AIO (#36391)
PR Close #36391
2020-04-02 10:53:12 -07:00
c810ac7153 build: sort module resolution warnings in ts-circular-deps tool (#36361)
For better overview of modules that cannot be resolved in the
`ts-circular-deps` tool, the warnings are now sorted.

Additionally, an empty line between fixed and new circular dependencies
is now printed. That should slightly help with distinguishing.

PR Close #36361
2020-04-02 10:52:47 -07:00
c24ad560fa feat(core): undecorated-classes migration should handle derived abstract classes (#35339)
In version 10, undecorated base classes that use Angular features need
to be decorated explicitly with `@Directive()`. Additionally, derived
classes of abstract directives need to be decorated.

The migration already handles this for undecorated classes that are
not explicitly decorated, but since in V9, abstract directives can be
used, we also need to handle this for explicitly decorated abstract
directives. e.g.

```
@Directive()
export class Base {...}

// needs to be decorated by migration when updating from v9 to v10
export class Wrapped extends Base {}

@Component(...)
export class Cmp extends Wrapped {}
```

PR Close #35339
2020-04-02 10:51:49 -07:00
3d2db5c5f0 test: add integration test for undecorated-classes-with-decorated-fields migration (#35339)
We don't have an integration test for the `undecorated-classes-with-decorated-fields
migration. For consistency and to cover for the latest changes, we add
it to the `ng update` integration test.

PR Close #35339
2020-04-02 10:51:48 -07:00
32eafef6a7 fix(core): undecorated-classes-with-decorated-fields migration does not decorate derived classes (#35339)
The `undecorated-classes-with-decorated-fields` migration has been
introduced with 904a2018e0, but misses
logic for decorating derived classes of undecorated classes which use
Angular features. Example scenario:

```ts
export abstract class MyBaseClass {
  @Input() someInput = true;
}

export abstract class BaseClassTwo extends MyBaseClass {}

@Component(...)
export class MyButton extends BaseClassTwo {}
```

Both abstract classes would need to be migrated. Previously, the migration
only added `@Directive()` to `MyBaseClass`, but with this change, it
also decorates `BaseClassTwo`.

This is necessary because the Angular Compiler requires `BaseClassTwo` to
have a directive definition when it flattens the directive metadata for
`MyButton` in order to perform type checking. Technically, not decorating
`BaseClassTwo` does not break at runtime.

We basically want to enforce consistent use of `@Directive` to simplify the
mental model. [See the migration guide](https://angular.io/guide/migration-undecorated-classes#migrating-classes-that-use-field-decorators).

Fixes #34376.

PR Close #35339
2020-04-02 10:51:48 -07:00
2366480250 refactor(core): move schematic import manager to shared utils (#35339)
The import manager has been created for both the `missing-injectable`
and `undecorated-classes-with-di` migration. Both initial PRs brought
in the manager class, so the manager is duplicated in the schematics.

In order to reduce this duplication, and to expose the manager to other
schematics/migrations, we move it into the shared schematic utils.

PR Close #35339
2020-04-02 10:51:48 -07:00
8e55a11283 refactor(core): move schematic base classes logic into shared utils (#35339)
Moves the `findBaseClassDeclarations` method into the shared
schematic utilities. This method will be useful for future
migrations, and for planned changes to the
`undecorated-classes-with-decorated-fields` migration.

PR Close #35339
2020-04-02 10:51:48 -07:00
e9de28111d build: enable service-worker tests on saucelabs (#36129)
Enables the `service-worker` tests on Saucelabs and fixes some issues that were preventing them from running on IE. The issues were:
1. We were serving es2017 code during tests. I've set it to es5.
2. The check which was verifying whether the environment is supported ended up hitting a `require` call in the browser which caused it to fail on browsers that don't support the `URL` API.

PR Close #36129
2020-04-01 15:37:47 -07:00
75afd80ae8 refactor(compiler): add @nocollapse annotation using a synthetic comment (#35932)
In Ivy, Angular decorators are compiled into static fields that are
inserted into a class declaration in a TypeScript transform. When
targeting Closure compiler such fields need to be annotated with
`@nocollapse` to prevent them from being lifted from a static field into
a variable, as that would prevent the Ivy runtime from being able to
find the compiled definitions.

Previously, there was a bug in TypeScript where synthetic comments added
in a transform would not be emitted at all, so as a workaround a global
regex-replace was done in the emit's `writeFile` callback that would add
the `@nocollapse` annotation to all static Ivy definition fields. This
approach is no longer possible when ngtsc is running as TypeScript
plugin, as a plugin cannot control emit behavior.

The workaround is no longer necessary, as synthetic comments are now
properly emitted, likely as of
https://github.com/microsoft/TypeScript/pull/22141 which has been
released with TypeScript 2.8.

This change is required for running ngtsc as TypeScript plugin in
Bazel's `ts_library` rule, to move away from the custom `ngc_wrapped`
approach.

Resolves FW-1952

PR Close #35932
2020-04-01 15:37:06 -07:00
a5eb0e56b6 docs(zone.js): fix typos and align formatting (#35907)
PR Close #35907
2020-04-01 15:35:37 -07:00
4d458db1b5 docs: update and edit web-worker page (#36383)
PR Close #36383
2020-04-01 15:25:47 -07:00
24a92472bf ci: use dev-infra cli from local sources (#36326)
Use dev-infra cli from local sources rather than loading
from @angular/dev-infra-private builds.

PR Close #36326
2020-04-01 15:24:29 -07:00
43006bcc45 feat(dev-infra): standard CLI commands using yargs (#36326)
Creates a standard model for CLI commands provided by ng-dev.
Allows for us to have any of the tools/scripts extend to be
included in the ng-dev command, or be standalone using the same
yargs parser.

PR Close #36326
2020-04-01 15:24:28 -07:00
326240eb91 fix(ngcc): allow ngcc configuration to match pre-release versions of packages (#36370)
Ngcc supports providing a project-level configuration to affect how
certain dependencies are processed and also has a built-in fallback
configuration for some unmaintained packages. Each entry in these
configurations could be scoped to specific versions of a package by
providing a version range. If no version range is provided for a
package, it defaults to `*` (with the intention of matching any
version).

Previously, the installed version of a package was tested against the
version range using the [semver][1] package's `satisfies()` function
with the default options. By default, `satisfies()` does not match
pre-releases (see [here][2] for more details on reasoning). While this
makes sense when determining what version of a dependency to install
(trying to avoid unexpected breaking changes), it is not desired in the
case of ngcc.

This commit fixes it by explicitly specifying that pre-release versions
should be matched normally.

[1]: https://www.npmjs.com/package/semver
[2]: https://github.com/npm/node-semver#prerelease-tags

PR Close #36370
2020-04-01 13:32:32 -07:00
b59bc0e38c fix(platform-server): update xhr2 dependency (#36366)
Previous versions of xhr2 used the depreciated "new Buffer()".

Closes #36358

PR Close #36366
2020-04-01 13:31:38 -07:00
5516802142 fix(compiler): avoid undefined expressions in holey array (#36343)
From G3 bug ID: 116443331

The View Engine compiler crashes when it tries to compile a test in JIT mode
that includes the d3-scale-chromatic library [1]. The d3 package initializes
some arrays using the following pattern:

```js
export var scheme = new Array(3).concat(
  "d8b365f5f5f55ab4ac",
  // ... more entries
).map(colors);
```

The stack trace from the crash is as follows:

```
TypeError: Cannot read property 'visitExpression' of undefined
    at ../../../third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts:505:39
    at JitEmitterVisitor.AbstractEmitterVisitor.visitAllObjects third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=526
    at JitEmitterVisitor.AbstractEmitterVisitor.visitAllExpressions third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=505
    at JitEmitterVisitor.AbstractEmitterVisitor.visitLiteralArrayExpr third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=484
    at LiteralArrayExpr.visitExpression third_party/javascript/angular2/rc/packages/compiler/src/output/output_ast.ts?l=791
    at ../../../third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts:492:19
    at JitEmitterVisitor.AbstractEmitterVisitor.visitAllObjects third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=526
    at JitEmitterVisitor.AbstractEmitterVisitor.visitLiteralMapExpr third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=490
    at LiteralMapExpr.visitExpression third_party/javascript/angular2/rc/packages/compiler/src/output/output_ast.ts?l=819
    at ../../../third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts:505:39
    at JitEmitterVisitor.AbstractEmitterVisitor.visitAllObjects third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=526
    at JitEmitterVisitor.AbstractEmitterVisitor.visitAllExpressions third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=505
    at JitEmitterVisitor.AbstractEmitterVisitor.visitInvokeFunctionExpr third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_emitter.ts?l=318
    at JitEmitterVisitor.AbstractJsEmitterVisitor.visitInvokeFunctionExpr third_party/javascript/angular2/rc/packages/compiler/src/output/abstract_js_emitter.ts?l=112
    at InvokeFunctionExpr.visitExpression third_party/javascript/angular2/rc/packages/compiler/src/output/output_ast.ts?l=440
```

This is because the corresponding output AST for the array is of the form

```ts
[
  undefined,
  undefined,
  undefined,
  o.LiteralExpr,
  // ...
]
```

The output AST is clearly malformed and breaks the type representation of
`LiteralArrayExpr` in which every entry is expected to be of type `Expression`.

This commit fixes the bug by using a plain `for` loop to iterate over the
entire length of the holey array and convert undefined elements to
`LiteralExpr`.

[1]: https://github.com/d3/d3-scale-chromatic/blob/master/src/diverging/BrBG.js

PR Close #36343
2020-04-01 13:31:14 -07:00
cc4b813e75 fix(ngcc): handle bad path mappings when finding entry-points (#36331)
Previously, a bad baseUrl or path mapping passed to an `EntryPointFinder`
could cause the original `sourceDirectory` to be superceded by a higher
directory. This could result in none of the sourceDirectory entry-points being
processed.

Now missing basePaths computed from path-mappings are discarded with
a warning. Further, if the `baseUrl` is the root directory then a warning is
given as this is most likely an error in the tsconfig.json.

Resolves #36313
Resolves #36283

PR Close #36331
2020-04-01 13:30:46 -07:00
64631063ae docs: fix typo in Tests guide (#36330)
Fixing typo in testing.md

PR Close #36330
2020-04-01 13:30:16 -07:00
719224bffd feat(dev-infra): add support for new global approvers in pullapprove (#36324)
Pullapprove as added a few new features to allow for us to better
execute our expectation for global approvals. We need to allow for
an expectation that our global approver groups are not in the list
of approved groups. Additionally, since approval groups apply to
all files in the repo, the global approval groups also do not have
conditions defined for them, which means pullapprove verification
need to allow for no conditions need to be defined.

PR Close #36324
2020-04-01 13:25:48 -07:00
fe2b6923ba fix(language-service): infer type of elements of array-like objects (#36312)
Currently the language service only provides support for determining the
type of array-like members when the array-like object is an `Array`.
However, there are other kinds of array-like objects, including
`ReadonlyArray`s and `readonly`-property arrays. This commit adds
support for retrieving the element type of arbitrary array-like objects.

Closes #36191

PR Close #36312
2020-04-01 13:24:53 -07:00
38ad1d97ab fix(ngcc): handle entry-points within container folders (#36305)
The previous optimizations in #35756 to the
`DirectoryWalkerEntryPointFinder` were over zealous
with regard to packages that have entry-points stored
in "container" directories in the package, where the
container directory was not an entry-point itself.

Now we will also walk such "container" folders as long
as they do not contain `.js` files, which we regard as an
indicator that the directory will not contain entry-points.

Fixes #36216

PR Close #36305
2020-04-01 13:20:52 -07:00
372b9101e2 refactor(ngcc): simplify DirectoryWalkerEntryPointFinder (#36305)
This commit simplifies the `DirectoryWalkerEntryPointFinder` inter-method
calling to make it easier to follow, and also to support controlling
walking of a directory based on its children.

PR Close #36305
2020-04-01 13:20:52 -07:00
7e62aa0c6e refactor(ngcc): rename INVALID_ENTRY_POINT to INCOMPATIBLE_ENTRY_POINT (#36305)
This name better reflects its meaning.

PR Close #36305
2020-04-01 13:20:52 -07:00
36e927a8c6 fix(zone.js): UNPATCHED_EVENTS and PASSIVE_EVENTS should be string[] not boolean (#36258)
__zone_symbol__UNPATCHED_EVENTS and __zone_symbol__PASSIVE_EVENTS should be string[] type not boolean.
For example:
```
const config = window as ZoneGlobalConfigurations;
config.__zone_symbol__UNPATCHED_EVENTS = ['scroll'];
config.__zone_symbol__PASSIVE_EVENTS = ['scroll'];
```

PR Close #36258
2020-04-01 13:20:00 -07:00
9d8bb634f9 fix(benchpress): update dependencies (#36205)
* updated, added, and removed dependencies in package.json
* added dependencies to BUILD.bazel

PR Close #36205
2020-04-01 13:19:33 -07:00
c5c57f6737 build: update to clang 1.4.0 and only run clang format on changed files (#36203)
Update to clang@1.4.0 to gain support for optional changing and nullish
coalescing.  Because this would trigger a change on >1800 files in the
repository, also changes our format enforcement to only be run against
changed files.  This will allow us to incramentally roll out the value
add of the upgraded clang format.

PR Close #36203
2020-04-01 13:18:09 -07:00
51a89c32c4 docs: update and edit web-worker page (#36026)
PR Close #36026
2020-04-01 13:17:26 -07:00
e1ac2efe4a docs: make page titles and toc task-oriented (#36024)
PR Close #36024
2020-04-01 13:16:48 -07:00
702e17cfe2 docs: change page title and minor edit (#36021)
PR Close #36021
2020-04-01 13:16:18 -07:00
4d1d0fa03b docs: update ng-conf announcement to remove livestream link (#36382)
Since the livestream for ng-conf is not public this year,
(and is only available to ng-conf attendees), we are
removing the link from the angular.io homepage.

Instead, we are now pointing to the ng-conf homepage for
more information.

PR Close #36382
2020-04-01 13:14:42 -07:00
ec8bae1b27 docs: update end date of survey to middle of April (#36339)
PR Close #36339
2020-04-01 11:10:58 -07:00
08348fc2e8 build(docs-infra): rename duplicate test name (#36348)
When running `docs-test` for the docs generation, a warning is printed for a
duplicate test. This commit fixes this issue.

PR Close #36348
2020-03-31 11:06:16 -07:00
63fbc71439 build: don't use deprecated $(location) pre-declared variable (#36308)
$(location) is not recommended in the bazel docs as depending on context it will either return the value of $(execpath) or $(rootpath). rules_nodejs now supports $(rootpath) and $(execpath) in templated_args of nodejs_binary.

PR Close #36308
2020-03-31 11:02:56 -07:00
b44f7b5e16 fix(zone.js): fix 2 bluebird test cases for each/mapSeries (#36295)
`Bluebird.each` and `Bluebird.mapSeries` will accept a callback with `value` parameter,
the `value` should be the item in the array, not array itself.

For example:
```
const arr = [1, 2];
Bluebird.each(arr, function(value, idx) {
  console.log(`value: ${value}, idx: ${idx}`);
})
```

the output will be
```
value: 1, idx: 0
value: 2, idx: 1
```

This PR fix the test cases for `each` and `mapSeries` APIs.

PR Close #36295
2020-03-31 10:59:56 -07:00
c5df9ce474 build(zone.js): update zone.js version to 0.10.3 (#36214)
PR Close #36214
2020-03-31 10:59:17 -07:00
2510e7dad6 docs: fix typo in Schematics guide (#36328)
Fixing typo in schematics-for-libraries.md
PR Close #36328
2020-03-30 15:32:05 -07:00
80c68583d1 refactor(core): use more narrow QueryList import to avoid circular deps issue (#36286)
Prior to this commit, the `packages/core/src/render3/interfaces/query.ts` file used to import `QueryList` using `../../linker`, which contains a lot of re-exports and as a result, this one import caused a lot of circular deps cycles reported by the tool that checks such deps. In other places in the code the `QueryList` is imported using more narrow import (`linker/query_list`), so this commit uses the same pattern. This change allowed to reduce the number of known cycles from 343 to 207, the golden file was updated accordingly.

PR Close #36286
2020-03-30 15:31:39 -07:00
5b6ced5599 build: update to rules_nodejs 1.5.0 (#36307)
### New stuff

* The `ts_project` rule is a simple wrapper around the TypeScript compiler, `tsc`. This is an alternative to `ts_library` but not a replacement. Read more about the trade-offs at https://bazelbuild.github.io/rules_nodejs/TypeScript#alternatives or read the [API docs](https://bazelbuild.github.io/rules_nodejs/TypeScript#ts_project)
* `pkg_npm` can now be used as a dependency within your repo as well as for publishing to npm. It provides a `LinkablePackageInfo` which is our internal API to pass package name/path to downstream compilations, essentially providing the "Lerna" feature.
* There is experimental support for Bazel's "worker mode" in `rollup_bundle`, which essentially puts Rollup in watch mode. Add the `supports_workers = True` attribute to opt-in.
* Better support for [pre-defined label variables](https://docs.bazel.build/versions/master/be/make-variables.html#predefined_label_variables) like `$(rootpath)` and `$(execpath)` - we no longer recommend using `$(location)` at all.

See release notes https://github.com/bazelbuild/rules_nodejs/releases/tag/1.5.0 for more info.

PR Close #36307
2020-03-30 11:25:16 -07:00
a383116b43 docs: fix typo in Dependency Injection guide (#36304)
Fixing typo in dependency-injection-navtree.md

PR Close #36304
2020-03-30 11:14:55 -07:00
c6dd900f60 fix(ngcc): do not write entry-point manifest outside node_modules (#36299)
Fixes #36296

PR Close #36299
2020-03-30 11:03:26 -07:00
5ac308060d refactor(ngcc): rename workerCount to maxWorkerCount (#36298)
Now that we spawn workers lazily as needed, this private property is
really the upper limit on how many workers we might spawn.

PR Close #36298
2020-03-30 11:02:52 -07:00
bc089abd32 docs: add strictTemplates in place of fullTemplateTypeCheck (#35628)
Co-Authored-By: Igor Minar <iminar@google.com>

Updating the recommended defaults for template typechecking strictness to the most strict in order
to catch most of the errors at compile time.

See https://angular.io/guide/template-typecheck for more info.

PR Close #35628
2020-03-30 10:57:15 -07:00
c94a33c525 refactor(dev-infra): fix lint warnings for Pullapprove-related scripts (#36287)
The `dev-infra` scripts were added to the list of sources that should be verified with clang (b07b6edc2a), but the Pullapprove-related scripts that were merged before (83e4a76afa) doesn't pass these checks. This commit updates a couple scripts to have a proper formatting.

PR Close #36287
2020-03-28 23:21:12 -07:00
5cee709266 fix(ngcc): do not spawn more processes than intended in parallel mode (#36280)
When running in parallel mode, ngcc spawns multiple worker processed to
process the various entry-points. The number of max allowed processes is
determined by the number of CPU cores available to the OS. There is also
currently an [upper limit of 8][1]. The number of active workers is in
turn inferred by the number of [task assignments][2].

In the past, counting the entries of `ClusterMaster#taskAssignments` was
enough, because worker processes were spawned eagerly at the beginning
and corresponding entries were created in `taskAssignments`.
Since #35719 however, worker processes are spawned lazily on an as
needed basis. Because there is some delay between
[spawning a process][3] and [inserting it][4] into `taskAssignments`,
there is a short period of time when `taskAssignment.size` does not
actually represent the number of spawned processes. This can result in
spawning more than `ClusterMaster#workerCount` processes.

An example of this can be seen in #36278, where the debug logs indicate
9 worker processes had been spawned (`All 9 workers are currently busy`)
despite the hard limit of 8.

This commit fixes this by using `cluster.workers` to compute the number
of spawned worker processes. `cluster.workers` is updated synchronously
with `cluster.fork()` and thus reflects the number of spawned workers
accurately at all times.

[1]: https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429
[2]: https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108
[3]: https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110
[4]: https://github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199

PR Close #36280
2020-03-27 14:12:28 -07:00
2d0847c307 docs: update release nots with blog post (#36268)
PR Close #36268
2020-03-27 11:18:23 -07:00
995cd15a69 fix(ngcc): correctly identify the package path of secondary entry-points (#36249)
Previously we only searched for package paths below the set of `basePaths`
that were computed from the `basePath` provided to ngcc and the set of
`pathMappings`.

In some scenarios, such as hoisted packages, the entry-point is not within
any of the `basePaths` identified above. For example:

```
project
  packages
    app
      node_modules
        app-lib (depends on lib1)
  node_modules
    lib1 (depends on lib2)
      node_modules
        lib2 (depends on lib3/entry-point)
    lib3
      entry-point
```

When CLI is compiling `app-lib` ngcc will be given
`project/packages/app/node_modules` as the `basePath.

If ngcc is asked to target `lib2`, the `targetPath` will be
`project/node_modules/lib1/node_modules/lib2`.

Since `lib2` depends upon `lib3/entry-point`, ngcc will need to compute
the package path for `project/node_modules/lib3/entry-point`.

Since `project/node_modules/lib3/entry-point` is not contained in the `basePath`
`project/packages/app/node_modules`, ngcc failed to compute the `packagePath`
correctly, instead assuming that it was the same as the entry-point path.

Now we also consider the nearest `node_modules` folder to the entry-point
path as an additional `basePath`. If one is found then we use the first
directory directly below that `node_modules` directory as the package path.

In the case of our example this extra `basePath` would be `project/node_modules`
which allows us to compute the `packagePath` of `project/node_modules/lib3`.

Fixes #35747

PR Close #36249
2020-03-27 11:17:45 -07:00
16497438d6 fix(core): run APP_INITIALIZERs before accessing LOCALE_ID token in Ivy TestBed (#36237)
Prior to this commit, Ivy TestBed was accessing locale ID before `APP_INITIALIZER` functions were called. This execution order is not consistent with the app bootstrap logic in `application_ref.ts`. This commit updates Ivy TestBed execution order to call initializers first (since they might affect `LOCALE_ID` token value) and accessing and setting locale ID after that.

Fixes #36230.

PR Close #36237
2020-03-27 11:16:57 -07:00
b54db86f43 build: fix bad pullapprove rule (#36232)
The dev-infra pull approve group contained a condition with
the glob having a string concatenation rather than a comma
separated list. This corrects this error, and in another PR
we will correct the verification scripts failure to catch
this.

PR Close #36232
2020-03-27 11:15:38 -07:00
44acf6734b build: allow custom module resolution for ts-circular-deps tests (#36226)
Currently the `ts-circular-deps` tool uses a hard-coded module resolver
that only works in the `angular/angular` repository.

If the tool is consumed in other repositories through the shared
dev-infra package, the module resolution won't work, and a few
resolvable imports (usually cross-entry-points) are accidentally
skipped. For each test, the resolution might differ, so tests can
now configure their module resolution in a configuration file.

Note that we intentionally don't rely on tsconfig's for module
resolution as parsing their mappings rather complicates the
circular dependency tool. Additionally, not every test has a
corresponding tsconfig file.

Also, hard-coding mappings to `@angular/*` while accepting a
path to the packages folder would work, but it would mean
that the circular deps tool is no longer self-contained. Rather,
and also for better flexibility, a custom resolver should be
specified.

PR Close #36226
2020-03-27 11:14:49 -07:00
b07b6edc2a build: add dev-infra to clang format sources to format (#36204)
PR Close #36204
2020-03-27 11:13:17 -07:00
83e4a76afa feat(dev-infra): handle excluding files via globs in pullapprove (#36162)
Updates the pullapprove verification script to handle
cases of excluding globs from groups.

PR Close #36162
2020-03-27 11:12:48 -07:00
bfa7b1a494 docs: correct a misleading sentence (#36155) (#36158)
Fixes #36155

PR Close #36158
2020-03-27 10:49:31 -07:00
8e0dec538e docs: clarify observables doc with new titles and tooltips (#36023)
PR Close #36023
2020-03-27 10:49:03 -07:00
1c385a1c22 build(docs-infra): do not include CI-specific config in docs examples ZIP archives (#36018)
In #35381, a new Protractor config file was introduced in docs examples,
`protractor-puppeteer.conf.js`, that was only supposed to be used on CI
and not be shipped with the ZIP archives provided for users to download
and experiment with the docs examples locally.

The logic to ignore the `protractor-puppeteer.conf.js` file was
incorrect, resulting in the file being retained in some examples (e.g.
[universal][1]). The problem was not immediately obvious, because most
examples explicitly specify all `**/*.js` files as ignored, but for
other examples the file was retained in the ZIP archive.

This commit fixes the logic to ensure the file is excluded from all docs
examples ZIP archives.

[1]: https://v9.angular.io/generated/zips/universal/universal.zip

PR Close #36018
2020-03-27 10:48:30 -07:00
f9bc84cd99 build(docs-infra): remove obsolete properties from zipper.json files (#36018)
The `removeSystemJsConfig` and `type` properties (present in some
`zipper.json` files) are now obsolete and are not taken into account by
the example zipper:
- `removeSystemJsConfig` is no longer relevant since most examples have
  been migrated to use the CLI.
- `type` is no longer relevant, because the project type is determined
  based on the `projectType` property in `example-config.json` files.

This commit removes these properties from `zipper.json` files and
updates the `example-zipper` docs to not mention them.

PR Close #36018
2020-03-27 10:48:30 -07:00
2d7c95fb70 fix(service-worker): prevent SW registration strategies from affecting app stabilization (#35870)
Previously, some of the built-in ServiceWorker registration strategies,
namely `registerWithDelay:<timeout>` and `registerWhenStable:<timeout>`,
would register potentially long-running timeout, thus preventing the app
from stabilizing before the timeouts expired. This was especially
problematic for the `registerWhenStable:<timeout>` strategy, which waits
for the app to stabilize, because the strategy itself would prevent the
app from stabilizing and thus the ServiceWorker would always be
registered after the timeout.

This commit fixes this by subscribing to the registration strategy
observable outside the Angular zone, thus not affecting the app's
stabilization.

PR Close #35870
2020-03-27 10:47:44 -07:00
29e8a64cf0 fix(service-worker): by default register the SW after 30s even the app never stabilizes (#35870)
Previously, when using the default ServiceWorker registration strategy
Angular would wait indefinitely for the [app to stabilize][1], before
registering the ServiceWorker script. This could lead to a situation
where the ServiceWorker would never be registered when there was a
long-running task (such as an interval or recurring timeout).

Such tasks can often be started by a 3rd-party dependency (beyond the
developer's control or even without them realizing). In addition, this
situation is particularly hard to detect, because the ServiceWorker is
typically not used during development and on production builds a
previous ServiceWorker instance might be already active.

This commit fixes this by changing the default registration strategy
from `registerWhenStable` to `registerWhenStable:30000`, which will
ensure that the ServiceWorker will be registered after 30s at the
latest, even if the app has not stabilized by then.

Fixes #34464

PR Close #35870
2020-03-27 10:47:44 -07:00
00efacf561 feat(service-worker): support timeout in registerWhenStable SW registration strategy (#35870)
Previously, when using the `registerWhenStable` ServiceWorker
registration strategy (which is also the default) Angular would wait
indefinitely for the [app to stabilize][1], before registering the
ServiceWorker script. This could lead to a situation where the
ServiceWorker would never be registered when there was a long-running
task (such as an interval or recurring timeout).

Such tasks can often be started by a 3rd-party dependency (beyond the
developer's control or even without them realizing). In addition, this
situation is particularly hard to detect, because the ServiceWorker is
typically not used during development and on production builds a
previous ServiceWorker instance might be already active.

This commit enhances the `registerWhenStable` registration strategy by
adding support for an optional `<timeout>` argument, which guarantees
that the ServiceWorker will be registered when the timeout expires, even
if the app has not stabilized yet.

For example, with `registerWhenStable:5000` the ServiceWorker will be
registered as soon as the app stabilizes or after 5 seconds if the app
has not stabilized by then.

Related to #34464.

[1]: https://angular.io/api/core/ApplicationRef#is-stable-examples

PR Close #35870
2020-03-27 10:47:44 -07:00
d96995b4e3 docs: update glossary defs for components, templates, and views (#35559)
PR Close #35559
2020-03-27 10:46:49 -07:00
fc3e5cb6d3 docs: coalesce release notes for the v9.1.0 release (#36247)
Merge all of the release notes across all v9.1.0 releases into a single one.

PR Close #36247
2020-03-25 14:11:07 -07:00
d37dad82f1 build: ensure that refs and shas for PRs only need to be requested once (#36207)
This is done by requesting the refs and shas for the PR when the
env.sh script is run.  Additionally, the env.sh script is now setup
to write all of the environment variables created to a cache file
and subsequent loads of the environment load the values from there.

The get-refs-and-shas-for-target.js script now also first attempts
to load the refs and shas from an environment variable before
falling back to requesting from github via the API.

PR Close #36207
2020-03-25 11:49:42 -07:00
22710fc353 docs: release notes for the v9.1.0 release 2020-03-25 09:44:22 -07:00
4f66250618 docs: release notes for the v9.1.0-rc.2 release 2020-03-24 16:18:10 -07:00
d783519835 fix(common): let KeyValuePipe accept type unions with null (#36093)
`KeyValuePipe` currently accepts `null` values as well as `Map`s and a
few others. However, due to the way in which TS overloads work, a type
of `T|null` will not be accepted by `KeyValuePipe`'s signatures, even
though both `T` and `null` individually would be.

To make this work, each signature that accepts some type `T` has been
duplicated with a second one below it that accepts a `T|null` and
includes `null` in its return type.

Fixes #35743

PR Close #36093
2020-03-24 14:41:41 -07:00
b8e9a30d3b fix(ngcc): use preserve whitespaces from tsconfig if provided (#36189)
Previously ngcc never preserved whitespaces but this is at odds
with how the ViewEngine compiler works. In ViewEngine, library
templates are recompiled with the current application's tsconfig
settings, which meant that whitespace preservation could be set
in the application tsconfig file.

This commit allows ngcc to use the `preserveWhitespaces` setting
from tsconfig when compiling library templates. One should be aware
that this disallows different projects with different tsconfig settings
to share the same node_modules folder, with regard to whitespace
preservation. But this is already the case in the current ngcc since
this configuration is hard coded right now.

Fixes #35871

PR Close #36189
2020-03-24 14:25:06 -07:00
32ce8b1326 feat(compiler): add dependency info and ng-content selectors to metadata (#35695)
This commit augments the `FactoryDef` declaration of Angular decorated
classes to contain information about the parameter decorators used in
the constructor. If no constructor is present, or none of the parameters
have any Angular decorators, then this will be represented using the
`null` type. Otherwise, a tuple type is used where the entry at index `i`
corresponds with parameter `i`. Each tuple entry can be one of two types:

1. If the associated parameter does not have any Angular decorators,
   the tuple entry will be the `null` type.
2. Otherwise, a type literal is used that may declare at least one of
   the following properties:
   - "attribute": if `@Attribute` is present. The injected attribute's
   name is used as string literal type, or the `unknown` type if the
   attribute name is not a string literal.
   - "self": if `@Self` is present, always of type `true`.
   - "skipSelf": if `@SkipSelf` is present, always of type `true`.
   - "host": if `@Host` is present, always of type `true`.
   - "optional": if `@Optional` is present, always of type `true`.

   A property is only present if the corresponding decorator is used.

   Note that the `@Inject` decorator is currently not included, as it's
   non-trivial to properly convert the token's value expression to a
   type that is valid in a declaration file.

Additionally, the `ComponentDefWithMeta` declaration that is created for
Angular components has been extended to include all selectors on
`ng-content` elements within the component's template.

This additional metadata is useful for tooling such as the Angular
Language Service, as it provides the ability to offer suggestions for
directives/components defined in libraries. At the moment, such
tooling extracts the necessary information from the _metadata.json_
manifest file as generated by ngc, however this metadata representation
is being replaced by the information emitted into the declaration files.

Resolves FW-1870

PR Close #35695
2020-03-24 14:21:42 -07:00
ff4eb0cb63 docs(elements): correct typo in custom elements image (#36090)
Fixes #36050

PR Close #36090
2020-03-24 10:36:11 -07:00
9ba46d9f88 fix(elements): correctly handle setting inputs to undefined (#36140)
Previously, when an input property was initially set to `undefined` it
would not be correctly recognized as a change (and trigger
`ngOnChanges()`).

This commit ensures that explicitly setting an input to `undefined` is
correctly handled the same as setting the property to any other value.
This aligns the behavior of Angular custom elements with that of the
corresponding components when used directly (not as custom elements).

PR Close #36140
2020-03-24 10:29:33 -07:00
b14ac96750 fix(elements): correctly set SimpleChange#firstChange for pre-existing inputs (#36140)
Previously, when an input property was set on an `NgElement` before
instantiating the underlying component, the `SimpleChange` object passed
to `ngOnChanges()` would have `firstChange` set to false, even if this
was the first change (as far as the component instance was concerned).

This commit fixes this by ensuring `SimpleChange#firstChange` is set to
true on first change, regardless if the property was set before or after
instantiating the component. This alignthe behavior of Angular custom
elements with that of the corresponding components when used directly
(not as custom elements).

Jira issue: [FW-2007](https://angular-team.atlassian.net/browse/FW-2007)

Fixes #36130

PR Close #36140
2020-03-24 10:29:32 -07:00
55dac05cf2 docs: fix typo in testing component with dependencies (#36219)
Fixes #36210

PR Close #36219
2020-03-24 10:19:47 -07:00
ae28d7c0b2 build(docs-infra): upgrade cli command docs sources to 56c648827 (#36224)
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](f5dd5b16a...56c648827):

**Modified**
- help/build.json
- help/lint.json
- help/test.json

PR Close #36224
2020-03-24 10:16:49 -07:00
380de1e7b4 fix(ngcc): use path-mappings from tsconfig in dependency resolution (#36180)
When computing the dependencies between packages which are not in
node_modules, we may need to rely upon path-mappings to find the path
to the imported entry-point.

This commit allows ngcc to use the path-mappings from a tsconfig
file to find dependencies. By default any tsconfig.json file in the directory
above the `basePath` is loaded but it is possible to use a path to a
specific file by providing the `tsConfigPath` property to mainNgcc,
or to turn off loading any tsconfig file by setting `tsConfigPath` to `null`.
At the command line this is controlled via the `--tsconfig` option.

Fixes #36119

PR Close #36180
2020-03-24 10:16:12 -07:00
4f9717331d test(common): Add test for NgForOfContext.count (#36046)
`NgForOfContext.count` is the length of the iterable.

PR Close #36046
2020-03-24 10:15:11 -07:00
36fc28642a docs(common): Add missing entry for NgForOfContext.count (#36046)
`count` is available in `NgForOfContext` but it's missing in the docs.

PR Close #36046
2020-03-24 10:15:11 -07:00
a323b9b1a3 test(core): re-enable IE 10/11 test on SauceLabs (#35962)
I was not able to reproduce IE 10/11 failrue of the disabled
tests on SauceLabs any more. I did some cleanup of the test
in question but I doubt it was the root cause of the problem.

PR Close #35962
2020-03-24 10:14:47 -07:00
58f4254fba fix(dev-infra): use @angular/dev-infra-private package for pullapprove verification (#35996)
Adds devDependency on @angular/dev-infra-private and removes the verify script
from tools, relying instead on the script from ng-dev.

PR Close #35996
2020-03-24 10:14:05 -07:00
4419907b08 docs: release notes for the v9.1.0-rc.1 release 2020-03-23 13:22:17 -07:00
9d415f9c3f fix(docs-infra): change app-list-item to app-item-list (#35601)
The `app-list-item` component sounds like it is used for a single
item, however it renders a list of items. There were also
several changes in the documentation, where it was becoming
confusing if the `app-list-item` is using a single item or multiple
items. This commit fixes this issue. It renames the component and its
respective properties to make sure that the intention is very clear.

Closes #35598

PR Close #35601
2020-03-23 11:40:15 -07:00
fced8ee40e fix(localize): allow ICU expansion case to start with any character except } (#36123)
Previously, an expansion case could only start with an alpha numeric character.
This commit fixes this by allowing an expansion case to start with any character
except `}`.

The [ICU spec](http://userguide.icu-project.org/formatparse/messages) is pretty vague:

> Use a "select" argument to select sub-messages via a fixed set of keywords.

It does not specify what can be a "keyword" but from looking at the surrounding syntax it
appears that it can indeed be any string that does not contain a `}` character.

Closes #31586

PR Close #36123
2020-03-23 11:37:12 -07:00
1cb7b88505 fix(dev-infra): change circular deps positional params to camelCase (#36165)
Changes the positional params for the circular deps tooling to
use camelCase as it requires being defined in camelCase while
in strict mode.  Additionally, remove the `version()` call as
the boolean arguement does not exist in current versions and
throws errors on execution.

PR Close #36165
2020-03-23 11:36:28 -07:00
0e76b32aa5 fix(dev-infra): prep ts-circular-deps to load via node_modules (#36165)
to run ts-circular-deps via installed node_modules, we needed to set
the hashbang of the script to be a node environment, and discover the
project directory based on where the script is run rather than the
scripts file location.

PR Close #36165
2020-03-23 11:36:28 -07:00
e81ad3a1bc docs: Add asterisk info in template syntax guide (#36176)
Add helpful alert for asterisk syntax in the `ngFor` section of template syntax guide

PR Close #36176
2020-03-23 11:36:09 -07:00
c3a85ceabc docs: Change important alert of ngFor (#36176)
Update the important alert of ngFor so that it has a unique format with that of ngIf

PR Close #36176
2020-03-23 11:36:09 -07:00
85e0e366df docs(elements): Edge supports Web Components (#36182)
PR Close #36182
2020-03-23 11:35:49 -07:00
0ce8ad3493 fix(core): workaround Terser inlining bug (#36200)
This variable name change works around https://github.com/terser/terser/issues/615, which was causing the JIT production tests to fail in the Angular CLI repository (https://github.com/angular/angular-cli/issues/17264).

PR Close #36200
2020-03-23 11:34:39 -07:00
528e25a81a build(docs-infra): upgrade cli command docs sources to f5dd5b16a (#36159)
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](6aa3c134c...f5dd5b16a):

**Modified**
- help/update.json

PR Close #36159
2020-03-20 13:57:18 -07:00
d25012e864 docs(zone.js): Typos on zone.md file and fixes on code examples. (#36138)
1. During reading the documentation I found some code examples that were refering to the class properties via methods, but without specifying the context `this`.
2. The 'onInvoke' hook was duplicated
3. A minor typo on `Zones and execution contexts` section
4. A minor typo on `Zones and async lifecycle hooks` section

PR Close #36138
2020-03-20 13:57:00 -07:00
c21c46a8e8 fix(docs-infra): include correct dependencies in StackBlitz examples (#36071)
Previously, all StackBlitz examples included the default dependencies
for `cli`-type projects. However, different example types may have
different `package.json` files with different dependencies.
For example, the [boilerplate `package.json`][1] for `elements` examples
includes an extra dependency on `@angular/elements`.

This commit changes `StackblitzBuilder` to use the dependencies that
correspond to each example type.
(NOTE: Manually verified the changes.)

Jira issue: [FW-2002][2]

[1]: https://github.com/angular/angular/blob/05d058622/aio/tools/examples/shared/boilerplate/elements/package.json
[2]: https://angular-team.atlassian.net/browse/FW-2002

PR Close #36071
2020-03-20 13:56:26 -07:00
9cc8bd5f7d refactor(docs-infra): clean up stackblitz-builder/builder.js script (#36071)
- Remove unused dependencies.
- Change `var` to `const/let`.
- Change regular functions as callbacks to arrow functions.
- Remove unnecessary intermediate variables.
- Switch from custom `_existsSync()` implementation to built-in
  `fs.existsSync()`.

PR Close #36071
2020-03-20 13:56:26 -07:00
ae3eaf8b16 test(compiler): remove whitespace in spans (#36169)
https://github.com/angular/angular/pull/36133 and https://github.com/angular/angular/pull/35986
caused a conflict in test after they both got merged to master.
This PR fixes the failed tests.

PR Close #36169
2020-03-20 12:52:31 -07:00
d714b95fb9 feat(compiler): Propagate value span of ExpressionBinding to ParsedProperty (#36133)
This commit propagates the correct value span in an ExpressionBinding of
a microsyntax expression to ParsedProperty, which in turn porpagates the
span to the template ASTs (both VE and Ivy).

PR Close #36133
2020-03-20 10:21:11 -07:00
912692137a fix(docs-infra): fix image name in example (#36127)
Closes #35618

PR Close #36127
2020-03-20 10:20:36 -07:00
6fc85073d2 feat(dev-infra): create commit-message validation script/tooling (#36117)
PR Close #36117
2020-03-20 10:20:12 -07:00
989dea7083 refactor(benchpress): delete broken code (#35922)
PR Close #35922
2020-03-20 10:19:48 -07:00
8968b206b4 feat(benchpress): create component_benchmark macro (#35692)
* Create component_benchmark macro
* Change class_bindings benchmark to use component_benchmark

PR Close #35692
2020-03-20 10:19:25 -07:00
df890d7629 fix(compiler): record correct end of expression (#34690)
This commit fixes a bug with the expression parser wherein the end index
of an expression node was recorded as the start index of the next token,
not the end index of the current token.

Closes #33477
Closes https://github.com/angular/vscode-ng-language-service/issues/433

PR Close #34690
2020-03-20 10:19:02 -07:00
47bfec4e46 feat(core): add isPromise generic (#34168)
This commit adds generic to `isPromise` function to help with type inference.

PR Close #34168
2020-03-20 10:15:01 -07:00
b4972fa165 release: cut the v9.1.0-rc.0 release 2020-03-19 12:44:09 -07:00
fb92f5de1a build: fix @bazel/bazel to bazelisk leftovers (#36132)
A few leftovers from from `@bazel/bazel` to `@bazel/bazelisk` migration
are still there. This commit fixes those, so that the repository no
longer relies on `@bazel/bazel`.

PR Close #36132
2020-03-19 08:58:47 -07:00
e342ffd855 fix(core): adhere to bootstrap options for JIT compiled components (#35534)
When using `platformBrowserDynamic().bootstrapModule()`, it is possible
to set `defaultEncapsulation` and `preserveWhitespaces` as default
configuration to influence how components are compiled. When compiling
components in JIT with Ivy, these options were not taken into account.

This commit publishes the options to be globally available, so that the
lazy compilation of JIT components has access to the configured
bootstrap options. Note that this approach does not allow changing the
options once they have been set, as Ivy's compilation model does not
allow for multiple compilations to exist at the same time.

For applications that bootstrap multiple modules, it is now required
to provide the exact same bootstrap options. An error is logged if
incompatible bootstrap options are provided, in which case the updated
options will be ignored.

Fixes #35230
Resolved FW-1838

PR Close #35534
2020-03-19 08:57:39 -07:00
c0143cb2ab build: ng_rollup_bundle internal rule should support ngcc (#36044)
The `ng_rollup_bundle` rule currently is only consumed in the
Angular framework repository. This means that Angular packages
are built from source, and ngcc is never needed to build rollup
bundles using Ivy.

Though, this rule is planned to be shared with other repositories
to support common benchmark code. This means that ngcc needs to be
handled as these other repositories cannot build Angular from source,
but instead consume Angular through NPM (with ngcc enabling Ivy).

The `ng_rollup_bundle` rule needs to dynamically prioritize `ngcc`
generated main resolution fields if `--define=angular_ivy_enabled=True`
is set (or with the alias: `--config=ivy`).

ds

PR Close #36044
2020-03-18 15:57:07 -07:00
c9f554cda7 fix(ngcc): do not crash on overlapping entry-points (#36083)
When two entry-points overlap, ngcc may attempt to process some
files twice. Previously, when this occured ngcc would just exit with an
error preventing any other entry-points from being processed.

This commit changes ngcc so that if `errorOnFailedEntryPoint` is false, it will
simply log an error and continue to process entry-points. This is useful when
ngcc is processing the entire node_modules folder and there are some invalid
entry-points that the project doesn't actually use.

PR Close #36083
2020-03-18 15:56:21 -07:00
ff665b9e6a fix(ngcc): do not crash on entry-point that fails to compile (#36083)
Previously, when an entry-point contained code that caused its compilation
to fail, ngcc would exit in the middle of processing, possibly leaving other
entry-points in a corrupt state.

This change adds a new `errorOnFailedEntryPoint` option to `mainNgcc` that
specifies whether ngcc should exit immediately or log an error and continue
processing other entry-points.

The default is `false` so that ngcc will not error but continue processing
as much as possible. This is useful in post-install hooks, and async CLI
integration, where we do not have as much control over which entry-points
should be processed.

The option is forced to true if the `targetEntryPointPath` is provided,
such as the sync integration with the CLI, since in that case it is targeting
an entry-point that will actually be used in the current project so we do want
ngcc to exit with an error at that point.

PR Close #36083
2020-03-18 15:56:21 -07:00
1790b63a5d refactor(ngcc): expose the TaskDependencies mapping on BaseTaskQueue (#36083)
Later when we implement the ability to continue processing when tasks have
failed to compile, we will also need to avoid processing tasks that depend
upon the failed task.

This refactoring exposes this list of dependent tasks in a way that can be
used to skip processing of tasks that depend upon a failed task.

It also changes the blocking model of the parallel mode of operation so
that non-typings tasks are now blocked on their corresponding typings task.
Previously the non-typings tasks could be triggered to run in parallel to
the typings task, since they do not have a hard dependency on each other,
but this made it difficult to skip task correctly if the typings task failed,
since it was possible that a non-typings task was already in flight when
the typings task failed. The result of this is a small potential degradation
of performance in async parallel processing mode, in the rare cases that
there were not enough unblocked tasks to make use of all the available
workers.

PR Close #36083
2020-03-18 15:56:21 -07:00
39d4016fe9 refactor(ngcc): abstract onTaskCompleted out of executors (#36083)
Moving the definition of the `onTaskCompleted` callback into `mainNgcc()`
allows it to be configured based on options passed in there more easily.
This will be the case when we want to configure whether to log or throw
an error for tasks that failed to be processed successfully.

This commit also creates two new folders and moves the code around a bit
to make it easier to navigate the code§:

* `execution/tasks`: specific helpers such as task completion handlers
* `execution/tasks/queues`: the `TaskQueue` implementations and helpers

PR Close #36083
2020-03-18 15:56:21 -07:00
712f2642d5 refactor(ngcc): add message text to task outcomes (#36083)
This sets up the task execution to be able to report failed compiles

PR Close #36083
2020-03-18 15:56:21 -07:00
d50881a86e docs: move asset management section (#35665)
PR Close #35665
2020-03-18 15:55:44 -07:00
c1a0f0617c release: cut the v9.1.0-next.5 release 2020-03-18 13:56:06 -07:00
13f7631c25 docs: release notes for the v9.0.7 release 2020-03-18 13:48:50 -07:00
d2c60cc216 ci: cache downloaded bazel version in circleci (#36098)
Similarly to what is done in `angular/components`, we should
cache the downloaded Bazel version (from `bazelisk`).

This reduces the overhead of downloading Bazel, and also avoids
the dependency on the external download server. We should avoid
external server dependencies as much as possible (see how the yarn
registry was flaky in the past).

PR Close #36098
2020-03-18 10:01:50 -07:00
1aa5783a45 docs: adding a note on extra text interpolations and HTML tags in translations to Ivy guide (#36029)
This commit updates Ivy compatibility guide with additional note on extra text interpolations and HTML tags in translations.

PR Close #36029
2020-03-18 10:00:59 -07:00
67b9adfd1a docs(upgrade): remove outdated/non-applicable AOT section from upgrade guide (#36015)
The AOT compilation section of the `ngUpgrade` guide was
outdated/non-applicable. This commit hides the section to avoid confusion.
Fixing the section and re-introducing it is being tracked in #35989.

PR Close #36015
2020-03-18 10:00:02 -07:00
5007b97db6 build(docs-infra): clean up dependencies and npm scripts in systemjs docs examples (#36015)
Previously, the `package.json` files added as boilerplate to docs
example projects of type `systemjs` were incorrect/outdated. They
contained unused dependencies and npm scripts and omitted used
dependencies.

This is not a big issue, because these examples are not offered as live
StackBlitz examples or downloadable ZIP archives, but having incorrect
`package.json` files is confusing and makes it more complicated to
update these examples.

This commit updates the `package.json` templates for the `systemjs` docs
examples and other configuration files to include used dependencies (and
remove unused ones). It also removes unused npm scripts.

PR Close #36015
2020-03-18 10:00:02 -07:00
5e45061a94 build(docs-infra): update project structure to cli@9 12/12 (dependencies) (#36015)
Update dependencies.
Also, disable AOT tests for `systemjs`-type examples in Ivy mode,
because our current setup does not work with v9. See #35989 for details.

Fixes #34382
Fixes #34383

PR Close #36015
2020-03-18 10:00:02 -07:00
2132ee38e4 build(docs-infra): update project structure to cli@9 11/12 (angular.json) (#36015)
Update `angular.json`.

PR Close #36015
2020-03-18 10:00:02 -07:00
f6adc0c3f9 build(docs-infra): update project structure to cli@9 10/12 (tsconfig.json) (#36015)
Update `tsconfig[.*].json`.
Also, all make necessary changes to ensure the example apps can be
successfully built with the new, stricter type-checking options.

PR Close #36015
2020-03-18 10:00:01 -07:00
9afd360eba build(docs-infra): update project structure to cli@9 9/12 (tslint.json) (#36015)
Update `tslint.json`.

PR Close #36015
2020-03-18 10:00:01 -07:00
dbbc8ef8a6 build(docs-infra): update project structure to cli@9 8/12 (favicon.ico) (#36015)
Update `favicon.ico`.

PR Close #36015
2020-03-18 10:00:01 -07:00
9d22e2a445 build(docs-infra): update project structure to cli@9 7/12 (.gitignore, protractor.conf.js) (#36015)
Update configs (`.gitignore`, `protractor.conf.js`).

PR Close #36015
2020-03-18 10:00:01 -07:00
c9fd8e39f3 build(docs-infra): update project structure to cli@9 6/12 (index.html) (#36015)
Update `index.html` (mostly remove empty line).

PR Close #36015
2020-03-18 10:00:01 -07:00
e108646d43 build(docs-infra): update project structure to cli@9 5/12 (polyfills.ts) (#36015)
Update `polyfills.ts` (`import './zone-flags.ts'` --> `import './zone-flags'`).

PR Close #36015
2020-03-18 10:00:01 -07:00
2cb862447c build(docs-infra): update project structure to cli@9 4/12 (test.ts) (#36015)
Update `test.ts`.

PR Close #36015
2020-03-18 10:00:01 -07:00
fc325c49ec build(docs-infra): update project structure to cli@9 3/12 (title in a h1 tag) (#36015)
Make test description less implementation specific.

PR Close #36015
2020-03-18 10:00:01 -07:00
a8e936791b build(docs-infra): update project structure to cli@9 2/12 (fixture.debugElement.componentInstance) (#36015)
`fixture.debugElement.componentInstance` --> `fixture.componentInstance`

PR Close #36015
2020-03-18 10:00:01 -07:00
5fccb46f6f build(docs-infra): update project structure to cli@9 1/12 (app.po.ts) (#36015)
Update `app.po.ts`.

PR Close #36015
2020-03-18 10:00:01 -07:00
5a7ac8c3b9 build(docs-infra): avoid Karma error when loading scripts from code.angularjs.org (#36015)
In the example apps used in the `ngUpgrade` guide, the AngularJS files
are loaded in `index.html` from `https://code.angularjs.org/`. Latest
browsers prevent loading the scripts from a page running on localhost
due to CORS:

```
Access to script at 'https://code.angularjs.org/1.5.5/angular.js' from origin
'http://localhost:9876' has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
```

NOTE:
Loading the files from `code.angularjs.org` is not mentioned in the
guide, therefore it is not needed to mention this config change there.

PR Close #36015
2020-03-18 10:00:01 -07:00
21b8d6956a build(docs-infra): remove obsolete content from example-config.json files (#36015)
The `build` and `run` properties in `example-config.json` are only used
in example projects of type `systemjs`. In CLI-type projects, `build`
and `run` are ignored.

PR Close #36015
2020-03-18 10:00:01 -07:00
cc238e6377 build(docs-infra): remove obsolete content from example-config.json in setup example (#36015)
The `unittesting` property in `example-config.json` is a remnant of the
setup (before `aio/` was moved into the `angular/angular` repo) and has
no effect any more.

PR Close #36015
2020-03-18 10:00:01 -07:00
df7504ade1 build(docs-infra): remove unused ngmodule-faq and visual-studio-2015 examples (#36015)
PR Close #36015
2020-03-18 10:00:01 -07:00
fbed0a1471 build(docs-infra): remove unused test.html file from testing example (#36015)
This file was from back when the `testing` example was not based on the
Angular CLI and is not used any more.

PR Close #36015
2020-03-18 10:00:01 -07:00
4cde83188a build(docs-infra): remove unused jsconfig.json file (#36015)
PR Close #36015
2020-03-18 10:00:00 -07:00
3e08347d8a ci(docs-infra): use the regular (non-Ivy) Angular packages in test_docs_examples_ivy CI job (#36015)
The docs examples tests are run both with Ivy turned off and on. When
Ivy is turned on, ngcc is used to convert all dependencies (including
the Angular framework packages to Ivy).

Previously, in order to speed things up, the `test_docs_examples_ivy` CI
job would use Angular packages built with Ivy (from
`dist/packages-dist-ivy-aot`). This however was a deviation from what
happens in real-world applications.

This commit changes the `test_docs_examples_ivy` CI job to always use
the regular Angular packages (as published on npm) and use ngcc to
convert them to Ivy.

Relevant discussion:
https://github.com/angular/angular/pull/35091#discussion_r373775396

PR Close #36015
2020-03-18 10:00:00 -07:00
9e70bcb34f fix(ngcc): consistently delegate to TypeScript host for typing files (#36089)
When ngcc is compiling an entry-point, it uses a `ReflectionHost` that
is specific to its format, e.g. ES2015, ES5, UMD or CommonJS. During the
compilation of that entry-point however, the reflector may be used to
reflect into external libraries using their declaration files.

Up until now this was achieved by letting all `ReflectionHost` classes
consider their parent class for reflector queries, thereby ending up in
the `TypeScriptReflectionHost` that is a common base class for all
reflector hosts. This approach has proven to be prone to bugs, as
failing to call into the base class would cause incompatibilities with
reading from declaration files.

The observation can be made that there's only two distinct kinds of
reflection host queries:
1. the reflector query is about code that is part of the entry-point
   that is being compiled, or
2. the reflector query is for an external library that the entry-point
   depends on, in which case the information is reflected
   from the declaration files.

The `ReflectionHost` that was chosen for the entry-point should serve
only reflector queries for the first case, whereas a regular
`TypeScriptReflectionHost` should be used for the second case. This
avoids the problem where a format-specific `ReflectionHost` fails to
handle the second case correctly, as it isn't even considered for such
reflector queries.

This commit introduces a `ReflectionHost` that delegates to the
`TypeScriptReflectionHost` for AST nodes within declaration files,
otherwise delegating to the format-specific `ReflectionHost`.

Fixes #35078
Resolves FW-1859

PR Close #36089
2020-03-17 13:34:04 -07:00
1bc3893c65 test(ngcc): use "module" format property for ES5 bundles (#36089)
The format property for ES5 bundles should be "module" or "es5"/"esm5",
but was "main" instead. The "main" property is appropriate for CommonJS
and UMD bundles, not for ES5 bundles.

PR Close #36089
2020-03-17 13:34:04 -07:00
a1e00f82f4 build: fix ts-api-guardian golden approval not working on windows (#36115)
Currently on Windows, it's not possible to approve goldens in
`ts-api-guardian`. This is because paths are resolved relatively
to the working directory. In Windows, golden files are resolved
to the actual workspace directory. The current logic tries to
compute a relative path to the runfile from the working directory.

This causes the file paths to have a lot of parent directory
path segments. Eventually, when joined with the build workspace
directory, the paths end up being incorrect. e.g.

```
fileName = ../../../../../../projects/angular/golden/<..>/common.d.ts`
outFile = BUILD_WORKSPACE_DIR + fileName;
```

To fix this, we no longer deal with confusing relative paths, but
instead always use absolute file system paths.

Additionally, this fixes that new goldens are generated at the wrong
location on all platforms.

PR Close #36115
2020-03-17 12:38:25 -07:00
a1cae28283 build: fix saucelabs jobs that were broken by bazelisk change (#36109)
PR Close #36109
2020-03-17 12:28:02 -07:00
02281281a8 build: watch for sauce service failures when waiting for it to start (#36109)
Also add two targets to make it more convienent to tail & dump the sauce service logs: //tools/saucelabs:sauce_service_tail & //tools/saucelabs:sauce_service_log

PR Close #36109
2020-03-17 12:28:01 -07:00
22be967104 ci: run ts-circular-deps check in lint job on ci (#35647)
PR Close #35647
2020-03-17 12:27:07 -07:00
f5a5c36d3c ci: set up golden file for typescript circular dependencies (#35647)
Sets up a golden file for the TypeScript circular dependencies for
source files inside of the `packages/` folder.

Also sets up the appropriate Yarn shorthand scripts, and a codeowner
group that is soley responsible for verifying changes to the golden.

PR Close #35647
2020-03-17 12:27:07 -07:00
b7138c1ec5 build: remove rollup packaging from dev-infra (#35647)
The dev-infra package currently uses rollup for packaging. This has been
done initially as a way to workaround manifest paths being used in the
AMD JavaScript output.

The actual solution to this problem is setting module names that match
the `package.json` name. This ensures that the package can be consumed
correctly in Bazel, and through NPM. This allows us to get rid of the
rollup bundling, and we don't need to hard-code which dependencies
should be external or included.

Additionally, tools that are part of `dev-infra` can now specify
their external dependencies simply in the `package.json`. To reduce
version duplication, and out-of-sync versions, a new genrule has been
created that syncs the versions with the top-level project
`package.json`.

PR Close #35647
2020-03-17 12:27:07 -07:00
7aab399c84 refactor: move ts-circular-dependencies tool to dev-infra (#35647)
PR Close #35647
2020-03-17 12:27:07 -07:00
9ea53803f7 build: create tool for validating typescript circular dependencies (#35647)
Creates a tool for validating TypeScript circular dependencies. The tool
has been designed in a way that allows us to slowly burn down the amount
of circular dependencies while ensuring that we don't regress.

The tool doesn't rely on Madge since it doesn't provide a programmatic
way for doing path mapping. We need path mapping since we also want to
check for cycles across different entry-points or packages. The tool
uses the TypeScript AST to manually collect cycles. This code is not
a lot of bloat and also gives us more flexibility (if we ever need it).

Closes #35041.

PR Close #35647
2020-03-17 12:27:06 -07:00
34a17f3699 Revert "build: fix ts-api-guardian golden approval not working on windows (#36096)" (#36113)
This reverts commit f862536ec4.

Reverted due to test failures that have shown up in the Windows CI Jobs
that don't run on pull requests. A follow-up will be sent that re-adds
the changes w/ fixes for the windows test job.

PR Close #36113
2020-03-17 11:18:07 -07:00
f862536ec4 build: fix ts-api-guardian golden approval not working on windows (#36096)
Currently on Windows, it's not possible to approve goldens in
`ts-api-guardian`. This is because paths are resolved relatively
to the working directory. In Windows, golden files are resolved
to the actual workspace directory. The current logic tries to
compute a relative path to the runfile from the working directory.

This causes the file paths to have a lot of parent directory
path segments. Eventually, when joined with the build workspace
directory, the paths end up being incorrect. e.g.

```
fileName = ../../../../../../projects/angular/golden/<..>/common.d.ts`
outFile = BUILD_WORKSPACE_DIR + fileName;
```

To fix this, we no longer deal with confusing relative paths, but
instead always use absolute file system paths.

Additionally, this fixes that new goldens are generated at the wrong
location on all platforms.

PR Close #36096
2020-03-17 10:42:09 -07:00
afc9839f43 build(zone.js): Update zone.js release process to use google-wombot (#36110)
Updated the docs to use the `google-wombot` release process.

PR Close #36110
2020-03-17 10:40:32 -07:00
e3ecdc6a63 feat(bazel): transform generated shims (in Ivy) with tsickle (#35975)
Currently, when Angular code is built with Bazel and with Ivy, generated
factory shims (.ngfactory files) are not processed via the majority of
tsickle's transforms. This is a subtle effect of the build infrastructure,
but it boils down to a TsickleHost method `shouldSkipTsickleProcessing`.

For ngc_wrapped builds (Bazel + Angular), this method is defined in the
`@bazel/typescript` (aka bazel rules_typescript) implementation of
`CompilerHost`. The default behavior is to skip tsickle processing for files
which are not present in the original `srcs[]` of the build rule. In
Angular's case, this includes all generated shim files.

For View Engine factories this is probably desirable as they're quite
complex and they've never been tested with tsickle. Ivy factories however
are smaller and very straightforward, and it makes sense to treat them like
any other output.

This commit adjusts two independent implementations of
`shouldSkipTsickleProcessing` to enable transformation of Ivy shims:

* in `@angular/bazel` aka ngc_wrapped, the upstream `@bazel/typescript`
  `CompilerHost` is patched to treat .ngfactory files the same as their
  original source file, with respect to tsickle processing.

  It is currently not possible to test this change as we don't have any test
  that inspects tsickle output with bazel. It will be extensively tested in
  g3.

* in `ngc`, Angular's own implementation is adjusted to allow for the
  processing of shims when compiling with Ivy. This enables a unit test to
  be written to validate the correct behavior of tsickle when given a host
  that's appropriately configured to process factory shims.

For ngtsc-as-a-plugin, a similar fix will need to be submitted upstream in
tsc_wrapped.

PR Close #35848

PR Close #35975
2020-03-17 10:17:28 -07:00
4af2a068c5 build: update to latest @bazel/ibazel version (#36097)
Updates to the latest `@bazel/ibazel` version that properly
resolves local `@bazel/bazelisk` installations.

The support for this temporarily broke from `0.12.0` to `0.12.2`.
https://github.com/bazelbuild/bazel-watcher/issues/352.

PR Close #36097
2020-03-17 09:33:02 -07:00
52d66ea5a9 feat(dev-infra): create common config file loading util (#36091)
Create a common config file loading utility function and the
necessary util directory.  This util directory can provide common
utility functions for usage inside of the dev-infra package.

PR Close #36091
2020-03-17 09:30:31 -07:00
61c37954c6 docs: remove browserstack badge from readme (#35684)
We don't run tests on Browserstack for this repository. Also the
badge was referring to a non-existent project.

This removes the badge since we don't need it anymore, and rather
we should generate a new one for repositories like `angular/components`
where browserstack is actually used, and where the badge can provide
useful information.

Closes #28287.

PR Close #35684
2020-03-17 09:29:43 -07:00
acc483e2eb feat(language-service): improve non-callable error message (#35271)
This commit improves the context of a non-callable function error
message by providing the affected call target and its non-callable type.

PR Close #35271
2020-03-17 09:28:59 -07:00
168a393589 refactor(core): misc refactoring to support upcoming changes to improve synthetic host bindings (#35884)
This commit performs a few updates to internal functions that would be required in upcoming changes to support synthetic host bindings in Directives.

* the `elementPropertyInternal` function was refactored to accept renderer as an argument (prior to that, there was a function that loads the renderer in some specific way for animation bindings)
* `elementPropertyInternal`, `elementAttributeInternal` and `listenerInternal` functions were updated to have a fixed set of arguments (for better performance)
* `elementPropertyInternal` and `elementAttributeInternal` functions were updated to take `tNode` as an argument instead of passing node index (that was used to retrieve `tNode` internally), in some cases we already have `tNode` available or we can retrieve it from the state

The refactoring was triggered by the need to pass different renderers to the `elementPropertyInternal` to support synthetic host bindings in Directives (see this comment for additional context: https://github.com/angular/angular/pull/35568/files#r388034584).

PR Close #35884
2020-03-16 16:44:04 -07:00
3110 changed files with 100799 additions and 80997 deletions

View File

@ -33,6 +33,11 @@ build --incompatible_strict_action_env
run --incompatible_strict_action_env
test --incompatible_strict_action_env
# Do not build runfile trees by default. If an execution strategy relies on runfile
# symlink teee, the tree is created on-demand. See: https://github.com/bazelbuild/bazel/issues/6627
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df
build --nobuild_runfile_links
###############################
# Release support #
# Turn on these settings with #
@ -42,7 +47,7 @@ test --incompatible_strict_action_env
# Releases should always be stamped with version control info
# This command assumes node on the path and is a workaround for
# https://github.com/bazelbuild/bazel/issues/4802
build:release --workspace_status_command="node ./tools/bazel_stamp_vars.js"
build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp"
build:release --stamp
###############################

View File

@ -14,7 +14,8 @@ build --repository_cache=/home/circleci/bazel_repository_cache
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
build --local_resources=14336,8.0,1.0
build --local_cpu_resources=8
build --local_ram_resources=14336
# All build executed remotely should be done using our RBE configuration.
build:remote --google_default_credentials

View File

@ -10,6 +10,10 @@ try-import %workspace%/.circleci/bazel.common.rc
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
build --repository_cache=C:/Users/circleci/bazel_repository_cache
# Manually set the local resources used in windows CI runs
build --local_ram_resources=13500
build --local_cpu_resources=4
# All windows jobs run on master and should use http caching
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
build --remote_accept_cached=true

View File

@ -22,15 +22,18 @@ version: 2.1
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
var_3: &cache_key v4-angular-node-12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
var_4: &cache_key_fallback v4-angular-node-12-
var_3_win: &cache_key_win v5-angular-win-node-12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
var_4_win: &cache_key_win_fallback v5-angular-win-node-12-
var_3: &cache_key v7-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
# We invalidate the cache if the Bazel version changes because otherwise the `bazelisk` cache
# folder will contain all previously used versions and ultimately cause the cache restoring to
# be slower due to its growing size.
var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
# 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.
var_5: &components_repo_unit_tests_cache_key v5-angular-components-598db096e668aa7e9debd56eedfd127b7a55e371
var_6: &components_repo_unit_tests_cache_key_fallback v5-angular-components-
var_5: &components_repo_unit_tests_cache_key v7-angular-components-448523bffffecd2b53a3d2854c3051b6b7a3934f
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
# `build-ivy-npm-packages`.
@ -223,6 +226,7 @@ jobs:
executor: default-executor
steps:
- checkout
- init_environment
- run:
name: Rebase PR on target branch
# After checkout, rebase on top of target branch.
@ -232,7 +236,7 @@ jobs:
git config user.name "angular-ci"
git config user.email "angular-ci"
# Rebase PR on top of target branch.
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
node tools/rebase-pr.js
else
echo "This build is not over a PR, nothing to do."
fi
@ -241,7 +245,6 @@ jobs:
keys:
- *cache_key
- *cache_key_fallback
- init_environment
- run:
name: Running Yarn install
command: yarn install --frozen-lockfile --non-interactive
@ -269,14 +272,11 @@ jobs:
- custom_attach_workspace
- init_environment
- run: 'yarn bazel:format -mode=check ||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
# Run the skylark linter to check our Bazel rules
- run: 'yarn bazel:lint ||
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
- run: yarn lint
- run: node tools/pullapprove/verify.js
- run: yarn -s tslint
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
- run: yarn -s ts-circular-deps:check
- run: yarn -s ng-dev pullapprove verify
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
test:
executor:
@ -347,7 +347,7 @@ jobs:
# See /tools/saucelabs/README.md for more info
command: |
yarn bazel run //tools/saucelabs:sauce_service_setup
TESTS=$(./node_modules/.bin/bazel query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "ivy-only", ...) except attr("tags", "fixme-saucelabs-ve", ...)')
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "ivy-only", ...) except attr("tags", "fixme-saucelabs-ve", ...)')
yarn bazel test --config=saucelabs ${TESTS}
yarn bazel run //tools/saucelabs:sauce_service_stop
no_output_timeout: 40m
@ -371,7 +371,7 @@ jobs:
# See /tools/saucelabs/README.md for more info
command: |
yarn bazel run //tools/saucelabs:sauce_service_setup
TESTS=$(./node_modules/.bin/bazel query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "no-ivy-aot", ...) except attr("tags", "fixme-saucelabs-ivy", ...)')
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "no-ivy-aot", ...) except attr("tags", "fixme-saucelabs-ivy", ...)')
yarn bazel test --config=saucelabs --config=ivy ${TESTS}
yarn bazel run //tools/saucelabs:sauce_service_stop
no_output_timeout: 40m
@ -384,10 +384,6 @@ jobs:
- custom_attach_workspace
- init_environment
- install_chrome_libs
# Compile dependencies to ivy
# Running `ngcc` here (instead of implicitly via `ng build`) allows us to take advantage of
# the parallel, async mode speed-up (~20-25s on CI).
- run: yarn --cwd aio ngcc --properties es2015
# Build aio
- run: yarn --cwd aio build --progress=false
# Lint the code
@ -450,7 +446,7 @@ jobs:
test_docs_examples:
parameters:
ivy:
viewengine:
type: boolean
default: false
executor:
@ -463,21 +459,10 @@ jobs:
- install_chrome_libs
# Install aio
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
- when:
condition: << parameters.ivy >>
steps:
# Rename the "dist/*-dist-ivy-aot" packages directories (persisted to the workspace by
# the `build-ivy-npm-packages` job) to "dist/*-dist" as the AIO package installer
# picks up the locally built packages from that location.
# *Note*: We could also adjust the packages installer, but given we won't have
# two different folders of Angular distributions in the future, we should keep
# the packages installer unchanged.
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
- run: mv dist/zone.js-dist-ivy-aot dist/zone.js-dist
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.ivy >>--ivy<</ parameters.ivy >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.viewengine >>--viewengine<</ parameters.viewengine >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
aio_preview:
@ -539,6 +524,7 @@ jobs:
- "node_modules"
- "aio/node_modules"
- "~/bazel_repository_cache"
- "~/.cache/bazelisk"
# Build the ivy npm packages.
build-ivy-npm-packages:
@ -828,10 +814,10 @@ workflows:
requires:
- build-npm-packages
- test_docs_examples:
name: test_docs_examples_ivy
ivy: true
name: test_docs_examples_viewengine
viewengine: true
requires:
- build-ivy-npm-packages
- build-npm-packages
- aio_preview:
# Only run on PR builds. (There can be no previews for non-PR builds.)
<<: *only_on_pull_requests
@ -856,7 +842,7 @@ workflows:
- test_aio_local
- test_aio_local_viewengine
- test_docs_examples
- test_docs_examples_ivy
- test_docs_examples_viewengine
# Get the artifacts to publish from the build-packages-dist job
# since the publishing script expects the legacy outputs layout.
- build-npm-packages

View File

@ -3,6 +3,7 @@
# Variables
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
readonly bashEnvCachePath="$projectDir/.circleci/bash_env_cache";
# Load helpers and make them available everywhere (through `$BASH_ENV`).
source $envHelpersPath;
@ -14,6 +15,7 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
####################################################################################################
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
####################################################################################################
setPublicVar CI "$CI"
setPublicVar PROJECT_ROOT "$projectDir";
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
# This is the branch being built; e.g. `pull/12345` for PR builds.
@ -22,10 +24,14 @@ setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
# workflows of such builds).
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
####################################################################################################
@ -68,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_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
setPublicVar COMPONENTS_REPO_COMMIT "598db096e668aa7e9debd56eedfd127b7a55e371"
setPublicVar COMPONENTS_REPO_COMMIT "448523bffffecd2b53a3d2854c3051b6b7a3934f"
####################################################################################################

72
.dev-infra.json Normal file
View File

@ -0,0 +1,72 @@
{
"commitMessage": {
"maxLength": 120,
"minBodyLength": 100,
"types": [
"build",
"ci",
"docs",
"feat",
"fix",
"perf",
"refactor",
"release",
"style",
"test"
],
"scopes": [
"animations",
"bazel",
"benchpress",
"changelog",
"common",
"compiler",
"compiler-cli",
"core",
"dev-infra",
"docs-infra",
"elements",
"forms",
"http",
"language-service",
"localize",
"ngcc",
"packaging",
"platform-browser",
"platform-browser-dynamic",
"platform-server",
"platform-webworker",
"platform-webworker-dynamic",
"router",
"service-worker",
"upgrade",
"ve",
"zone.js"
]
},
"format": {
"clang-format": {
"matchers": [
"dev-infra/**/*.{js,ts}",
"packages/**/*.{js,ts}",
"!packages/zone.js",
"!packages/common/locales/**/*.{js,ts}",
"!packages/common/src/i18n/available_locales.ts",
"!packages/common/src/i18n/currencies.ts",
"!packages/common/src/i18n/locale_en.ts",
"modules/benchmarks/**/*.{js,ts}",
"modules/playground/**/*.{js,ts}",
"tools/**/*.{js,ts}",
"!tools/gulp-tasks/cldr/extract.js",
"!tools/public_api_guard/**/*.d.ts",
"!tools/ts-api-guardian/test/fixtures/**",
"./*.{js,ts}",
"!**/node_modules/**",
"!**/dist/**",
"!**/built/**",
"!shims_for_IE.js"
]
},
"buildifier": true
}
}

View File

@ -97,6 +97,12 @@
version: 3
# Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config.
meta:
1: &can-be-global-approved "\"global-approvers\" not in groups.approved"
2: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
# turn on 'draft' support
# https://docs.pullapprove.com/config/github-api-version/
# https://developer.github.com/v3/previews/#draft-pull-requests
@ -115,11 +121,49 @@ pullapprove_conditions:
groups:
# =========================================================
# Global Approvers
#
# All reviews performed for global approvals require using
# the `Reviewed-for:` specifier to set the approval
# specificity as documented at:
# https://docs.pullapprove.com/reviewed-for/
# =========================================================
global-approvers:
type: optional
reviewers:
teams:
- framework-global-approvers
reviews:
request: 0
required: 1
reviewed_for: required
# =========================================================
# Global Approvers For Docs
#
# All reviews performed for global docs approvals require
# using the `Reviewed-for:` specifier to set the approval
# specificity as documented at:
# https://docs.pullapprove.com/reviewed-for/
# =========================================================
global-docs-approvers:
type: optional
reviewers:
teams:
- framework-global-approvers-for-docs-only-changes
reviews:
request: 0
required: 1
reviewed_for: required
# =========================================================
# Framework: Animations
# =========================================================
fw-animations:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/animations/**',
@ -135,9 +179,6 @@ groups:
reviewers:
users:
- matsko
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -145,8 +186,10 @@ groups:
# =========================================================
fw-compiler:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
contains_any_globs(files.exclude('packages/compiler-cli/ngcc/**'), [
'packages/compiler/**',
'packages/examples/compiler/**',
'packages/compiler-cli/**',
@ -161,9 +204,6 @@ groups:
- AndrewKushnir
- JoostK
- kara
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -171,19 +211,31 @@ groups:
# =========================================================
fw-ngcc:
conditions:
- >
contains_any_globs(files, [
'packages/compiler-cli/ngcc/**'
])
- *can-be-global-approved
- *can-be-global-docs-approved
- files.include('packages/compiler-cli/ngcc/**')
reviewers:
users:
- alxhub
- gkalpak
- JoostK
- petebacondarwin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
# Framework: Migrations
# =========================================================
fw-migrations:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- files.include("packages/core/schematics/**")
reviewers:
users:
- alxhub
- crisbeto
- devversion
- kara
# =========================================================
@ -191,8 +243,10 @@ groups:
# =========================================================
fw-core:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
contains_any_globs(files.exclude("packages/core/schematics/**"), [
'packages/core/**',
'packages/examples/core/**',
'packages/common/**',
@ -258,7 +312,6 @@ groups:
'aio/content/examples/ngmodules/**',
'aio/content/guide/ngmodule-api.md',
'aio/content/guide/ngmodule-faq.md',
'aio/content/examples/ngmodule-faq/**',
'aio/content/guide/ngmodule-vs-jsmodule.md',
'aio/content/guide/module-types.md',
'aio/content/guide/template-syntax.md',
@ -301,9 +354,6 @@ groups:
- kara
- mhevery
- pkozlowski-opensource
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -311,10 +361,11 @@ groups:
# =========================================================
fw-http:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/common/http/**',
'packages/http/**',
'packages/examples/http/**',
'aio/content/guide/http.md',
'aio/content/examples/http/**',
@ -324,9 +375,6 @@ groups:
users:
- alxhub
- IgorMinar
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -334,6 +382,8 @@ groups:
# =========================================================
fw-elements:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/elements/**',
@ -345,9 +395,6 @@ groups:
users:
- andrewseguin
- gkalpak
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -355,6 +402,8 @@ groups:
# =========================================================
fw-forms:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/forms/**',
@ -378,9 +427,6 @@ groups:
reviewers:
users:
- AndrewKushnir
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -388,6 +434,8 @@ groups:
# =========================================================
fw-i18n:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/core/src/i18n/**',
@ -412,9 +460,6 @@ groups:
- AndrewKushnir
- mhevery
- petebacondarwin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -422,6 +467,8 @@ groups:
# =========================================================
fw-platform-server:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/platform-server/**',
@ -432,9 +479,6 @@ groups:
users:
- alxhub
- kyliau
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -442,27 +486,30 @@ groups:
# =========================================================
fw-router:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/router/**',
'packages/examples/router/**',
'aio/content/guide/router.md',
'aio/content/guide/router-tutorial.md',
'aio/content/examples/router-tutorial/**',
'aio/content/examples/router/**',
'aio/content/images/guide/router/**'
])
reviewers:
users:
- atscott
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
# Framework: Service Worker
# =========================================================
fw-server-worker:
fw-service-worker:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/service-worker/**',
@ -481,9 +528,6 @@ groups:
- alxhub
- gkalpak
- IgorMinar
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -491,6 +535,8 @@ groups:
# =========================================================
fw-upgrade:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/upgrade/**',
@ -512,9 +558,6 @@ groups:
users:
- gkalpak
- petebacondarwin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -522,6 +565,8 @@ groups:
# =========================================================
fw-testing:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'**/testing/**',
@ -531,12 +576,10 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- IgorMinar
- kara
- pkozlowski-opensource
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -544,6 +587,7 @@ groups:
# =========================================================
fw-benchmarks:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'modules/benchmarks/**'
@ -553,8 +597,6 @@ groups:
- IgorMinar
- kara
- pkozlowski-opensource
teams:
- ~framework-global-approvers
# =========================================================
@ -562,6 +604,7 @@ groups:
# =========================================================
fw-playground:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'modules/playground/**'
@ -570,8 +613,6 @@ groups:
users:
- IgorMinar
- kara
teams:
- ~framework-global-approvers
# =========================================================
@ -579,6 +620,8 @@ groups:
# =========================================================
fw-security:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/core/src/sanitization/**',
@ -593,15 +636,14 @@ groups:
users:
- IgorMinar
- mhevery
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
# Bazel
# =========================================================
bazel:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/bazel/**',
@ -612,9 +654,6 @@ groups:
- IgorMinar
- josephperrott
- kyliau
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -622,6 +661,8 @@ groups:
# =========================================================
language-service:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/language-service/**',
@ -632,9 +673,6 @@ groups:
users:
- ayazhafiz
- kyliau
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -642,6 +680,8 @@ groups:
# =========================================================
zone-js:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/zone.js/**',
@ -651,9 +691,6 @@ groups:
users:
- JiaLiPassion
- mhevery
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -661,6 +698,8 @@ groups:
# =========================================================
benchpress:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'packages/benchpress/**'
@ -668,9 +707,6 @@ groups:
reviewers:
users:
- alxhub
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -678,6 +714,7 @@ groups:
# =========================================================
integration-tests:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'integration/**'
@ -688,8 +725,6 @@ groups:
- josephperrott
- kara
- mhevery
teams:
- ~framework-global-approvers
# =========================================================
@ -697,6 +732,8 @@ groups:
# =========================================================
docs-getting-started-and-tutorial:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/guide/setup-local.md',
@ -720,9 +757,6 @@ groups:
- aikidave
- IgorMinar
- StephenFluin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -730,6 +764,8 @@ groups:
# =========================================================
docs-marketing:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/marketing/**',
@ -743,9 +779,6 @@ groups:
users:
- IgorMinar
- StephenFluin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -753,6 +786,8 @@ groups:
# =========================================================
docs-observables:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/guide/observables.md',
@ -769,9 +804,6 @@ groups:
reviewers:
users:
- alxhub
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -779,6 +811,8 @@ groups:
# =========================================================
docs-packaging-and-releasing:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'docs/PUBLIC_API.md',
@ -803,9 +837,6 @@ groups:
users:
- IgorMinar
- kara
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -813,6 +844,8 @@ groups:
# =========================================================
docs-cli:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/cli/**',
@ -826,7 +859,7 @@ groups:
'aio/content/images/guide/deployment/**',
'aio/content/guide/file-structure.md',
'aio/content/guide/ivy.md',
'aio/content/guide/web-worker.md'
'aio/content/guide/web-worker.md',
'aio/content/guide/workspace-config.md',
])
reviewers:
@ -834,9 +867,6 @@ groups:
- clydin
- IgorMinar
- mgechev
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -844,6 +874,8 @@ groups:
# =========================================================
docs-libraries:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/guide/creating-libraries.md',
@ -855,9 +887,6 @@ groups:
- alan-agius4
- IgorMinar
- mgechev
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -865,6 +894,8 @@ groups:
# =========================================================
docs-schematics:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/guide/schematics.md',
@ -878,9 +909,6 @@ groups:
- alan-agius4
- IgorMinar
- mgechev
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -888,6 +916,8 @@ groups:
# =========================================================
docs-infra:
conditions:
- *can-be-global-approved
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/*',
@ -901,17 +931,13 @@ groups:
'aio/content/guide/docs-style-guide.md',
'aio/content/examples/docs-style-guide/**',
'aio/content/images/guide/docs-style-guide/**',
'aio/content/guide/visual-studio-2015.md',
'aio/content/examples/visual-studio-2015/**'
'aio/content/guide/visual-studio-2015.md'
])
reviewers:
users:
- gkalpak
- IgorMinar
- petebacondarwin
teams:
- ~framework-global-approvers
- ~framework-global-approvers-for-docs-only-changes
# =========================================================
@ -919,6 +945,7 @@ groups:
# =========================================================
dev-infra:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'*',
@ -954,12 +981,12 @@ groups:
'tools/build/**',
'tools/circular_dependency_test/**',
'tools/contributing-stats/**',
'tools/components/**',
'tools/gulp-tasks/**',
'tools/ng_rollup_bundle/**',
'tools/ngcontainer/**',
'tools/npm/**',
'tools/npm_integration_test/**',
'tools/pullapprove/**',
'tools/rxjs/**',
'tools/saucelabs/**',
'tools/size-tracking/**',
@ -969,7 +996,6 @@ groups:
'tools/ts-api-guardian/**',
'tools/tslint/**',
'tools/utils/**',
'tools/validate-commit-message/**',
'tools/yarn/**',
'tools/*',
'**/*.bzl',
@ -982,8 +1008,6 @@ groups:
- gkalpak
- IgorMinar
- josephperrott
teams:
- ~framework-global-approvers
# =========================================================
@ -991,6 +1015,7 @@ groups:
# =========================================================
public-api:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'goldens/public-api/**',
@ -1003,8 +1028,6 @@ groups:
reviewers:
users:
- IgorMinar
teams:
- ~framework-global-approvers
# ================================================
@ -1012,17 +1035,32 @@ groups:
# ================================================
size-tracking:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'aio/scripts/_payload-limits.json',
'integration/_payload-limits.json'
'goldens/size-tracking/**'
])
reviewers:
users:
- IgorMinar
- kara
teams:
- ~framework-global-approvers
# ================================================
# Circular dependencies
# ================================================
circular-dependencies:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'goldens/circular-deps/packages.json'
])
reviewers:
users:
- IgorMinar
- josephperrott
- kara
####################################################################################
@ -1034,6 +1072,7 @@ groups:
# =========================================================
code-ownership:
conditions:
- *can-be-global-approved
- >
contains_any_globs(files, [
'.pullapprove.yml'
@ -1041,8 +1080,6 @@ groups:
reviewers:
users:
- IgorMinar
teams:
- ~framework-global-approvers
# ====================================================
@ -1050,6 +1087,7 @@ groups:
# ====================================================
fallback:
conditions:
- *can-be-global-approved
# Groups which are found to have matching conditions are `active`
# according to PullApprove. If no groups are matched and considered
# active, we still want to have a review occur.
@ -1057,5 +1095,3 @@ groups:
reviewers:
users:
- IgorMinar
teams:
- ~framework-global-approvers

View File

@ -34,7 +34,7 @@
"name": "IVY:packages/core/test/acceptance",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazel",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
@ -51,7 +51,7 @@
"name": "IVY:packages/core/test/render3",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazel",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
@ -68,7 +68,7 @@
"name": "IVY:packages/core/test",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazel",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",

View File

@ -6,7 +6,7 @@
{
"label": "IVY:packages/core/test/...",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
@ -23,7 +23,7 @@
{
"label": "VE:packages/core/test/...",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test",
@ -39,7 +39,7 @@
{
"label": "IVY:packages/core/test/acceptance",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
@ -54,7 +54,7 @@
{
"label": "VE:packages/core/test/acceptance",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test/acceptance",
@ -68,7 +68,7 @@
{
"label": "IVY:packages/core/test",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
@ -83,7 +83,7 @@
{
"label": "VE:packages/core/test",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test",
@ -97,7 +97,7 @@
{
"label": "IVY:packages/core/test/render3",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazel",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",

View File

@ -34805,15 +34805,27 @@ function hasMergeConflicts(str) {
function parse(str, fileLoc) {
const parser = new Parser(str, fileLoc);
parser.next();
try {
return parser.parse();
} catch (error1) {
if (!fileLoc.endsWith(`.yml`)) {
try {
return safeLoad(str, {
schema: FAILSAFE_SCHEMA
});
} catch (error2) {
throw error1;
return parser.parse();
} catch (error1) {
try {
return safeLoad(str, {
schema: FAILSAFE_SCHEMA
});
} catch (error2) {
throw error1;
}
}
} else {
const result = safeLoad(str, {
schema: FAILSAFE_SCHEMA
});
if (typeof result === 'object') {
return result;
} else {
return {};
}
}
}
@ -46666,7 +46678,7 @@ function mkdirfix (name, opts, cb) {
/* 194 */
/***/ (function(module, exports) {
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.21.1","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.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"}}}
/***/ }),
/* 195 */
@ -69876,12 +69888,12 @@ function getRcConfigForFolder(cwd) {
}
function loadRcFile(fileText, filePath) {
var _parse = (0, (_lockfile || _load_lockfile()).parse)(fileText, 'yarnrc');
var _parse = (0, (_lockfile || _load_lockfile()).parse)(fileText, filePath);
let values = _parse.object;
if (filePath.match(/\.yml$/)) {
if (filePath.match(/\.yml$/) && typeof values.yarnPath === 'string') {
values = { 'yarn-path': values.yarnPath };
}
@ -74848,7 +74860,20 @@ let run = exports.run = (() => {
} else {
let suggestion;
for (const commandName in scripts) {
for (var _iterator9 = scripts.keys(), _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
var _ref16;
if (_isArray9) {
if (_i9 >= _iterator9.length) break;
_ref16 = _iterator9[_i9++];
} else {
_i9 = _iterator9.next();
if (_i9.done) break;
_ref16 = _i9.value;
}
const commandName = _ref16;
const steps = leven(commandName, action);
if (steps < 2) {
suggestion = commandName;
@ -74933,19 +74958,19 @@ let run = exports.run = (() => {
const printedCommands = new Map();
for (var _iterator9 = pkgCommands, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
var _ref16;
for (var _iterator10 = pkgCommands, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
var _ref17;
if (_isArray9) {
if (_i9 >= _iterator9.length) break;
_ref16 = _iterator9[_i9++];
if (_isArray10) {
if (_i10 >= _iterator10.length) break;
_ref17 = _iterator10[_i10++];
} else {
_i9 = _iterator9.next();
if (_i9.done) break;
_ref16 = _i9.value;
_i10 = _iterator10.next();
if (_i10.done) break;
_ref17 = _i10.value;
}
const pkgCommand = _ref16;
const pkgCommand = _ref17;
const action = scripts.get(pkgCommand);
invariant(action, 'Action must exists');
@ -76076,6 +76101,11 @@ class TarballFetcher extends (_baseFetcher || _load_baseFetcher()).default {
chown: false, // don't chown. just leave as it is
map: header => {
header.mtime = now;
if (header.linkname) {
const basePath = path.posix.dirname(path.join('/', header.name));
const jailPath = path.posix.join(basePath, header.linkname);
header.linkname = path.posix.relative('/', jailPath);
}
return header;
},
fs: patchedFs
@ -78409,6 +78439,11 @@ class RequestManager {
rejectNext(err);
};
const rejectWithoutUrl = function rejectWithoutUrl(err) {
err.message = err.message;
rejectNext(err);
};
const queueForRetry = reason => {
const attempts = params.retryAttempts || 0;
if (attempts >= this.maxRetryAttempts - 1) {
@ -78464,6 +78499,11 @@ class RequestManager {
}
}
if (res.statusCode === 401 && res.caseless && res.caseless.get('server') === 'GitHub.com') {
const message = `${res.body.message}. If using GITHUB_TOKEN in your env, check that it is valid.`;
rejectWithoutUrl(new Error(this.reporter.lang('unauthorizedResponse', res.caseless.get('server'), message)));
}
if (res.statusCode === 401 && res.headers['www-authenticate']) {
const authMethods = res.headers['www-authenticate'].split(/,\s*/).map(s => s.toLowerCase());
@ -96966,12 +97006,14 @@ function _load_asyncToGenerator() {
let run = exports.run = (() => {
var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, args) {
if (flags.install) {
const installVersion = flags[`2`] ? `berry` : flags.install;
if (installVersion) {
const lockfilePath = path.resolve(config.cwd, 'yarn.lock');
if (!(yield (_fs || _load_fs()).exists(lockfilePath))) {
yield (_fs || _load_fs()).writeFile(lockfilePath, '');
}
yield (_child || _load_child()).spawn((_constants || _load_constants()).NODE_BIN_PATH, [process.argv[1], 'policies', 'set-version', flags.install], {
yield (_child || _load_child()).spawn((_constants || _load_constants()).NODE_BIN_PATH, [process.argv[1], 'policies', 'set-version', installVersion], {
stdio: 'inherit',
cwd: config.cwd
});
@ -97266,6 +97308,7 @@ function setFlags(commander) {
commander.option('-y, --yes', 'use default options');
commander.option('-p, --private', 'use default options and private true');
commander.option('-i, --install <value>', 'install a specific Yarn release');
commander.option('-2', 'generates the project using Yarn 2');
}
function hasWrapper(commander, args) {
@ -98254,6 +98297,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
let bundleUrl;
let bundleVersion;
let isV2 = false;
if (range === 'nightly' || range === 'nightlies') {
bundleUrl = 'https://nightly.yarnpkg.com/latest.js';
@ -98261,10 +98305,18 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
} else if (range === 'berry' || range === 'v2' || range === '2') {
bundleUrl = 'https://github.com/yarnpkg/berry/raw/master/packages/berry-cli/bin/berry.js';
bundleVersion = 'berry';
isV2 = true;
} else {
const releases = yield fetchReleases(config, {
includePrereleases: allowRc
});
let releases = [];
try {
releases = yield fetchReleases(config, {
includePrereleases: allowRc
});
} catch (e) {
reporter.error(e.message);
return;
}
const release = releases.find(function (release) {
// $FlowFixMe
@ -98285,7 +98337,6 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
reporter.log(`Downloading ${chalk.green(bundleUrl)}...`);
const bundle = yield fetchBundle(config, bundleUrl);
const rc = (0, (_rc || _load_rc()).getRcConfigForFolder)(config.lockfileFolder);
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`);
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
@ -98293,10 +98344,22 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
yield (_fs || _load_fs()).chmod(yarnPath, 0o755);
const rcPath = `${config.lockfileFolder}/.yarnrc`;
reporter.log(`Updating ${chalk.magenta(rcPath)}...`);
rc['yarn-path'] = path.relative(config.lockfileFolder, yarnPath);
yield (_fs || _load_fs()).writeFilePreservingEol(rcPath, `${(0, (_lockfile || _load_lockfile()).stringify)(rc)}\n`);
const targetPath = path.relative(config.lockfileFolder, yarnPath).replace(/\\/g, '/');
if (isV2) {
const rcPath = `${config.lockfileFolder}/.yarnrc.yml`;
reporter.log(`Updating ${chalk.magenta(rcPath)}...`);
yield (_fs || _load_fs()).writeFilePreservingEol(rcPath, `yarnPath: ${JSON.stringify(targetPath)}\n`);
} else {
const rcPath = `${config.lockfileFolder}/.yarnrc`;
reporter.log(`Updating ${chalk.magenta(rcPath)}...`);
const rc = (0, (_rc || _load_rc()).getRcConfigForFolder)(config.lockfileFolder);
rc['yarn-path'] = targetPath;
yield (_fs || _load_fs()).writeFilePreservingEol(rcPath, `${(0, (_lockfile || _load_lockfile()).stringify)(rc)}\n`);
}
reporter.log(`Done!`);
})();
@ -99619,11 +99682,11 @@ let run = exports.run = (() => {
throw new (_errors || _load_errors()).MessageError(reporter.lang('workspaceRootNotFound', config.cwd));
}
if (flags.originalArgs < 1) {
if (args.length < 1) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('workspaceMissingWorkspace'));
}
if (flags.originalArgs < 2) {
if (args.length < 2) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('workspaceMissingCommand'));
}
@ -99632,7 +99695,7 @@ let run = exports.run = (() => {
const workspaces = yield config.resolveWorkspaces(workspaceRootFolder, manifest);
var _ref2 = flags.originalArgs || [];
var _ref2 = args || [];
const workspaceName = _ref2[0],
rest = _ref2.slice(1);
@ -99818,28 +99881,23 @@ let runScript = exports.runScript = (() => {
const workspaces = yield config.resolveWorkspaces(workspaceRootFolder, manifest);
try {
var _ref6 = flags.originalArgs || [];
const _ = _ref6[0],
rest = _ref6.slice(1);
for (var _iterator4 = Object.keys(workspaces), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
var _ref7;
var _ref6;
if (_isArray4) {
if (_i4 >= _iterator4.length) break;
_ref7 = _iterator4[_i4++];
_ref6 = _iterator4[_i4++];
} else {
_i4 = _iterator4.next();
if (_i4.done) break;
_ref7 = _i4.value;
_ref6 = _i4.value;
}
const workspaceName = _ref7;
const workspaceName = _ref6;
const loc = workspaces[workspaceName].loc;
reporter.log(`${os.EOL}> ${workspaceName}`);
yield (_child || _load_child()).spawn((_constants2 || _load_constants2()).NODE_BIN_PATH, [(_constants2 || _load_constants2()).YARN_BIN_PATH, ...rest], {
yield (_child || _load_child()).spawn((_constants2 || _load_constants2()).NODE_BIN_PATH, [(_constants2 || _load_constants2()).YARN_BIN_PATH, 'run', ...args], {
stdio: 'inherit',
cwd: loc
});
@ -100059,7 +100117,11 @@ let main = exports.main = (() => {
commandName = 'install';
isKnownCommand = true;
}
if (commandName === 'set' && args[0] === 'version') {
commandName = 'policies';
args.splice(0, 1, 'set-version');
isKnownCommand = true;
}
if (!isKnownCommand) {
// if command is not recognized, then set default to `run`
args.unshift(commandName);
@ -100070,15 +100132,20 @@ let main = exports.main = (() => {
let warnAboutRunDashDash = false;
// we are using "yarn <script> -abc", "yarn run <script> -abc", or "yarn node -abc", we want -abc
// to be script options, not yarn options
const PROXY_COMMANDS = new Set([`run`, `create`, `node`]);
if (PROXY_COMMANDS.has(commandName)) {
// PROXY_COMMANDS is a map of command name to the number of preservedArgs
const PROXY_COMMANDS = {
run: 1, // yarn run {command}
create: 1, // yarn create {project}
node: 0, // yarn node
workspaces: 1, // yarn workspaces {command}
workspace: 2 // yarn workspace {package} {command}
};
if (PROXY_COMMANDS.hasOwnProperty(commandName)) {
if (endArgs.length === 0) {
let preservedArgs = 0;
// the "run" and "create" command take one argument that we want to parse as usual (the
// script/package name), hence the splice(1)
if (command === (_index3 || _load_index3()).default.run || command === (_index3 || _load_index3()).default.create) {
preservedArgs += 1;
}
// $FlowFixMe doesn't like that PROXY_COMMANDS doesn't have keys for all commands.
let preservedArgs = PROXY_COMMANDS[commandName];
// If the --into option immediately follows the command (or the script name in the "run/create"
// case), we parse them as regular options so that we can cd into them
if (args[preservedArgs] === `--into`) {
@ -100090,7 +100157,6 @@ let main = exports.main = (() => {
}
}
(_commander || _load_commander()).default.originalArgs = args;
args = [...preCommandArgs, ...args];
command.setFlags((_commander || _load_commander()).default);
@ -100532,6 +100598,11 @@ let start = (() => {
const opts = { stdio: 'inherit', env: Object.assign({}, process.env, { YARN_IGNORE_PATH: 1 }) };
let exitCode = 0;
process.on(`SIGINT`, function () {
// We don't want SIGINT to kill our process; we want it to kill the
// innermost process, whose end will cause our own to exit.
});
try {
if (yarnPath.endsWith(`.js`)) {
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
@ -104923,6 +104994,7 @@ const messages = {
errorExtractingTarball: 'Extracting tar content of $1 failed, the file appears to be corrupt: $0',
updateInstalling: 'Installing $0...',
hostedGitResolveError: 'Error connecting to repository. Please, check the url.',
unauthorizedResponse: 'Received a 401 from $0. $1',
unknownFetcherFor: 'Unknown fetcher for $0',
@ -106797,7 +106869,7 @@ const semver = __webpack_require__(22);
const path = __webpack_require__(0);
const url = __webpack_require__(24);
const VALID_BIN_KEYS = /^[a-z0-9_-]+$/i;
const VALID_BIN_KEYS = /^(?!\.{0,2}$)[a-z0-9._-]+$/i;
const LICENSE_RENAMES = {
'MIT/X11': 'MIT',
@ -107660,7 +107732,11 @@ function parseRcPaths(paths, parser) {
try {
return parser((0, (_fs || _load_fs()).readFileSync)(path).toString(), path);
} catch (error) {
return {};
if (error.code === 'ENOENT' || error.code === 'EISDIR') {
return {};
} else {
throw error;
}
}
}));
}

View File

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

View File

@ -8,6 +8,7 @@ exports_files([
"scripts/ci/track-payload-size.sh",
"scripts/ci/payload-size.sh",
"scripts/ci/payload-size.js",
"package.json",
])
alias(

View File

@ -1,32 +1,603 @@
<a name="9.1.0-next.4"></a>
# [9.1.0-next.4](https://github.com/angular/angular/compare/9.1.0-next.2...9.1.0-next.4) (2020-03-10)
<a name="10.0.0-next.6"></a>
# [10.0.0-next.6](https://github.com/angular/angular/compare/10.0.0-next.5...10.0.0-next.6) (2020-05-07)
### Bug Fixes
* **bazel:** do not use manifest paths for generated imports within compilation unit ([#35841](https://github.com/angular/angular/issues/35841)) ([9581658](https://github.com/angular/angular/commit/9581658))
* **core:** undecorated-classes-with-di migration should handle libraries generated with CLI versions past v6.2.0 ([#35824](https://github.com/angular/angular/issues/35824)) ([59607dc](https://github.com/angular/angular/commit/59607dc)), closes [#34985](https://github.com/angular/angular/issues/34985)
* **language-service:** fix calculation of pipe spans ([#35986](https://github.com/angular/angular/issues/35986)) ([406419b](https://github.com/angular/angular/commit/406419b))
* **language-service:** resolve the real path for symlink ([#35895](https://github.com/angular/angular/issues/35895)) ([4e1d780](https://github.com/angular/angular/commit/4e1d780))
* **language-service:** resolve the variable from the template context first ([#35982](https://github.com/angular/angular/issues/35982)) ([3d46a45](https://github.com/angular/angular/commit/3d46a45))
* **localize:** improve matching and parsing of XLIFF 1.2 translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([350ac11](https://github.com/angular/angular/commit/350ac11))
* fix flaky test cases of passive events ([#35679](https://github.com/angular/angular/issues/35679)) ([8ef29b6](https://github.com/angular/angular/commit/8ef29b6))
* **localize:** improve matching and parsing of XLIFF 2.0 translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([08071e5](https://github.com/angular/angular/commit/08071e5))
* **localize:** improve matching and parsing of XTB translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([0e2a577](https://github.com/angular/angular/commit/0e2a577))
* **localize:** merge translation from all XLIFF `<file>` elements ([#35936](https://github.com/angular/angular/issues/35936)) ([fc4c3c3](https://github.com/angular/angular/commit/fc4c3c3)), closes [#35839](https://github.com/angular/angular/issues/35839)
* **ngcc:** introduce a new LockFile implementation that uses a child-process ([#35861](https://github.com/angular/angular/issues/35861)) ([c55f900](https://github.com/angular/angular/commit/c55f900)), closes [#35761](https://github.com/angular/angular/issues/35761)
* **platform-browser:** add missing peerDependency on `[@angular](https://github.com/angular)/animations` ([#35949](https://github.com/angular/angular/issues/35949)) ([64d6f13](https://github.com/angular/angular/commit/64d6f13)), closes [#35888](https://github.com/angular/angular/issues/35888)
* **router:** state data missing in routerLink ([#33203](https://github.com/angular/angular/issues/33203)) ([de67978](https://github.com/angular/angular/commit/de67978))
* **bazel:** ng_package rule should update "package.json" of ts_library targets ([#36944](https://github.com/angular/angular/issues/36944)) ([d5293d2](https://github.com/angular/angular/commit/d5293d2))
* **compiler:** remove outdated and invalid warning for unresolved DI parameters ([#36985](https://github.com/angular/angular/issues/36985)) ([d0280a0](https://github.com/angular/angular/commit/d0280a0))
* **compiler:** switch to 'referencedFiles' for shim generation ([#36211](https://github.com/angular/angular/issues/36211)) ([4213e8d](https://github.com/angular/angular/commit/4213e8d))
* **compiler-cli:** `isCaseSensitive()` returns correct value ([#36859](https://github.com/angular/angular/issues/36859)) ([fc4741f](https://github.com/angular/angular/commit/fc4741f))
* **compiler-cli:** don't try to tag non-ts files as shims ([#36987](https://github.com/angular/angular/issues/36987)) ([42d1091](https://github.com/angular/angular/commit/42d1091))
* **compiler-cli:** ensure `getRootDirs()` handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([3f3e9b7](https://github.com/angular/angular/commit/3f3e9b7))
* **compiler-cli:** ensure `MockFileSystem` handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([26eacd4](https://github.com/angular/angular/commit/26eacd4))
* **compiler-cli:** ensure LogicalFileSystem handles case-sensitivity ([#36859](https://github.com/angular/angular/issues/36859)) ([53a8459](https://github.com/angular/angular/commit/53a8459))
* **compiler-cli:** fix bug tracking indirect NgModule dependencies ([#36211](https://github.com/angular/angular/issues/36211)) ([bab90a7](https://github.com/angular/angular/commit/bab90a7))
* **compiler-cli:** fix case-sensitivity issues in NgtscCompilerHost ([#36859](https://github.com/angular/angular/issues/36859)) ([0ec0ff3](https://github.com/angular/angular/commit/0ec0ff3))
* **compiler-cli:** normalize mock Windows file paths correctly ([#36859](https://github.com/angular/angular/issues/36859)) ([b682bd1](https://github.com/angular/angular/commit/b682bd1))
* **compiler-cli:** use CompilerHost to ensure canonical file paths ([#36859](https://github.com/angular/angular/issues/36859)) ([a10c126](https://github.com/angular/angular/commit/a10c126))
* **core:** handle pluralize functions that expect a number ([#36901](https://github.com/angular/angular/issues/36901)) ([2ff4b35](https://github.com/angular/angular/commit/2ff4b35)), closes [#36888](https://github.com/angular/angular/issues/36888)
* **core:** properly get root nodes from embedded views with <ng-content> ([#36051](https://github.com/angular/angular/issues/36051)) ([e30e132](https://github.com/angular/angular/commit/e30e132)), closes [#35967](https://github.com/angular/angular/issues/35967)
* **forms:** handle numeric values properly in the validator ([#36157](https://github.com/angular/angular/issues/36157)) ([88a235d](https://github.com/angular/angular/commit/88a235d)), closes [#35591](https://github.com/angular/angular/issues/35591)
* **forms:** number input fires valueChanges twice ([#36087](https://github.com/angular/angular/issues/36087)) ([97d6d90](https://github.com/angular/angular/commit/97d6d90)), closes [#12540](https://github.com/angular/angular/issues/12540)
* **localize:** ensure `getLocation()` works ([#36853](https://github.com/angular/angular/issues/36853)) ([70b25a3](https://github.com/angular/angular/commit/70b25a3))
* **ngcc:** support ModuleWithProviders functions that delegate ([#36948](https://github.com/angular/angular/issues/36948)) ([fafa50d](https://github.com/angular/angular/commit/fafa50d)), closes [#36892](https://github.com/angular/angular/issues/36892)
### Features
* **bazel:** simplify ng_package by dropping esm5 and fesm5 ([#36944](https://github.com/angular/angular/issues/36944)) ([9dbb30f](https://github.com/angular/angular/commit/9dbb30f))
* **compiler-cli:** report error if undecorated class with Angular features is discovered ([#36921](https://github.com/angular/angular/issues/36921)) ([4c92cf4](https://github.com/angular/angular/commit/4c92cf4))
* **core:** undecorated-classes-with-decorated-fields migration should handle classes with lifecycle hooks ([#36921](https://github.com/angular/angular/issues/36921)) ([c6ecdc9](https://github.com/angular/angular/commit/c6ecdc9))
* **ngcc:** support for new APF where `module` points to esm2015 output ([#36944](https://github.com/angular/angular/issues/36944)) ([c98a4d6](https://github.com/angular/angular/commit/c98a4d6))
* **language-service:** [ivy] Parse Angular compiler options ([#36922](https://github.com/angular/angular/issues/36922)) ([dbd0f8e](https://github.com/angular/angular/commit/dbd0f8e))
* remove TypeScript 3.6 and 3.7 support ([#36329](https://github.com/angular/angular/issues/36329)) ([fbd281c](https://github.com/angular/angular/commit/fbd281c))
### Performance Improvements
* **compiler-cli:** perform template type-checking incrementally ([#36211](https://github.com/angular/angular/issues/36211)) ([ecffc35](https://github.com/angular/angular/commit/ecffc35))
* **compiler-cli:** split Ivy template type-checking into multiple files ([#36211](https://github.com/angular/angular/issues/36211)) ([b861e9c](https://github.com/angular/angular/commit/b861e9c))
### BREAKING CHANGES
* TypeScript versions 3.6 and 3.7 are no longer supported, please update to TypeScript 3.8
* **forms:** Number inputs no longer listen to the `change` event.
Tests which trigger `change` events need to be updated to trigger `input` events instead.
The `change` event was in place to support IE9, as we found that `input` events were not fired with backspace or cut actions. If you need to maintain IE9 support, you will need to add a change event listener to number inputs and call the `onChange` method of `NumberValueAccessor` manually.
Lastly, old versions of WebDriver would synthetically trigger the `change` event on `WebElement.clear` and `WebElement.sendKeys`. If you are using an old version of WebDriver, you may need to update tests to ensure `input` events are triggered. For example, you could use `element.sendKeys(Keys.chord(Keys.CONTROL, "a"), Keys.BACK_SPACE);` in place of `element.clear()`.
* **forms:** The `minLength` and `maxLength` validators now verify that the form control's value has a
numeric `length` property, and only validate for length if that's the case.
Previously, falsey values without the length property (such as `0` or
`false` values) were triggering validation errors. If your code relies on
the old behavior, you can include other validators such as [min][1] or
[requiredTrue][2] to the list of validators for a particular field.
[1]: https://angular.io/api/forms/Validators#min
[2]: https://angular.io/api/forms/Validators#requiredTrue
* **bazel:** esm5 and fesm5 format is no longer distributed in
Angular's npm packages e.g. @angular/core
If you are not using Angular CLI to build your application or library,
and you need to be able to build es5 artifacts, then you will need to
downlevel the distributed Angular code to es5 on your own.
Angular CLI will automatically downlevel the code to es5 if differential
loading is enabled in the Angular project, so no action is required from
Angular CLI users.
<a name="9.1.5"></a>
## [9.1.5](https://github.com/angular/angular/compare/9.1.4...9.1.5) (2020-05-07)
### Bug Fixes
* **compiler-cli:** `isCaseSensitive()` returns correct value ([#36968](https://github.com/angular/angular/issues/36968)) ([4becc1b](https://github.com/angular/angular/commit/4becc1b))
* **compiler-cli:** ensure `getRootDirs()` handles case-sensitivity ([#36968](https://github.com/angular/angular/issues/36968)) ([5bddeea](https://github.com/angular/angular/commit/5bddeea))
* **compiler-cli:** ensure `MockFileSystem` handles case-sensitivity ([#36968](https://github.com/angular/angular/issues/36968)) ([b6c042d](https://github.com/angular/angular/commit/b6c042d))
* **compiler-cli:** ensure LogicalFileSystem handles case-sensitivity ([#36968](https://github.com/angular/angular/issues/36968)) ([65337fb](https://github.com/angular/angular/commit/65337fb))
* **compiler-cli:** fix case-sensitivity issues in NgtscCompilerHost ([#36968](https://github.com/angular/angular/issues/36968)) ([4abd603](https://github.com/angular/angular/commit/4abd603))
* **compiler-cli:** normalize mock Windows file paths correctly ([#36968](https://github.com/angular/angular/issues/36968)) ([654868f](https://github.com/angular/angular/commit/654868f))
* **compiler-cli:** use CompilerHost to ensure canonical file paths ([#36968](https://github.com/angular/angular/issues/36968)) ([7e9d5f5](https://github.com/angular/angular/commit/7e9d5f5))
* **core:** handle pluralize functions that expect a number ([#36901](https://github.com/angular/angular/issues/36901)) ([e5317d5](https://github.com/angular/angular/commit/e5317d5)), closes [#36888](https://github.com/angular/angular/issues/36888)
* **core:** properly get root nodes from embedded views with <ng-content> ([#36051](https://github.com/angular/angular/issues/36051)) ([a576852](https://github.com/angular/angular/commit/a576852)), closes [#35967](https://github.com/angular/angular/issues/35967)
* **core:** Refresh transplanted views at insertion point only ([#35968](https://github.com/angular/angular/issues/35968)) ([c8c2272](https://github.com/angular/angular/commit/c8c2272)), closes [#35400](https://github.com/angular/angular/issues/35400) [#21324](https://github.com/angular/angular/issues/21324)
* **localize:** ensure `getLocation()` works ([#36920](https://github.com/angular/angular/issues/36920)) ([701016d](https://github.com/angular/angular/commit/701016d))
* **ngcc:** do not run in parallel mode if there are less than 3 CPU cores ([#36626](https://github.com/angular/angular/issues/36626)) ([3800455](https://github.com/angular/angular/commit/3800455))
* **ngcc:** give up re-spawing crashed worker process after 3 attempts ([#36626](https://github.com/angular/angular/issues/36626)) ([1863733](https://github.com/angular/angular/commit/1863733))
* **ngcc:** handle `ENOMEM` errors in worker processes ([#36626](https://github.com/angular/angular/issues/36626)) ([901b980](https://github.com/angular/angular/commit/901b980))
* **ngcc:** support ModuleWithProviders functions that delegate ([#36948](https://github.com/angular/angular/issues/36948)) ([9d13ee0](https://github.com/angular/angular/commit/9d13ee0)), closes [#36892](https://github.com/angular/angular/issues/36892)
* **ngcc:** support recovering when a worker process crashes ([#36626](https://github.com/angular/angular/issues/36626)) ([f30307a](https://github.com/angular/angular/commit/f30307a)), closes [#36278](https://github.com/angular/angular/issues/36278)
* **ngcc:** partially support TS 3.9 wrapped ES2015 classes ([#36884](https://github.com/angular/angular/issues/36884)) ([ebb4733](https://github.com/angular/angular/commit/ebb4733))
### Performance Improvements
* **ngcc:** only compute basePaths in TargetedEntryPointFinder when needed ([#36881](https://github.com/angular/angular/issues/36881)) ([5ea51b2](https://github.com/angular/angular/commit/5ea51b2)), closes [#36874](https://github.com/angular/angular/issues/36874)
* **ngcc:** speed up the `getBasePaths()` computation ([#36881](https://github.com/angular/angular/issues/36881)) ([b6d0e21](https://github.com/angular/angular/commit/b6d0e21))
<a name="10.0.0-next.5"></a>
# [10.0.0-next.5](https://github.com/angular/angular/compare/10.0.0-next.4...10.0.0-next.5) (2020-05-04)
### Bug Fixes
* **core:** log error instead of warning for unknown properties and elements ([#36399](https://github.com/angular/angular/issues/36399)) ([9d9d46f](https://github.com/angular/angular/commit/9d9d46f)), closes [#35699](https://github.com/angular/angular/issues/35699)
* **core:** Refresh transplanted views at insertion point only ([#35968](https://github.com/angular/angular/issues/35968)) ([1786586](https://github.com/angular/angular/commit/1786586)), closes [#35400](https://github.com/angular/angular/issues/35400) [#21324](https://github.com/angular/angular/issues/21324)
* **ngcc:** do not run in parallel mode if there are less than 3 CPU cores ([#36626](https://github.com/angular/angular/issues/36626)) ([4c63241](https://github.com/angular/angular/commit/4c63241))
* **ngcc:** give up re-spawning crashed worker process after 3 attempts ([#36626](https://github.com/angular/angular/issues/36626)) ([793cb32](https://github.com/angular/angular/commit/793cb32))
* **ngcc:** handle `ENOMEM` errors in worker processes ([#36626](https://github.com/angular/angular/issues/36626)) ([4779c4b](https://github.com/angular/angular/commit/4779c4b))
* **ngcc:** provide a unique exit code for timeouts ([#36838](https://github.com/angular/angular/issues/36838)) ([d805526](https://github.com/angular/angular/commit/d805526))
* **ngcc:** support recovering when a worker process crashes ([#36626](https://github.com/angular/angular/issues/36626)) ([966598c](https://github.com/angular/angular/commit/966598c)), closes [#36278](https://github.com/angular/angular/issues/36278)
* **ngcc:** support TS 3.9 wrapped ES2015 classes ([#36884](https://github.com/angular/angular/issues/36884)) ([db4c59d](https://github.com/angular/angular/commit/db4c59d))
* **router:** cancel navigation when at least one resolver completes with no "next" emission ([#24621](https://github.com/angular/angular/issues/24621)) ([d9c4840](https://github.com/angular/angular/commit/d9c4840)), closes [#24195](https://github.com/angular/angular/issues/24195)
### Code Refactoring
* **common:** remove WrappedValue from AsyncPipe ([#36633](https://github.com/angular/angular/issues/36633)) ([49be32c](https://github.com/angular/angular/commit/49be32c)), closes [#29927](https://github.com/angular/angular/issues/29927)
### Features
* **localize:** support merging multiple translation files ([#36792](https://github.com/angular/angular/issues/36792)) ([72f534f](https://github.com/angular/angular/commit/72f534f))
* **ngcc:** allow async locking timeouts to be configured ([#36838](https://github.com/angular/angular/issues/36838)) ([38f805c](https://github.com/angular/angular/commit/38f805c))
* **ngcc:** support marking an in-progress task as unprocessed ([#36626](https://github.com/angular/angular/issues/36626)) ([4665c35](https://github.com/angular/angular/commit/4665c35))
* **ngcc:** support reverting a file written by `FileWriter` ([#36626](https://github.com/angular/angular/issues/36626)) ([772ccf0](https://github.com/angular/angular/commit/772ccf0))
* **service-worker:** include `CacheQueryOptions` options in ngsw-config ([#34663](https://github.com/angular/angular/issues/34663)) ([dc9f4b9](https://github.com/angular/angular/commit/dc9f4b9)), closes [#28443](https://github.com/angular/angular/issues/28443)
* **service-worker:** use `ignoreVary: true` when retrieving responses from cache ([#34663](https://github.com/angular/angular/issues/34663)) ([ee35e22](https://github.com/angular/angular/commit/ee35e22)), closes [#36638](https://github.com/angular/angular/issues/36638)
### Performance Improvements
* **ngcc:** only compute basePaths in TargetedEntryPointFinder when needed ([#36881](https://github.com/angular/angular/issues/36881)) ([ec6b9cc](https://github.com/angular/angular/commit/ec6b9cc)), closes [#36874](https://github.com/angular/angular/issues/36874)
* **ngcc:** speed up the `getBasePaths()` computation ([#36881](https://github.com/angular/angular/issues/36881)) ([e037840](https://github.com/angular/angular/commit/e037840))
### BREAKING CHANGES
* **core:** Warnings about unknown elements are now logged as errors. This won't break your app, but it may trip up tools that expect nothing to be logged via `console.error`.
* **router:** Any resolver which return EMPTY will cancel navigation.
If you want to allow the navigation to continue, you will need to update the resolvers to emit
some value, (i.e. defaultIfEmpty(...), of(...), etc).
* **service-worker:** Previously, [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)
headers would be taken into account when retrieving resources from the
cache, completely preventing the retrieval of cached assets (due to
ServiceWorker implementation details) and leading to unpredictable
behavior due to inconsistent/buggy implementations in different
browsers.
Now, `Vary` headers are ignored when retrieving resources from the
ServiceWorker caches, which can result in resources being retrieved even
when their headers are different. If your application needs to
differentiate its responses based on request headers, please make sure
the Angular ServiceWorker is [configured](https://angular.io/guide/service-worker-config)
to avoid caching the affected resources.
* **common:** This change could result in ExpressionChangedAfterItHasBeenChecked errors that
were not detected before. The error could previously have gone undetected
because two WrappedValues are considered "equal" in all cases for the purposes
of the check, even if their respective unwrapped values are not.
Additionally, `[val]=(observable | async).someProperty` will no longer
trigger change detection if the value of `someProperty` is identical to
the value in the previous emit. If you need to force change detection,
either update the binding to use an object whose reference changes or
subscribe to the observable and call markForCheck as needed.
<a name="10.0.0-next.4"></a>
# [10.0.0-next.4](https://github.com/angular/angular/compare/10.0.0-next.3...10.0.0-next.4) (2020-04-29)
### Bug Fixes
* **compiler:** normalize line endings in ICU expansions ([#36741](https://github.com/angular/angular/issues/36741)) ([70dd27f](https://github.com/angular/angular/commit/70dd27f)), closes [#36725](https://github.com/angular/angular/issues/36725)
* **core:** attempt to recover from user errors during creation ([#36381](https://github.com/angular/angular/issues/36381)) ([3d82aa7](https://github.com/angular/angular/commit/3d82aa7)), closes [#31221](https://github.com/angular/angular/issues/31221)
* **core:** handle synthetic props in Directive host bindings correctly ([#35568](https://github.com/angular/angular/issues/35568)) ([f27deea](https://github.com/angular/angular/commit/f27deea)), closes [#35501](https://github.com/angular/angular/issues/35501)
* **language-service:** disable update the `[@angular](https://github.com/angular)/core` module ([#36783](https://github.com/angular/angular/issues/36783)) ([dd049ca](https://github.com/angular/angular/commit/dd049ca))
* **localize:** include legacy ids when describing messages ([#36761](https://github.com/angular/angular/issues/36761)) ([47f9867](https://github.com/angular/angular/commit/47f9867))
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([89c5890](https://github.com/angular/angular/commit/89c5890)), closes [#35584](https://github.com/angular/angular/issues/35584)
### Features
* **router:** allow CanLoad guard to return UrlTree ([#36610](https://github.com/angular/angular/issues/36610)) ([00e6cb1](https://github.com/angular/angular/commit/00e6cb1)), closes [#26521](https://github.com/angular/angular/issues/26521) [#28306](https://github.com/angular/angular/issues/28306)
<a name="9.1.4"></a>
## [9.1.4](https://github.com/angular/angular/compare/9.1.3...9.1.4) (2020-04-29)
### Bug Fixes
* **core:** attempt to recover from user errors during creation ([#36381](https://github.com/angular/angular/issues/36381)) ([d743331](https://github.com/angular/angular/commit/d743331)), closes [#31221](https://github.com/angular/angular/issues/31221)
* **core:** handle synthetic props in Directive host bindings correctly ([#35568](https://github.com/angular/angular/issues/35568)) ([0f389fa](https://github.com/angular/angular/commit/0f389fa)), closes [#35501](https://github.com/angular/angular/issues/35501)
* **language-service:** disable update the `[@angular](https://github.com/angular)/core` module ([#36783](https://github.com/angular/angular/issues/36783)) ([d3a77ea](https://github.com/angular/angular/commit/d3a77ea))
* **localize:** include legacy ids when describing messages ([#36761](https://github.com/angular/angular/issues/36761)) ([aa94cd5](https://github.com/angular/angular/commit/aa94cd5))
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([c440165](https://github.com/angular/angular/commit/c440165)), closes [#35584](https://github.com/angular/angular/issues/35584)
<a name="10.0.0-next.3"></a>
# [10.0.0-next.3](https://github.com/angular/angular/compare/10.0.0-next.2...10.0.0-next.3) (2020-04-22)
### Bug Fixes
* **common:** format day-periods that cross midnight ([#36611](https://github.com/angular/angular/issues/36611)) ([c6e5fc4](https://github.com/angular/angular/commit/c6e5fc4)), closes [#36566](https://github.com/angular/angular/issues/36566)
* **compiler:** avoid generating i18n attributes in plain form ([#36422](https://github.com/angular/angular/issues/36422)) ([88b0985](https://github.com/angular/angular/commit/88b0985))
* **core:** do not use unbound attributes as inputs to structural directives ([#36441](https://github.com/angular/angular/issues/36441)) ([acf6075](https://github.com/angular/angular/commit/acf6075))
* **core:** handle empty translations correctly ([#36499](https://github.com/angular/angular/issues/36499)) ([b1f1d3f](https://github.com/angular/angular/commit/b1f1d3f)), closes [#36476](https://github.com/angular/angular/issues/36476)
* **core:** missing-injectable migration should not migrate `@NgModule` classes ([#36369](https://github.com/angular/angular/issues/36369)) ([28995db](https://github.com/angular/angular/commit/28995db)), closes [#35700](https://github.com/angular/angular/issues/35700)
* **core:** pipes injecting viewProviders when used on a component host node ([#36512](https://github.com/angular/angular/issues/36512)) ([81d23b3](https://github.com/angular/angular/commit/81d23b3)), closes [#36146](https://github.com/angular/angular/issues/36146)
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([4a9f0be](https://github.com/angular/angular/commit/4a9f0be)), closes [#35945](https://github.com/angular/angular/issues/35945)
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([942b986](https://github.com/angular/angular/commit/942b986)), closes [#36619](https://github.com/angular/angular/issues/36619)
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([8be0972](https://github.com/angular/angular/commit/8be0972))
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([cabf997](https://github.com/angular/angular/commit/cabf997)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com//github.com/nodejs/node/issues/3596/issues/issuecomment-250890218)
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([0c2ed4c](https://github.com/angular/angular/commit/0c2ed4c)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com//github.com/angular/angular-cli/issues/16860/issues/issuecomment-614694269)
### BREAKING CHANGES
* **common:** format day-periods that cross midnight
When formatting a time with the `b` or `B` format codes, the rendered
string was not correctly handling day periods that spanned midnight.
Instead the logic was falling back to the default case of `AM`.
Now the logic has been updated so that it matches times that are within
a day period that spans midnight, so it will now render the correct
output, such as `at night` in the case of English.
Applications that are using either `formatDate()` or `DatePipe` and any
of the `b` or `B` format codes will be affected by this change.
<a name="9.1.3"></a>
## [9.1.3](https://github.com/angular/angular/compare/9.1.2...9.1.3) (2020-04-22)
### Bug Fixes
* **compiler:** avoid generating i18n attributes in plain form ([#36422](https://github.com/angular/angular/issues/36422)) ([08b8b51](https://github.com/angular/angular/commit/08b8b51))
* **core:** do not use unbound attributes as inputs to structural directives ([#36441](https://github.com/angular/angular/issues/36441)) ([c0ed57d](https://github.com/angular/angular/commit/c0ed57d))
* **core:** handle empty translations correctly ([#36499](https://github.com/angular/angular/issues/36499)) ([a5ea100](https://github.com/angular/angular/commit/a5ea100)), closes [#36476](https://github.com/angular/angular/issues/36476)
* **core:** missing-injectable migration should not migrate `@NgModule` classes ([#36369](https://github.com/angular/angular/issues/36369)) ([0bd50e2](https://github.com/angular/angular/commit/0bd50e2)), closes [#35700](https://github.com/angular/angular/issues/35700)
* **core:** pipes injecting viewProviders when used on a component host node ([#36512](https://github.com/angular/angular/issues/36512)) ([5ae8473](https://github.com/angular/angular/commit/5ae8473)), closes [#36146](https://github.com/angular/angular/issues/36146)
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([fe1d9ba](https://github.com/angular/angular/commit/fe1d9ba)), closes [#35945](https://github.com/angular/angular/issues/35945)
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([9724169](https://github.com/angular/angular/commit/9724169)), closes [#36619](https://github.com/angular/angular/issues/36619)
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([5bab498](https://github.com/angular/angular/commit/5bab498))
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([da159bd](https://github.com/angular/angular/commit/da159bd)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com//github.com/nodejs/node/issues/3596/issues/issuecomment-250890218)
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([18be33a](https://github.com/angular/angular/commit/18be33a)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com//github.com/angular/angular-cli/issues/16860/issues/issuecomment-614694269)
<a name="10.0.0-next.2"></a>
# [10.0.0-next.2](https://github.com/angular/angular/compare/10.0.0-next.1...10.0.0-next.2) (2020-04-15)
### Bug Fixes
* **common:** `locales/global/*.js` are not ES5 compliant ([#36342](https://github.com/angular/angular/issues/36342)) ([078b0be](https://github.com/angular/angular/commit/078b0be)), closes [angular/angular-cli#16394](https://github.com/angular/angular-cli/issues/16394)
* **compiler:** handle type references to namespaced symbols correctly ([#36106](https://github.com/angular/angular/issues/36106)) ([4aa4e6f](https://github.com/angular/angular/commit/4aa4e6f)), closes [#36006](https://github.com/angular/angular/issues/36006)
* **core:** undecorated-classes-with-decorated-fields migration should avoid error if base class has no value declaration ([#36543](https://github.com/angular/angular/issues/36543)) ([ca67748](https://github.com/angular/angular/commit/ca67748)), closes [#36522](https://github.com/angular/angular/issues/36522)
* **ngcc:** correctly detect external files from nested `node_modules/` ([#36559](https://github.com/angular/angular/issues/36559)) ([6ab43d7](https://github.com/angular/angular/commit/6ab43d7)), closes [#36526](https://github.com/angular/angular/issues/36526)
* **ngcc:** display output from the unlocker process on Windows ([#36569](https://github.com/angular/angular/issues/36569)) ([e041ac6](https://github.com/angular/angular/commit/e041ac6))
* **ngcc:** do not spawn unlocker processes on cluster workers ([#36569](https://github.com/angular/angular/issues/36569)) ([66effde](https://github.com/angular/angular/commit/66effde)), closes [#35861](https://github.com/angular/angular/issues/35861)
* **ngcc:** do not warn if `paths` mapping does not exist ([#36525](https://github.com/angular/angular/issues/36525)) ([717df13](https://github.com/angular/angular/commit/717df13)), closes [#36518](https://github.com/angular/angular/issues/36518)
* **ngcc:** force ngcc to exit on error ([#36622](https://github.com/angular/angular/issues/36622)) ([663b768](https://github.com/angular/angular/commit/663b768)), closes [#36616](https://github.com/angular/angular/issues/36616)
* **router:** pass correct component to canDeactivate checks when using two or more sibling router-outlets ([#36302](https://github.com/angular/angular/issues/36302)) ([80e6c07](https://github.com/angular/angular/commit/80e6c07)), closes [#34614](https://github.com/angular/angular/issues/34614)
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([0cc53fb](https://github.com/angular/angular/commit/0cc53fb)), closes [#36492](https://github.com/angular/angular/issues/36492)
### Performance Improvements
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([3bedfda](https://github.com/angular/angular/commit/3bedfda))
* **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([a185efb](https://github.com/angular/angular/commit/a185efb)), closes [#issuecomment-608401834](https://github.com/angular/angular/issues/issuecomment-608401834)
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([ec0ce60](https://github.com/angular/angular/commit/ec0ce60))
<a name="9.1.2"></a>
## [9.1.2](https://github.com/angular/angular/compare/9.1.1...9.1.2) (2020-04-15)
### Bug Fixes
* **compiler:** handle type references to namespaced symbols correctly ([#36106](https://github.com/angular/angular/issues/36106)) ([468cf69](https://github.com/angular/angular/commit/468cf69)), closes [#36006](https://github.com/angular/angular/issues/36006)
* **core:** undecorated-classes-with-decorated-fields migration should avoid error if base class has no value declaration ([#36543](https://github.com/angular/angular/issues/36543)) ([3992341](https://github.com/angular/angular/commit/3992341)), closes [#36522](https://github.com/angular/angular/issues/36522)
* **ngcc:** correctly detect external files from nested `node_modules/` ([#36559](https://github.com/angular/angular/issues/36559)) ([8c559ef](https://github.com/angular/angular/commit/8c559ef)), closes [#36526](https://github.com/angular/angular/issues/36526)
* **ngcc:** display output from the unlocker process on Windows ([#36569](https://github.com/angular/angular/issues/36569)) ([12266b2](https://github.com/angular/angular/commit/12266b2))
* **ngcc:** do not spawn unlocker processes on cluster workers ([#36569](https://github.com/angular/angular/issues/36569)) ([e385abc](https://github.com/angular/angular/commit/e385abc)), closes [#35861](https://github.com/angular/angular/issues/35861)
* **ngcc:** do not warn if `paths` mapping does not exist ([#36525](https://github.com/angular/angular/issues/36525)) ([33eee43](https://github.com/angular/angular/commit/33eee43)), closes [#36518](https://github.com/angular/angular/issues/36518)
* **ngcc:** force ngcc to exit on error ([#36622](https://github.com/angular/angular/issues/36622)) ([933cbfb](https://github.com/angular/angular/commit/933cbfb)), closes [#36616](https://github.com/angular/angular/issues/36616)
* **router:** pass correct component to canDeactivate checks when using two or more sibling router-outlets ([#36302](https://github.com/angular/angular/issues/36302)) ([8e7f903](https://github.com/angular/angular/commit/8e7f903)), closes [#34614](https://github.com/angular/angular/issues/34614)
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([a67afcc](https://github.com/angular/angular/commit/a67afcc)), closes [#36492](https://github.com/angular/angular/issues/36492)
### Performance Improvements
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([e06512b](https://github.com/angular/angular/commit/e06512b)) * **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([918e628](https://github.com/angular/angular/commit/918e628)), closes [#issuecomment-608401834](https://github.com/angular/angular/issues/issuecomment-608401834)
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([603b094](https://github.com/angular/angular/commit/603b094))
<a name="10.0.0-next.1"></a>
# [10.0.0-next.1](https://github.com/angular/angular/compare/10.0.0-next.0...10.0.0-next.1) (2020-04-08)
This release contains various API docs improvements.
<a name="10.0.0-next.0"></a>
# [10.0.0-next.0](https://github.com/angular/angular/compare/9.1.0-rc.0...10.0.0-next.0) (2020-04-08)
### Bug Fixes
* **common:** let `KeyValuePipe` accept type unions with `null` ([#36093](https://github.com/angular/angular/issues/36093)) ([d783519](https://github.com/angular/angular/commit/d783519)), closes [#35743](https://github.com/angular/angular/issues/35743)
* **compiler:** avoid undefined expressions in holey array ([#36343](https://github.com/angular/angular/issues/36343)) ([5516802](https://github.com/angular/angular/commit/5516802))
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
* **compiler:** resolve enum values in binary operations ([#36461](https://github.com/angular/angular/issues/36461)) ([64022f5](https://github.com/angular/angular/commit/64022f5)), closes [#35584](https://github.com/angular/angular/issues/35584)
* **compiler-cli:** pass real source spans where they are empty ([#31805](https://github.com/angular/angular/issues/31805)) ([e893c5a](https://github.com/angular/angular/commit/e893c5a))
* **core:** avoid migration error when non-existent symbol is imported ([#36367](https://github.com/angular/angular/issues/36367)) ([d43c306](https://github.com/angular/angular/commit/d43c306)), closes [#36346](https://github.com/angular/angular/issues/36346)
* **core:** ngOnDestroy on multi providers called with incorrect context ([#35840](https://github.com/angular/angular/issues/35840)) ([95fc3d4](https://github.com/angular/angular/commit/95fc3d4)), closes [#35231](https://github.com/angular/angular/issues/35231)
* **core:** run `APP_INITIALIZER`s before accessing `LOCALE_ID` token in Ivy TestBed ([#36237](https://github.com/angular/angular/issues/36237)) ([1649743](https://github.com/angular/angular/commit/1649743)), closes [#36230](https://github.com/angular/angular/issues/36230)
* **core:** undecorated-classes-with-decorated-fields migration does not decorate derived classes ([#35339](https://github.com/angular/angular/issues/35339)) ([32eafef](https://github.com/angular/angular/commit/32eafef)), closes [#34376](https://github.com/angular/angular/issues/34376)
* **core:** workaround Terser inlining bug ([#36200](https://github.com/angular/angular/issues/36200)) ([0ce8ad3](https://github.com/angular/angular/commit/0ce8ad3))
* **elements:** correctly handle setting inputs to `undefined` ([#36140](https://github.com/angular/angular/issues/36140)) ([9ba46d9](https://github.com/angular/angular/commit/9ba46d9))
* **elements:** correctly set `SimpleChange#firstChange` for pre-existing inputs ([#36140](https://github.com/angular/angular/issues/36140)) ([b14ac96](https://github.com/angular/angular/commit/b14ac96)), closes [#36130](https://github.com/angular/angular/issues/36130)
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([fe2b692](https://github.com/angular/angular/commit/fe2b692)), closes [#36191](https://github.com/angular/angular/issues/36191)
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([81195a2](https://github.com/angular/angular/commit/81195a2))
* **localize:** allow ICU expansion case to start with any character except `}` ([#36123](https://github.com/angular/angular/issues/36123)) ([fced8ee](https://github.com/angular/angular/commit/fced8ee)), closes [#31586](https://github.com/angular/angular/issues/31586)
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([76a8cd5](https://github.com/angular/angular/commit/76a8cd5)), closes [/github.com/angular/angular/issues/36414#issuecomment-609644282](https://github.com//github.com/angular/angular/issues/36414/issues/issuecomment-609644282)
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([326240e](https://github.com/angular/angular/commit/326240e))
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([ca25c95](https://github.com/angular/angular/commit/ca25c95)), closes [#36089](https://github.com/angular/angular/issues/36089)
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([aecf9de](https://github.com/angular/angular/commit/aecf9de))
* **ngcc:** correctly identify the package path of secondary entry-points ([#36249](https://github.com/angular/angular/issues/36249)) ([995cd15](https://github.com/angular/angular/commit/995cd15)), closes [#35747](https://github.com/angular/angular/issues/35747)
* **ngcc:** detect non-emitted, non-imported TypeScript helpers ([#36418](https://github.com/angular/angular/issues/36418)) ([5fa7b8b](https://github.com/angular/angular/commit/5fa7b8b))
* **ngcc:** do not spawn more processes than intended in parallel mode ([#36280](https://github.com/angular/angular/issues/36280)) ([5cee709](https://github.com/angular/angular/commit/5cee709)), closes [#35719](https://github.com/angular/angular/issues/35719) [#36278](https://github.com/angular/angular/issues/36278) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts/issues/L429) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L108) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L110) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L199)
* **ngcc:** do not write entry-point manifest outside node_modules ([#36299](https://github.com/angular/angular/issues/36299)) ([c6dd900](https://github.com/angular/angular/commit/c6dd900)), closes [#36296](https://github.com/angular/angular/issues/36296)
* **ngcc:** don't crash on cyclic source-map references ([#36452](https://github.com/angular/angular/issues/36452)) ([ee70a18](https://github.com/angular/angular/commit/ee70a18)), closes [#35727](https://github.com/angular/angular/issues/35727) [#35757](https://github.com/angular/angular/issues/35757)
* **ngcc:** handle bad path mappings when finding entry-points ([#36331](https://github.com/angular/angular/issues/36331)) ([cc4b813](https://github.com/angular/angular/commit/cc4b813)), closes [#36313](https://github.com/angular/angular/issues/36313) [#36283](https://github.com/angular/angular/issues/36283)
* **ngcc:** handle entry-points within container folders ([#36305](https://github.com/angular/angular/issues/36305)) ([38ad1d9](https://github.com/angular/angular/commit/38ad1d9)), closes [#35756](https://github.com/angular/angular/issues/35756) [#36216](https://github.com/angular/angular/issues/36216)
* **ngcc:** sniff `main` property for ESM5 format ([#36396](https://github.com/angular/angular/issues/36396)) ([2463548](https://github.com/angular/angular/commit/2463548)), closes [#35788](https://github.com/angular/angular/issues/35788)
* **ngcc:** support ignoring deep-imports via package config ([#36423](https://github.com/angular/angular/issues/36423)) ([f9fb833](https://github.com/angular/angular/commit/f9fb833)), closes [#35750](https://github.com/angular/angular/issues/35750)
* **ngcc:** support simple `browser` property in entry-points ([#36396](https://github.com/angular/angular/issues/36396)) ([6b3aa60](https://github.com/angular/angular/commit/6b3aa60)), closes [#36062](https://github.com/angular/angular/issues/36062)
* **ngcc:** use path-mappings from tsconfig in dependency resolution ([#36180](https://github.com/angular/angular/issues/36180)) ([380de1e](https://github.com/angular/angular/commit/380de1e)), closes [#36119](https://github.com/angular/angular/issues/36119)
* **ngcc:** use preserve whitespaces from tsconfig if provided ([#36189](https://github.com/angular/angular/issues/36189)) ([b8e9a30](https://github.com/angular/angular/commit/b8e9a30)), closes [#35871](https://github.com/angular/angular/issues/35871)
* **platform-server:** update `xhr2` dependency ([#36366](https://github.com/angular/angular/issues/36366)) ([b59bc0e](https://github.com/angular/angular/commit/b59bc0e)), closes [#36358](https://github.com/angular/angular/issues/36358)
* **router:** allow UrlMatcher to return null ([#36402](https://github.com/angular/angular/issues/36402)) ([568e9df](https://github.com/angular/angular/commit/568e9df)), closes [#29824](https://github.com/angular/angular/issues/29824)
* **router:** state data missing in routerLink ([#36462](https://github.com/angular/angular/issues/36462)) ([e0415db](https://github.com/angular/angular/commit/e0415db)), closes [#33173](https://github.com/angular/angular/issues/33173)
* **service-worker:** by default register the SW after 30s even the app never stabilizes ([#35870](https://github.com/angular/angular/issues/35870)) ([29e8a64](https://github.com/angular/angular/commit/29e8a64)), closes [#34464](https://github.com/angular/angular/issues/34464)
* **service-worker:** prevent SW registration strategies from affecting app stabilization ([#35870](https://github.com/angular/angular/issues/35870)) ([2d7c95f](https://github.com/angular/angular/commit/2d7c95f))
### Features
* **compiler:** add dependency info and ng-content selectors to metadata ([#35695](https://github.com/angular/angular/issues/35695)) ([32ce8b1](https://github.com/angular/angular/commit/32ce8b1))
* **compiler:** Propagate value span of ExpressionBinding to ParsedProperty ([#36133](https://github.com/angular/angular/issues/36133)) ([d714b95](https://github.com/angular/angular/commit/d714b95))
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([c24ad56](https://github.com/angular/angular/commit/c24ad56))
* **service-worker:** support timeout in `registerWhenStable` SW registration strategy ([#35870](https://github.com/angular/angular/issues/35870)) ([00efacf](https://github.com/angular/angular/commit/00efacf)), closes [#34464](https://github.com/angular/angular/issues/34464)
### BREAKING CHANGES
* **router:** UrlMatcher's type now reflects that it could always return
null.
If you implemented your own Router or Recognizer class, please update it to
handle matcher returning null.
<a name="9.1.1"></a>
## [9.1.1](https://github.com/angular/angular/compare/9.1.0...9.1.1) (2020-04-07)
### Bug Fixes
* **compiler:** avoid undefined expressions in holey array ([#36343](https://github.com/angular/angular/issues/36343)) ([90cae34](https://github.com/angular/angular/commit/90cae34))
* **compiler:** resolve enum values in binary operations ([#36461](https://github.com/angular/angular/issues/36461)) ([cbc25bb](https://github.com/angular/angular/commit/cbc25bb)), closes [#35584](https://github.com/angular/angular/issues/35584)
* **compiler-cli:** pass real source spans where they are empty ([#31805](https://github.com/angular/angular/issues/31805)) ([4894220](https://github.com/angular/angular/commit/4894220))
* **core:** avoid migration error when non-existent symbol is imported ([#36367](https://github.com/angular/angular/issues/36367)) ([dff52ec](https://github.com/angular/angular/commit/dff52ec)), closes [#36346](https://github.com/angular/angular/issues/36346)
* **core:** ngOnDestroy on multi providers called with incorrect context ([#35840](https://github.com/angular/angular/issues/35840)) ([af42694](https://github.com/angular/angular/commit/af42694)), closes [#35231](https://github.com/angular/angular/issues/35231)
* **core:** run `APP_INITIALIZER`s before accessing `LOCALE_ID` token in Ivy TestBed ([#36237](https://github.com/angular/angular/issues/36237)) ([5c28af0](https://github.com/angular/angular/commit/5c28af0)), closes [#36230](https://github.com/angular/angular/issues/36230)
* **core:** undecorated-classes-with-decorated-fields migration does not decorate derived classes ([#35339](https://github.com/angular/angular/issues/35339)) ([5ff5a11](https://github.com/angular/angular/commit/5ff5a11)), closes [#34376](https://github.com/angular/angular/issues/34376)
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([a631b99](https://github.com/angular/angular/commit/a631b99))
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([ff523c9](https://github.com/angular/angular/commit/ff523c9)), closes [#36191](https://github.com/angular/angular/issues/36191)
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([ffa4e11](https://github.com/angular/angular/commit/ffa4e11))
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([136596d](https://github.com/angular/angular/commit/136596d)), closes [/github.com/angular/angular/issues/36414#issuecomment-609644282](https://github.com//github.com/angular/angular/issues/36414/issues/issuecomment-609644282)
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([cb0a2a0](https://github.com/angular/angular/commit/cb0a2a0))
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([879457c](https://github.com/angular/angular/commit/879457c)), closes [#36089](https://github.com/angular/angular/issues/36089)
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([0daa488](https://github.com/angular/angular/commit/0daa488))
* **ngcc:** correctly identify the package path of secondary entry-points ([#36249](https://github.com/angular/angular/issues/36249)) ([e53b686](https://github.com/angular/angular/commit/e53b686)), closes [#35747](https://github.com/angular/angular/issues/35747)
* **ngcc:** detect non-emitted, non-imported TypeScript helpers ([#36418](https://github.com/angular/angular/issues/36418)) ([93b32d3](https://github.com/angular/angular/commit/93b32d3))
* **ngcc:** do not spawn more processes than intended in parallel mode ([#36280](https://github.com/angular/angular/issues/36280)) ([6ea232e](https://github.com/angular/angular/commit/6ea232e)), closes [#35719](https://github.com/angular/angular/issues/35719) [#36278](https://github.com/angular/angular/issues/36278) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts#L429](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/main.ts/issues/L429) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L108](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L108) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L110](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L110) [/github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts#L199](https://github.com//github.com/angular/angular/blob/b8e9a30d3b6/packages/compiler-cli/ngcc/src/execution/cluster/master.ts/issues/L199)
* **ngcc:** do not write entry-point manifest outside node_modules ([#36299](https://github.com/angular/angular/issues/36299)) ([bb8744d](https://github.com/angular/angular/commit/bb8744d)), closes [#36296](https://github.com/angular/angular/issues/36296)
* **ngcc:** don't crash on cyclic source-map references ([#36452](https://github.com/angular/angular/issues/36452)) ([56af303](https://github.com/angular/angular/commit/56af303)), closes [#35727](https://github.com/angular/angular/issues/35727) [#35757](https://github.com/angular/angular/issues/35757)
* **ngcc:** handle bad path mappings when finding entry-points ([#36331](https://github.com/angular/angular/issues/36331)) ([7bb3588](https://github.com/angular/angular/commit/7bb3588)), closes [#36313](https://github.com/angular/angular/issues/36313) [#36283](https://github.com/angular/angular/issues/36283)
* **ngcc:** handle entry-points within container folders ([#36305](https://github.com/angular/angular/issues/36305)) ([392ef93](https://github.com/angular/angular/commit/392ef93)), closes [#35756](https://github.com/angular/angular/issues/35756) [#36216](https://github.com/angular/angular/issues/36216)
* **ngcc:** sniff `main` property for ESM5 format ([#36396](https://github.com/angular/angular/issues/36396)) ([93cbef2](https://github.com/angular/angular/commit/93cbef2)), closes [#35788](https://github.com/angular/angular/issues/35788)
* **ngcc:** support ignoring deep-imports via package config ([#36423](https://github.com/angular/angular/issues/36423)) ([31eaf78](https://github.com/angular/angular/commit/31eaf78)), closes [#35750](https://github.com/angular/angular/issues/35750)
* **ngcc:** support simple `browser` property in entry-points ([#36396](https://github.com/angular/angular/issues/36396)) ([b0d680d](https://github.com/angular/angular/commit/b0d680d)), closes [#36062](https://github.com/angular/angular/issues/36062)
* **platform-server:** update `xhr2` dependency ([#36366](https://github.com/angular/angular/issues/36366)) ([14ae3c0](https://github.com/angular/angular/commit/14ae3c0)), closes [#36358](https://github.com/angular/angular/issues/36358)
* **router:** state data missing in routerLink ([#36462](https://github.com/angular/angular/issues/36462)) ([0e7a89a](https://github.com/angular/angular/commit/0e7a89a)), closes [#33173](https://github.com/angular/angular/issues/33173)
<a name="9.1.0"></a>
# [9.1.0](https://github.com/angular/angular/compare/9.0.0...9.1.0) (2020-03-25)
### Release Highlights
To learn about the release highlights and our CLI-powered automated update workflow for your projects please check out the [v9.1 release announcement](https://blog.angular.io/version-9-1-of-angular-now-available-typescript-3-8-faster-builds-and-more-eb292f989428).
* TypeScript 3.8 update
* ngcc improvements
* performance optimizations
* concurrency & reliability improvements for monorepo use-cases (npm postinstall script no longer recommended)
* i18n now supports RTL locale info
* Ivy compatibility fixes
### Features
* **bazel:** enable ivy template type-checking in g3 ([#35672](https://github.com/angular/angular/issues/35672)) ([8f5b7f3](https://github.com/angular/angular/commit/8f5b7f3))
* **bazel:** transform generated shims (in Ivy) with tsickle ([#35975](https://github.com/angular/angular/issues/35975)) ([e3ecdc6](https://github.com/angular/angular/commit/e3ecdc6)), closes [#35848](https://github.com/angular/angular/issues/35848)
* **compiler-cli:** implement NgTscPlugin on top of the NgCompiler API ([#34792](https://github.com/angular/angular/issues/34792)) ([3c69442dbd](https://github.com/angular/angular/commit/3c69442dbd))
* **compiler:** Add sourceSpan and keySpan to TemplateBinding ([#35897](https://github.com/angular/angular/issues/35897)) ([06779cf](https://github.com/angular/angular/commit/06779cf))
* **compiler:** Propagate source span and value span to Variable AST ([#36047](https://github.com/angular/angular/issues/36047)) ([31bec8c](https://github.com/angular/angular/commit/31bec8c))
* **compiler:** add dependency info and ng-content selectors to metadata ([#35695](https://github.com/angular/angular/issues/35695)) ([fb70083](https://github.com/angular/angular/commit/fb70083))
* **language-service:** improve non-callable error message ([#35271](https://github.com/angular/angular/issues/35271)) ([acc483e](https://github.com/angular/angular/commit/acc483e))
* **language-service:** modularize error messages ([#35678](https://github.com/angular/angular/issues/35678)) ([47a1811](https://github.com/angular/angular/commit/47a1811)), closes [#32663](https://github.com/angular/angular/issues/32663)
* **ngcc:** implement source-map flattening ([#35132](https://github.com/angular/angular/issues/35132)) ([df816c9](https://github.com/angular/angular/commit/df816c9))
* **ngcc:** pause async ngcc processing if another process has the lockfile ([#35131](https://github.com/angular/angular/issues/35131)) ([eef0753](https://github.com/angular/angular/commit/eef0753))
* **ngcc:** support invalidating the entry-point manifest ([#35931](https://github.com/angular/angular/issues/35931)) ([8ea61a1](https://github.com/angular/angular/commit/8ea61a1))
* **zone.js** add a temp solution to support passive event listeners. ([#34503](https://github.com/angular/angular/issues/34503)) ([f9d483e](https://github.com/angular/angular/commit/f9d483e))
* **zone.js** add an tickOptions parameter with property processNewMacroTasksSynchronously. ([#33838](https://github.com/angular/angular/issues/33838)) ([17b862c](https://github.com/angular/angular/commit/17b862c)), closes [#33799](https://github.com/angular/angular/issues/33799)
* **zone.js** add interface definitions which zone extends EventTarget ([#35304](https://github.com/angular/angular/issues/35304)) ([4acb676](https://github.com/angular/angular/commit/4acb676)), closes [#35173](https://github.com/angular/angular/issues/35173)
* **zone.js** support passive event options by defining global variables in zone.js config file ([#34503](https://github.com/angular/angular/issues/34503)) ([d7d359e](https://github.com/angular/angular/commit/d7d359e))
* define all zone.js configurations to typescript interfaces ([#35329](https://github.com/angular/angular/issues/35329)) ([03d88c7](https://github.com/angular/angular/commit/03d88c7))
* typescript 3.8 support ([#35864](https://github.com/angular/angular/issues/35864)) ([95c729f](https://github.com/angular/angular/commit/95c729f))
### Performance Improvements
* **core:** add micro benchmark for destroy hook invocation ([#35784](https://github.com/angular/angular/issues/35784)) ([0653db1](https://github.com/angular/angular/commit/0653db1))
* **core:** adding micro benchmark for host bindings ([#35705](https://github.com/angular/angular/issues/35705)) ([8fed1fe](https://github.com/angular/angular/commit/8fed1fe)), closes [#35568](https://github.com/angular/angular/issues/35568)
* **core:** avoid recursive scope recalculation when TestBed.overrideModule is used ([#35454](https://github.com/angular/angular/issues/35454)) ([0a1a989](https://github.com/angular/angular/commit/0a1a989))
* **core:** use multiple directives in host bindings micro benchmark ([#35736](https://github.com/angular/angular/issues/35736)) ([5bc39f8](https://github.com/angular/angular/commit/5bc39f8))
* **ivy:** remove unused event argument in listener instructions ([#35097](https://github.com/angular/angular/issues/35097)) ([9228d7f](https://github.com/angular/angular/commit/9228d7f))
* **ngcc:** link segment markers for faster traversal ([#36027](https://github.com/angular/angular/issues/36027)) ([47025e0](https://github.com/angular/angular/commit/47025e0))
* **ngcc:** only create tasks for non-processed formats ([#35719](https://github.com/angular/angular/issues/35719)) ([d7efc45](https://github.com/angular/angular/commit/d7efc45))
* **ngcc:** reduce directory traversing ([#35756](https://github.com/angular/angular/issues/35756)) ([e0a35e1](https://github.com/angular/angular/commit/e0a35e1)), closes [#35717](https://github.com/angular/angular/issues/35717)
* **ngcc:** spawn workers lazily ([#35719](https://github.com/angular/angular/issues/35719)) ([dc40a93](https://github.com/angular/angular/commit/dc40a93)), closes [#35717](https://github.com/angular/angular/issues/35717)
* **ngcc:** store the position of SegmentMarkers to avoid unnecessary computation ([#36027](https://github.com/angular/angular/issues/36027)) ([772bb5e](https://github.com/angular/angular/commit/772bb5e))
* **ngcc:** use binary search when flattening mappings ([#36027](https://github.com/angular/angular/issues/36027)) ([348ff0c](https://github.com/angular/angular/commit/348ff0c))
* **ngcc:** use line start positions for computing offsets in source-map flattening ([#36027](https://github.com/angular/angular/issues/36027)) ([e890082](https://github.com/angular/angular/commit/e890082))
* **ngcc:** use the `EntryPointManifest` in `DirectoryWalkerEntryPointFinder` ([#35931](https://github.com/angular/angular/issues/35931)) ([ec9f4d5](https://github.com/angular/angular/commit/ec9f4d5))
### Bug Fixes
* **animations:** Remove ɵAnimationDriver from private exports ([#35690](https://github.com/angular/angular/issues/35690)) ([ec789b0](https://github.com/angular/angular/commit/ec789b0))
* **animations:** allow computeStyle to work on elements created in Node ([#35810](https://github.com/angular/angular/issues/35810)) ([17cf04e](https://github.com/angular/angular/commit/17cf04e))
* **animations:** false positive when detecting Node in Webpack builds ([#35134](https://github.com/angular/angular/issues/35134)) ([dc4ae4b](https://github.com/angular/angular/commit/dc4ae4b)), closes [#35117](https://github.com/angular/angular/issues/35117)
* **animations:** process shorthand `margin` and `padding` styles correctly ([#35701](https://github.com/angular/angular/issues/35701)) ([35c9f0d](https://github.com/angular/angular/commit/35c9f0d)), closes [#35463](https://github.com/angular/angular/issues/35463)
* **bazel:** devserver shows blank page in Windows ([#35159](https://github.com/angular/angular/issues/35159)) ([727f92f](https://github.com/angular/angular/commit/727f92f))
* **bazel:** do not use manifest paths for generated imports within compilation unit ([#35841](https://github.com/angular/angular/issues/35841)) ([9581658](https://github.com/angular/angular/commit/9581658))
* **bazel:** ng_package rule creates incorrect UMD module exports ([#35792](https://github.com/angular/angular/issues/35792)) ([5c2a908](https://github.com/angular/angular/commit/5c2a908)), closes [angular/components#18652](https://github.com/angular/components/issues/18652)
* **bazel:** prod server doesn't serve files in windows ([#35991](https://github.com/angular/angular/issues/35991)) ([96e3449](https://github.com/angular/angular/commit/96e3449))
* **bazel:** spawn prod server using port 4200 ([#35160](https://github.com/angular/angular/issues/35160)) ([829f506](https://github.com/angular/angular/commit/829f506))
* **bazel:** update ibazel to 0.11.1 ([#35158](https://github.com/angular/angular/issues/35158)) ([4e6d237](https://github.com/angular/angular/commit/4e6d237))
* **bazel:** update several packages for better windows support ([#35991](https://github.com/angular/angular/issues/35991)) ([32f099a](https://github.com/angular/angular/commit/32f099a))
* **bazel:** update typescript peer dependency range ([#36013](https://github.com/angular/angular/issues/36013)) ([5e3a898](https://github.com/angular/angular/commit/5e3a898))
* **common:** let `KeyValuePipe` accept type unions with `null` ([#36093](https://github.com/angular/angular/issues/36093)) ([407fa42](https://github.com/angular/angular/commit/407fa42)), closes [#35743](https://github.com/angular/angular/issues/35743)
* **compiler-cli:** TypeScript peer dependency range ([#36008](https://github.com/angular/angular/issues/36008)) ([5f7d066](https://github.com/angular/angular/commit/5f7d066))
* **compiler-cli:** suppress extraRequire errors in Closure Compiler ([#35737](https://github.com/angular/angular/issues/35737)) ([c296bfc](https://github.com/angular/angular/commit/c296bfc))
* **compiler:** Propagate value span of ExpressionBinding to ParsedProperty ([#36133](https://github.com/angular/angular/issues/36133)) ([2ce5fa3](https://github.com/angular/angular/commit/2ce5fa3))
* **compiler:** do not recurse to find static symbols of same module ([#35262](https://github.com/angular/angular/issues/35262)) ([e179c58](https://github.com/angular/angular/commit/e179c58))
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
* **compiler:** report errors for missing binding names ([#34595](https://github.com/angular/angular/issues/34595)) ([d13cab7](https://github.com/angular/angular/commit/d13cab7))
* **compiler:** support directive inputs with interpolations on `<ng-template>`s ([#35984](https://github.com/angular/angular/issues/35984)) ([79659ee](https://github.com/angular/angular/commit/79659ee)), closes [#35752](https://github.com/angular/angular/issues/35752)
* **compiler:** support i18n attributes on `<ng-template>` tags ([#35681](https://github.com/angular/angular/issues/35681)) ([40da51f](https://github.com/angular/angular/commit/40da51f))
* **compiler:** type-checking error for duplicate variables in templates ([#35674](https://github.com/angular/angular/issues/35674)) ([2c41bb8](https://github.com/angular/angular/commit/2c41bb8)), closes [#35186](https://github.com/angular/angular/issues/35186)
* **compiler:** use FatalDiagnosticError to generate better error messages ([#35244](https://github.com/angular/angular/issues/35244)) ([646655d](https://github.com/angular/angular/commit/646655d))
* **core:** Add `style="{{exp}}"` based interpolation ([#34202](https://github.com/angular/angular/issues/34202)) ([2562a3b](https://github.com/angular/angular/commit/2562a3b)), closes [#33575](https://github.com/angular/angular/issues/33575)
* **core:** Remove `debugger` statement ([#35763](https://github.com/angular/angular/issues/35763)) ([8f38eb7](https://github.com/angular/angular/commit/8f38eb7)), closes [#35470](https://github.com/angular/angular/issues/35470)
* **core:** Remove `debugger` statement when assert is thrown ([#35763](https://github.com/angular/angular/issues/35763)) ([4003538](https://github.com/angular/angular/commit/4003538)), closes [#35470](https://github.com/angular/angular/issues/35470)
* **core:** add `noSideEffects()` to `make*Decorator()` functions ([#35769](https://github.com/angular/angular/issues/35769)) ([dc6a791](https://github.com/angular/angular/commit/dc6a791))
* **core:** add `noSideEffects()` to `ɵɵdefineComponent()` ([#35769](https://github.com/angular/angular/issues/35769)) ([ba36127](https://github.com/angular/angular/commit/ba36127))
* **core:** add strictLiteralTypes to align core + VE checking of literals ([#35462](https://github.com/angular/angular/issues/35462)) ([4253662](https://github.com/angular/angular/commit/4253662))
* **core:** adhere to bootstrap options for JIT compiled components ([#35534](https://github.com/angular/angular/issues/35534)) ([e342ffd](https://github.com/angular/angular/commit/e342ffd)), closes [#35230](https://github.com/angular/angular/issues/35230)
* **core:** allow null / undefined values in query results ([#35796](https://github.com/angular/angular/issues/35796)) ([5652fb1](https://github.com/angular/angular/commit/5652fb1)), closes [#35673](https://github.com/angular/angular/issues/35673)
* **core:** better handing of ICUs outside of i18n blocks ([#35347](https://github.com/angular/angular/issues/35347)) ([c013dd4](https://github.com/angular/angular/commit/c013dd4))
* **core:** better inference for circularly referenced directive types ([#35622](https://github.com/angular/angular/issues/35622)) ([173a1ac](https://github.com/angular/angular/commit/173a1ac)), closes [#35372](https://github.com/angular/angular/issues/35372) [#35603](https://github.com/angular/angular/issues/35603) [#35522](https://github.com/angular/angular/issues/35522)
* **core:** correctly concatenate static and dynamic binding to `class` when shadowed ([#35350](https://github.com/angular/angular/issues/35350)) ([8c75f21](https://github.com/angular/angular/commit/8c75f21)), closes [#35335](https://github.com/angular/angular/issues/35335)
* **core:** don't re-invoke pure pipes that throw and arguments are the same ([#35827](https://github.com/angular/angular/issues/35827)) ([19cfaf7](https://github.com/angular/angular/commit/19cfaf7))
* **core:** emulate a View Engine type-checking bug with safe navigation ([#35462](https://github.com/angular/angular/issues/35462)) ([a61fe41](https://github.com/angular/angular/commit/a61fe41))
* **core:** error in AOT when pipe inherits constructor from injectable that uses DI ([#35468](https://github.com/angular/angular/issues/35468)) ([e17bde9](https://github.com/angular/angular/commit/e17bde9)), closes [#35277](https://github.com/angular/angular/issues/35277)
* **core:** error when accessing NgModuleRef.componentFactoryResolver in constructor ([#35637](https://github.com/angular/angular/issues/35637)) ([835618c](https://github.com/angular/angular/commit/835618c)), closes [#35580](https://github.com/angular/angular/issues/35580)
* **core:** handle `<ng-template>` with local refs in i18n blocks ([#35758](https://github.com/angular/angular/issues/35758)) ([ef75875](https://github.com/angular/angular/commit/ef75875))
* **core:** incorrectly generating shared pure function between null and object literal ([#35481](https://github.com/angular/angular/issues/35481)) ([22786c8](https://github.com/angular/angular/commit/22786c8)), closes [#33705](https://github.com/angular/angular/issues/33705) [#35298](https://github.com/angular/angular/issues/35298)
* **core:** injecting incorrect provider when re-providing injectable with useClass ([#34574](https://github.com/angular/angular/issues/34574)) ([0bc35a7](https://github.com/angular/angular/commit/0bc35a7)), closes [#34110](https://github.com/angular/angular/issues/34110)
* **core:** log error instead of warning for unknown properties and elements ([#35798](https://github.com/angular/angular/issues/35798)) ([00f3c58](https://github.com/angular/angular/commit/00f3c58)), closes [#35699](https://github.com/angular/angular/issues/35699)
* **core:** make subclass inherit developer-defined data ([#35105](https://github.com/angular/angular/issues/35105)) ([a756161](https://github.com/angular/angular/commit/a756161))
* **core:** provide a more detailed error message for NG6002/NG6003 ([#35620](https://github.com/angular/angular/issues/35620)) ([2d89b5d](https://github.com/angular/angular/commit/2d89b5d))
* **core:** remove side effects from `ɵɵNgOnChangesFeature()` ([#35769](https://github.com/angular/angular/issues/35769)) ([9cf85d2](https://github.com/angular/angular/commit/9cf85d2))
* **core:** remove side effects from `ɵɵgetInheritedFactory()` ([#35769](https://github.com/angular/angular/issues/35769)) ([c195d22](https://github.com/angular/angular/commit/c195d22))
* **core:** remove support for `Map`/`Set` in `[class]`/`[style]` bindings ([#35392](https://github.com/angular/angular/issues/35392)) ([2ca7984](https://github.com/angular/angular/commit/2ca7984))
* **core:** support sanitizer value in the [style] bindings ([#35564](https://github.com/angular/angular/issues/35564)) ([3af103a](https://github.com/angular/angular/commit/3af103a)), closes [#35476](https://github.com/angular/angular/issues/35476)
* **core:** treat `[class]` and `[className]` as unrelated bindings ([#35668](https://github.com/angular/angular/issues/35668)) ([a153b61](https://github.com/angular/angular/commit/a153b61)), closes [#35577](https://github.com/angular/angular/issues/35577)
* **core:** unable to NgModuleRef.injector in module constructor ([#35731](https://github.com/angular/angular/issues/35731)) ([1f8a243](https://github.com/angular/angular/commit/1f8a243)), closes [#35677](https://github.com/angular/angular/issues/35677) [#35639](https://github.com/angular/angular/issues/35639)
* **core:** undecorated-classes-with-di migration should handle libraries generated with CLI versions past v6.2.0 ([#35824](https://github.com/angular/angular/issues/35824)) ([59607dc](https://github.com/angular/angular/commit/59607dc)), closes [#34985](https://github.com/angular/angular/issues/34985)
* **core:** use proper configuration to compile Injectable in JIT ([#35706](https://github.com/angular/angular/issues/35706)) ([7b13977](https://github.com/angular/angular/commit/7b13977))
* **core:** verify parsed ICU expression at runtime before executing it ([#35923](https://github.com/angular/angular/issues/35923)) ([8c2d842](https://github.com/angular/angular/commit/8c2d842)), closes [#35689](https://github.com/angular/angular/issues/35689)
* **core:** workaround Terser inlining bug ([#36200](https://github.com/angular/angular/issues/36200)) ([f71d132](https://github.com/angular/angular/commit/f71d132))
* **elements:** correctly handle setting inputs to `undefined` ([#36140](https://github.com/angular/angular/issues/36140)) ([e066bdd](https://github.com/angular/angular/commit/e066bdd))
* **elements:** correctly set `SimpleChange#firstChange` for pre-existing inputs ([#36140](https://github.com/angular/angular/issues/36140)) ([447a600](https://github.com/angular/angular/commit/447a600)), closes [#36130](https://github.com/angular/angular/issues/36130)
* **elements:** schematics fail with schema.json not found error ([#35211](https://github.com/angular/angular/issues/35211)) ([94d002b](https://github.com/angular/angular/commit/94d002b)), closes [#35154](https://github.com/angular/angular/issues/35154)
* **forms:** change Array.reduce usage to Array.forEach ([#35349](https://github.com/angular/angular/issues/35349)) ([554c2cb](https://github.com/angular/angular/commit/554c2cb))
* **ivy:** `LFrame` needs to release memory on `leaveView()` ([#35156](https://github.com/angular/angular/issues/35156)) ([b9b512f](https://github.com/angular/angular/commit/b9b512f)), closes [#35148](https://github.com/angular/angular/issues/35148)
* **ivy:** add attributes and classes to host elements based on selector ([#34481](https://github.com/angular/angular/issues/34481)) ([f95b8ce](https://github.com/angular/angular/commit/f95b8ce))
* **ivy:** ensure module imports are instantiated before the module being declared ([#35172](https://github.com/angular/angular/issues/35172)) ([b6a3a73](https://github.com/angular/angular/commit/b6a3a73))
* **ivy:** error if directive with synthetic property binding is on same node as directive that injects ViewContainerRef ([#35343](https://github.com/angular/angular/issues/35343)) ([d6bc63f](https://github.com/angular/angular/commit/d6bc63f)), closes [#35342](https://github.com/angular/angular/issues/35342)
* **ivy:** narrow `NgIf` context variables in template type checker ([#35125](https://github.com/angular/angular/issues/35125)) ([40039d8](https://github.com/angular/angular/commit/40039d8)), closes [#34572](https://github.com/angular/angular/issues/34572)
* **ivy:** queries should match elements inside ng-container with the descendants: false option ([#35384](https://github.com/angular/angular/issues/35384)) ([3f4e02b](https://github.com/angular/angular/commit/3f4e02b)), closes [#34768](https://github.com/angular/angular/issues/34768)
* **ivy:** repeat template guards to narrow types in event handlers ([#35193](https://github.com/angular/angular/issues/35193)) ([dea1b96](https://github.com/angular/angular/commit/dea1b96)), closes [#35073](https://github.com/angular/angular/issues/35073)
* **ivy:** set namespace for host elements of dynamically created components ([#35136](https://github.com/angular/angular/issues/35136)) ([480a4c3](https://github.com/angular/angular/commit/480a4c3))
* **ivy:** support dynamic query tokens in AOT mode ([#35307](https://github.com/angular/angular/issues/35307)) ([3e3a1ef](https://github.com/angular/angular/commit/3e3a1ef)), closes [#34267](https://github.com/angular/angular/issues/34267)
* **ivy:** wrong context passed to ngOnDestroy when resolved multiple times ([#35249](https://github.com/angular/angular/issues/35249)) ([5fbfe69](https://github.com/angular/angular/commit/5fbfe69)), closes [#35167](https://github.com/angular/angular/issues/35167)
* **language-service:** Suggest ? and ! operator on nullable receiver ([#35200](https://github.com/angular/angular/issues/35200)) ([3cc24a9](https://github.com/angular/angular/commit/3cc24a9))
* **language-service:** fix calculation of pipe spans ([#35986](https://github.com/angular/angular/issues/35986)) ([406419b](https://github.com/angular/angular/commit/406419b))
* **language-service:** get the right 'ElementAst' in the nested HTML tag ([#35317](https://github.com/angular/angular/issues/35317)) ([8e354da](https://github.com/angular/angular/commit/8e354da))
* **language-service:** infer $implicit value for ngIf template contexts ([#35941](https://github.com/angular/angular/issues/35941)) ([18b1bd4](https://github.com/angular/angular/commit/18b1bd4))
* **language-service:** infer context type of structural directives ([#35537](https://github.com/angular/angular/issues/35537)) ([#35561](https://github.com/angular/angular/issues/35561)) ([54fd33f](https://github.com/angular/angular/commit/54fd33f))
* **language-service:** provide completions for the structural directive that only injects the 'ViewContainerRef' ([#35466](https://github.com/angular/angular/issues/35466)) ([66c06eb](https://github.com/angular/angular/commit/66c06eb))
* **language-service:** provide hover for interpolation in attribute value ([#35494](https://github.com/angular/angular/issues/35494)) ([049f118](https://github.com/angular/angular/commit/049f118)), closes [PR#34847](https://github.com/PR/issues/34847)
* **language-service:** resolve the real path for symlink ([#35895](https://github.com/angular/angular/issues/35895)) ([4e1d780](https://github.com/angular/angular/commit/4e1d780))
* **language-service:** resolve the variable from the template context first ([#35982](https://github.com/angular/angular/issues/35982)) ([3d46a45](https://github.com/angular/angular/commit/3d46a45))
* **localize:** allow ICU expansion case to start with any character except `}` ([#36123](https://github.com/angular/angular/issues/36123)) ([0767d37](https://github.com/angular/angular/commit/0767d37)), closes [#31586](https://github.com/angular/angular/issues/31586)
* **localize:** improve matching and parsing of XLIFF 1.2 translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([350ac11](https://github.com/angular/angular/commit/350ac11))
* **localize:** improve matching and parsing of XLIFF 2.0 translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([08071e5](https://github.com/angular/angular/commit/08071e5))
* **localize:** improve matching and parsing of XTB translation files ([#35793](https://github.com/angular/angular/issues/35793)) ([0e2a577](https://github.com/angular/angular/commit/0e2a577))
* **localize:** improve placeholder mismatch error message ([#35593](https://github.com/angular/angular/issues/35593)) ([53f059e](https://github.com/angular/angular/commit/53f059e))
* **localize:** merge translation from all XLIFF `<file>` elements ([#35936](https://github.com/angular/angular/issues/35936)) ([fc4c3c3](https://github.com/angular/angular/commit/fc4c3c3)), closes [#35839](https://github.com/angular/angular/issues/35839)
* **localize:** show helpful error when providing an invalid cli option ([#36010](https://github.com/angular/angular/issues/36010)) ([aad02e8](https://github.com/angular/angular/commit/aad02e8))
* **localize:** support minified ES5 `$localize` calls ([#35562](https://github.com/angular/angular/issues/35562)) ([df75451](https://github.com/angular/angular/commit/df75451)), closes [#35376](https://github.com/angular/angular/issues/35376)
* **ngcc:** add default config for `angular2-highcharts` ([#35527](https://github.com/angular/angular/issues/35527)) ([3cc8127](https://github.com/angular/angular/commit/3cc8127)), closes [#35399](https://github.com/angular/angular/issues/35399)
* **ngcc:** allow deep-import warnings to be ignored ([#35683](https://github.com/angular/angular/issues/35683)) ([20b0c80](https://github.com/angular/angular/commit/20b0c80)), closes [#35615](https://github.com/angular/angular/issues/35615)
* **ngcc:** capture path-mapped entry-points that start with same string ([#35592](https://github.com/angular/angular/issues/35592)) ([71b5970](https://github.com/angular/angular/commit/71b5970)), closes [#35536](https://github.com/angular/angular/issues/35536)
* **ngcc:** consistently delegate to TypeScript host for typing files ([#36089](https://github.com/angular/angular/issues/36089)) ([9e70bcb](https://github.com/angular/angular/commit/9e70bcb)), closes [#35078](https://github.com/angular/angular/issues/35078)
* **ngcc:** correctly detect emitted TS helpers in ES5 ([#35191](https://github.com/angular/angular/issues/35191)) ([bd6a39c](https://github.com/angular/angular/commit/bd6a39c))
* **ngcc:** correctly detect outer aliased class identifiers in ES5 ([#35527](https://github.com/angular/angular/issues/35527)) ([fde8915](https://github.com/angular/angular/commit/fde8915)), closes [#35399](https://github.com/angular/angular/issues/35399)
* **ngcc:** do not crash on entry-point that fails to compile ([#36083](https://github.com/angular/angular/issues/36083)) ([ff665b9](https://github.com/angular/angular/commit/ff665b9))
* **ngcc:** do not crash on overlapping entry-points ([#36083](https://github.com/angular/angular/issues/36083)) ([c9f554c](https://github.com/angular/angular/commit/c9f554c))
* **ngcc:** ensure that path-mapped secondary entry-points are processed correctly ([#35227](https://github.com/angular/angular/issues/35227)) ([c3c1140](https://github.com/angular/angular/commit/c3c1140)), closes [#35188](https://github.com/angular/angular/issues/35188)
* **ngcc:** handle imports in dts files when processing CommonJS ([#35191](https://github.com/angular/angular/issues/35191)) ([b6e8847](https://github.com/angular/angular/commit/b6e8847)), closes [#34356](https://github.com/angular/angular/issues/34356)
* **ngcc:** handle mappings outside the content when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([73cf7d5](https://github.com/angular/angular/commit/73cf7d5)), closes [#35709](https://github.com/angular/angular/issues/35709)
* **ngcc:** handle missing sources when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([72c4fda](https://github.com/angular/angular/commit/72c4fda)), closes [#35709](https://github.com/angular/angular/issues/35709)
* **ngcc:** handle multiple original sources when flattening source-maps ([#36027](https://github.com/angular/angular/issues/36027)) ([a40be00](https://github.com/angular/angular/commit/a40be00))
* **ngcc:** introduce a new LockFile implementation that uses a child-process ([#35861](https://github.com/angular/angular/issues/35861)) ([c55f900](https://github.com/angular/angular/commit/c55f900)), closes [#35761](https://github.com/angular/angular/issues/35761)
* **ngcc:** show helpful error when providing an invalid option ([#36010](https://github.com/angular/angular/issues/36010)) ([1f89c61](https://github.com/angular/angular/commit/1f89c61))
* **ngcc:** use path-mappings from tsconfig in dependency resolution ([#36180](https://github.com/angular/angular/issues/36180)) ([6defe96](https://github.com/angular/angular/commit/6defe96)), closes [#36119](https://github.com/angular/angular/issues/36119)
* **ngcc:** use preserve whitespaces from tsconfig if provided ([#36189](https://github.com/angular/angular/issues/36189)) ([aef4323](https://github.com/angular/angular/commit/aef4323)), closes [#35871](https://github.com/angular/angular/issues/35871)
* **platform-browser:** add missing peerDependency on `[@angular](https://github.com/angular)/animations` ([#35949](https://github.com/angular/angular/issues/35949)) ([64d6f13](https://github.com/angular/angular/commit/64d6f13)), closes [#35888](https://github.com/angular/angular/issues/35888)
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([c839c05](https://github.com/angular/angular/commit/c839c05)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com//github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
* **router:** state data missing in routerLink ([#33203](https://github.com/angular/angular/issues/33203)) ([de67978](https://github.com/angular/angular/commit/de67978))
* **service-worker:** treat 503 as offline ([#35595](https://github.com/angular/angular/issues/35595)) ([96cdf03](https://github.com/angular/angular/commit/96cdf03)), closes [#35571](https://github.com/angular/angular/issues/35571)
* fix flaky test cases of passive events ([#35679](https://github.com/angular/angular/issues/35679)) ([8ef29b6](https://github.com/angular/angular/commit/8ef29b6))
<a name="9.0.7"></a>
## [9.0.7](https://github.com/angular/angular/compare/9.0.6...9.0.7) (2020-03-18)
### Bug Fixes
* **compiler:** do not recurse to find static symbols of same module ([#35262](https://github.com/angular/angular/issues/35262)) ([a52b568](https://github.com/angular/angular/commit/a52b568))
* **compiler:** support directive inputs with interpolations on `<ng-template>`s ([#35984](https://github.com/angular/angular/issues/35984)) ([a6bf31b](https://github.com/angular/angular/commit/a6bf31b)), closes [#35752](https://github.com/angular/angular/issues/35752)
* **core:** don't re-invoke pure pipes that throw and arguments are the same ([#35827](https://github.com/angular/angular/issues/35827)) ([3fa632b](https://github.com/angular/angular/commit/3fa632b))
* **core:** verify parsed ICU expression at runtime before executing it ([#35923](https://github.com/angular/angular/issues/35923)) ([9cd115d](https://github.com/angular/angular/commit/9cd115d)), closes [#35689](https://github.com/angular/angular/issues/35689)
* **language-service:** infer $implicit value for ngIf template contexts ([#35941](https://github.com/angular/angular/issues/35941)) ([f5e4410](https://github.com/angular/angular/commit/f5e4410))
* **ngcc:** a new LockFile implementation that uses a child-process ([#35934](https://github.com/angular/angular/issues/35934)) ([743ce7b](https://github.com/angular/angular/commit/743ce7b)), closes [#35761](https://github.com/angular/angular/issues/35761)
* **ngcc:** consistently delegate to TypeScript host for typing files ([#36089](https://github.com/angular/angular/issues/36089)) ([76d7188](https://github.com/angular/angular/commit/76d7188)), closes [#35078](https://github.com/angular/angular/issues/35078)
* **ngcc:** handle multiple original sources when flattening source-maps ([#36027](https://github.com/angular/angular/issues/36027)) ([e6167cf](https://github.com/angular/angular/commit/e6167cf))
### Performance Improvements
* **ngcc:** link segment markers for faster traversal ([#36027](https://github.com/angular/angular/issues/36027)) ([a0fa63b](https://github.com/angular/angular/commit/a0fa63b))
* **ngcc:** store the position of SegmentMarkers to avoid unnecessary computation ([#36027](https://github.com/angular/angular/issues/36027)) ([4ce9098](https://github.com/angular/angular/commit/4ce9098))
* **ngcc:** use binary search when flattening mappings ([#36027](https://github.com/angular/angular/issues/36027)) ([8768fc4](https://github.com/angular/angular/commit/8768fc4))
* **ngcc:** use line start positions for computing offsets in source-map flattening ([#36027](https://github.com/angular/angular/issues/36027)) ([daa2a08](https://github.com/angular/angular/commit/daa2a08))
@ -57,53 +628,6 @@
* **ngcc:** reduce directory traversing ([#35756](https://github.com/angular/angular/issues/35756)) ([2eaf420](https://github.com/angular/angular/commit/2eaf420)), closes [#35717](https://github.com/angular/angular/issues/35717)
<a name="9.1.0-next.3"></a>
# [9.1.0-next.3](https://github.com/angular/angular/compare/9.1.0-next.2...9.1.0-next.3) (2020-03-04)
### Bug Fixes
* **animations:** allow computeStyle to work on elements created in Node ([#35810](https://github.com/angular/angular/issues/35810)) ([17cf04e](https://github.com/angular/angular/commit/17cf04e))
* **animations:** process shorthand `margin` and `padding` styles correctly ([#35701](https://github.com/angular/angular/issues/35701)) ([35c9f0d](https://github.com/angular/angular/commit/35c9f0d)), closes [#35463](https://github.com/angular/angular/issues/35463)
* **bazel:** ng_package rule creates incorrect UMD module exports ([#35792](https://github.com/angular/angular/issues/35792)) ([5c2a908](https://github.com/angular/angular/commit/5c2a908)), closes [angular/components#18652](https://github.com/angular/components/issues/18652)
* **compiler:** support i18n attributes on `<ng-template>` tags ([#35681](https://github.com/angular/angular/issues/35681)) ([40da51f](https://github.com/angular/angular/commit/40da51f))
* **compiler:** type-checking error for duplicate variables in templates ([#35674](https://github.com/angular/angular/issues/35674)) ([2c41bb8](https://github.com/angular/angular/commit/2c41bb8)), closes [#35186](https://github.com/angular/angular/issues/35186)
* **compiler-cli:** suppress extraRequire errors in Closure Compiler ([#35737](https://github.com/angular/angular/issues/35737)) ([c296bfc](https://github.com/angular/angular/commit/c296bfc))
* **core:** add `noSideEffects()` to `make*Decorator()` functions ([#35769](https://github.com/angular/angular/issues/35769)) ([dc6a791](https://github.com/angular/angular/commit/dc6a791))
* **core:** add `noSideEffects()` to `ɵɵdefineComponent()` ([#35769](https://github.com/angular/angular/issues/35769)) ([ba36127](https://github.com/angular/angular/commit/ba36127))
* **core:** allow null / undefined values in query results ([#35796](https://github.com/angular/angular/issues/35796)) ([5652fb1](https://github.com/angular/angular/commit/5652fb1)), closes [#35673](https://github.com/angular/angular/issues/35673)
* **core:** handle `<ng-template>` with local refs in i18n blocks ([#35758](https://github.com/angular/angular/issues/35758)) ([ef75875](https://github.com/angular/angular/commit/ef75875))
* **core:** log error instead of warning for unknown properties and elements ([#35798](https://github.com/angular/angular/issues/35798)) ([00f3c58](https://github.com/angular/angular/commit/00f3c58)), closes [#35699](https://github.com/angular/angular/issues/35699)
* **core:** Remove `debugger` statement ([#35763](https://github.com/angular/angular/issues/35763)) ([8f38eb7](https://github.com/angular/angular/commit/8f38eb7)), closes [#35470](https://github.com/angular/angular/issues/35470)
* **core:** Remove `debugger` statement when assert is thrown ([#35763](https://github.com/angular/angular/issues/35763)) ([4003538](https://github.com/angular/angular/commit/4003538)), closes [#35470](https://github.com/angular/angular/issues/35470)
* **core:** remove side effects from `ɵɵgetInheritedFactory()` ([#35769](https://github.com/angular/angular/issues/35769)) ([c195d22](https://github.com/angular/angular/commit/c195d22))
* **core:** remove side effects from `ɵɵNgOnChangesFeature()` ([#35769](https://github.com/angular/angular/issues/35769)) ([9cf85d2](https://github.com/angular/angular/commit/9cf85d2))
* **core:** treat `[class]` and `[className]` as unrelated bindings ([#35668](https://github.com/angular/angular/issues/35668)) ([a153b61](https://github.com/angular/angular/commit/a153b61)), closes [#35577](https://github.com/angular/angular/issues/35577)
* **core:** unable to NgModuleRef.injector in module constructor ([#35731](https://github.com/angular/angular/issues/35731)) ([1f8a243](https://github.com/angular/angular/commit/1f8a243)), closes [#35677](https://github.com/angular/angular/issues/35677) [#35639](https://github.com/angular/angular/issues/35639)
* **core:** use proper configuration to compile Injectable in JIT ([#35706](https://github.com/angular/angular/issues/35706)) ([7b13977](https://github.com/angular/angular/commit/7b13977))
* **ivy:** narrow `NgIf` context variables in template type checker ([#35125](https://github.com/angular/angular/issues/35125)) ([40039d8](https://github.com/angular/angular/commit/40039d8)), closes [#34572](https://github.com/angular/angular/issues/34572)
* **ivy:** support dynamic query tokens in AOT mode ([#35307](https://github.com/angular/angular/issues/35307)) ([3e3a1ef](https://github.com/angular/angular/commit/3e3a1ef)), closes [#34267](https://github.com/angular/angular/issues/34267)
* **ngcc:** allow deep-import warnings to be ignored ([#35683](https://github.com/angular/angular/issues/35683)) ([20b0c80](https://github.com/angular/angular/commit/20b0c80)), closes [#35615](https://github.com/angular/angular/issues/35615)
* **ngcc:** handle mappings outside the content when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([73cf7d5](https://github.com/angular/angular/commit/73cf7d5)), closes [#35709](https://github.com/angular/angular/issues/35709)
* **ngcc:** handle missing sources when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([72c4fda](https://github.com/angular/angular/commit/72c4fda)), closes [#35709](https://github.com/angular/angular/issues/35709)
### Features
* **language-service:** modularize error messages ([#35678](https://github.com/angular/angular/issues/35678)) ([47a1811](https://github.com/angular/angular/commit/47a1811)), closes [#32663](https://github.com/angular/angular/issues/32663)
* define all zone.js configurations to typescript interfaces ([#35329](https://github.com/angular/angular/issues/35329)) ([03d88c7](https://github.com/angular/angular/commit/03d88c7))
### Performance Improvements
* **core:** add micro benchmark for destroy hook invocation ([#35784](https://github.com/angular/angular/issues/35784)) ([0653db1](https://github.com/angular/angular/commit/0653db1))
* **core:** adding micro benchmark for host bindings ([#35705](https://github.com/angular/angular/issues/35705)) ([8fed1fe](https://github.com/angular/angular/commit/8fed1fe)), closes [#35568](https://github.com/angular/angular/issues/35568)
* **core:** use multiple directives in host bindings micro benchmark ([#35736](https://github.com/angular/angular/issues/35736)) ([5bc39f8](https://github.com/angular/angular/commit/5bc39f8))
* **ngcc:** only create tasks for non-processed formats ([#35719](https://github.com/angular/angular/issues/35719)) ([d7efc45](https://github.com/angular/angular/commit/d7efc45))
* **ngcc:** spawn workers lazily ([#35719](https://github.com/angular/angular/issues/35719)) ([dc40a93](https://github.com/angular/angular/commit/dc40a93)), closes [#35717](https://github.com/angular/angular/issues/35717)
<a name="9.0.5"></a>
## [9.0.5](https://github.com/angular/angular/compare/9.0.4...9.0.5) (2020-03-04)
@ -152,58 +676,6 @@
* **ngcc:** handle missing sources when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([7ff845b](https://github.com/angular/angular/commit/7ff845b)), closes [#35709](https://github.com/angular/angular/issues/35709)
<a name="9.1.0-next.2"></a>
# [9.1.0-next.2](https://github.com/angular/angular/compare/9.1.0-next.1...9.1.0-next.2) (2020-02-27)
### Bug Fixes
* **animations:** false positive when detecting Node in Webpack builds ([#35134](https://github.com/angular/angular/issues/35134)) ([dc4ae4b](https://github.com/angular/angular/commit/dc4ae4b)), closes [#35117](https://github.com/angular/angular/issues/35117)
* **animations:** Remove ɵAnimationDriver from private exports ([#35690](https://github.com/angular/angular/issues/35690)) ([ec789b0](https://github.com/angular/angular/commit/ec789b0))
* **compiler:** use FatalDiagnosticError to generate better error messages ([#35244](https://github.com/angular/angular/issues/35244)) ([646655d](https://github.com/angular/angular/commit/646655d))
* **core:** make subclass inherit developer-defined data ([#35105](https://github.com/angular/angular/issues/35105)) ([a756161](https://github.com/angular/angular/commit/a756161))
* **core:** support sanitizer value in the [style] bindings ([#35564](https://github.com/angular/angular/issues/35564)) ([3af103a](https://github.com/angular/angular/commit/3af103a)), closes [#35476](https://github.com/angular/angular/issues/35476)
* **core:** Add `style="{{exp}}"` based interpolation ([#34202](https://github.com/angular/angular/issues/34202)) ([2562a3b](https://github.com/angular/angular/commit/2562a3b)), closes [#33575](https://github.com/angular/angular/issues/33575)
* **core:** add strictLiteralTypes to align core + VE checking of literals ([#35462](https://github.com/angular/angular/issues/35462)) ([4253662](https://github.com/angular/angular/commit/4253662))
* **core:** better inference for circularly referenced directive types ([#35622](https://github.com/angular/angular/issues/35622)) ([173a1ac](https://github.com/angular/angular/commit/173a1ac)), closes [#35372](https://github.com/angular/angular/issues/35372) [#35603](https://github.com/angular/angular/issues/35603) [#35522](https://github.com/angular/angular/issues/35522)
* **core:** emulate a View Engine type-checking bug with safe navigation ([#35462](https://github.com/angular/angular/issues/35462)) ([a61fe41](https://github.com/angular/angular/commit/a61fe41))
* **core:** error in AOT when pipe inherits constructor from injectable that uses DI ([#35468](https://github.com/angular/angular/issues/35468)) ([e17bde9](https://github.com/angular/angular/commit/e17bde9)), closes [#35277](https://github.com/angular/angular/issues/35277)
* **core:** error when accessing NgModuleRef.componentFactoryResolver in constructor ([#35637](https://github.com/angular/angular/issues/35637)) ([835618c](https://github.com/angular/angular/commit/835618c)), closes [#35580](https://github.com/angular/angular/issues/35580)
* **core:** incorrectly generating shared pure function between null and object literal ([#35481](https://github.com/angular/angular/issues/35481)) ([22786c8](https://github.com/angular/angular/commit/22786c8)), closes [#33705](https://github.com/angular/angular/issues/33705) [#35298](https://github.com/angular/angular/issues/35298)
* **core:** injecting incorrect provider when re-providing injectable with useClass ([#34574](https://github.com/angular/angular/issues/34574)) ([0bc35a7](https://github.com/angular/angular/commit/0bc35a7)), closes [#34110](https://github.com/angular/angular/issues/34110)
* **core:** provide a more detailed error message for NG6002/NG6003 ([#35620](https://github.com/angular/angular/issues/35620)) ([2d89b5d](https://github.com/angular/angular/commit/2d89b5d))
* **language-service:** get the right 'ElementAst' in the nested HTML tag ([#35317](https://github.com/angular/angular/issues/35317)) ([8e354da](https://github.com/angular/angular/commit/8e354da))
* **language-service:** infer context type of structural directives ([#35537](https://github.com/angular/angular/issues/35537)) ([#35561](https://github.com/angular/angular/issues/35561)) ([54fd33f](https://github.com/angular/angular/commit/54fd33f))
* **language-service:** provide completions for the structural directive that only injects the 'ViewContainerRef' ([#35466](https://github.com/angular/angular/issues/35466)) ([66c06eb](https://github.com/angular/angular/commit/66c06eb))
* **language-service:** provide hover for interpolation in attribute value ([#35494](https://github.com/angular/angular/issues/35494)) ([049f118](https://github.com/angular/angular/commit/049f118)), closes [PR#34847](https://github.com/PR/issues/34847)
* **localize:** improve placeholder mismatch error message ([#35593](https://github.com/angular/angular/issues/35593)) ([53f059e](https://github.com/angular/angular/commit/53f059e))
* **localize:** support minified ES5 `$localize` calls ([#35562](https://github.com/angular/angular/issues/35562)) ([df75451](https://github.com/angular/angular/commit/df75451)), closes [#35376](https://github.com/angular/angular/issues/35376)
* **ngcc:** add default config for `angular2-highcharts` ([#35527](https://github.com/angular/angular/issues/35527)) ([3cc8127](https://github.com/angular/angular/commit/3cc8127)), closes [#35399](https://github.com/angular/angular/issues/35399)
* **ngcc:** capture path-mapped entry-points that start with same string ([#35592](https://github.com/angular/angular/issues/35592)) ([71b5970](https://github.com/angular/angular/commit/71b5970)), closes [#35536](https://github.com/angular/angular/issues/35536)
* **ngcc:** correctly detect emitted TS helpers in ES5 ([#35191](https://github.com/angular/angular/issues/35191)) ([bd6a39c](https://github.com/angular/angular/commit/bd6a39c))
* **ngcc:** correctly detect outer aliased class identifiers in ES5 ([#35527](https://github.com/angular/angular/issues/35527)) ([fde8915](https://github.com/angular/angular/commit/fde8915)), closes [#35399](https://github.com/angular/angular/issues/35399)
* **ngcc:** handle imports in dts files when processing CommonJS ([#35191](https://github.com/angular/angular/issues/35191)) ([b6e8847](https://github.com/angular/angular/commit/b6e8847)), closes [#34356](https://github.com/angular/angular/issues/34356)
* **router:** removed unused ApplicationRef dependency ([#35642](https://github.com/angular/angular/issues/35642)) ([c839c05](https://github.com/angular/angular/commit/c839c05)), closes [/github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97#diff-c0baae5e1df628e1a217e8dc38557](https://github.com//github.com/angular/angular/commit/5a849829c42330d7e88e83e916e6e36380c97a97/issues/diff-c0baae5e1df628e1a217e8dc38557)
* **service-worker:** treat 503 as offline ([#35595](https://github.com/angular/angular/issues/35595)) ([96cdf03](https://github.com/angular/angular/commit/96cdf03)), closes [#35571](https://github.com/angular/angular/issues/35571)
### Features
* **ngcc:** implement source-map flattening ([#35132](https://github.com/angular/angular/issues/35132)) ([df816c9](https://github.com/angular/angular/commit/df816c9))
* **bazel:** enable ivy template type-checking in g3 ([#35672](https://github.com/angular/angular/issues/35672)) ([8f5b7f3](https://github.com/angular/angular/commit/8f5b7f3))
* **zone.js** add interface definitions which zone extends EventTarget ([#35304](https://github.com/angular/angular/issues/35304)) ([4acb676](https://github.com/angular/angular/commit/4acb676)), closes [#35173](https://github.com/angular/angular/issues/35173)
* **zone.js** add a temp solution to support passive event listeners. ([#34503](https://github.com/angular/angular/issues/34503)) ([f9d483e](https://github.com/angular/angular/commit/f9d483e))
* **zone.js** add an tickOptions parameter with property processNewMacroTasksSynchronously. ([#33838](https://github.com/angular/angular/issues/33838)) ([17b862c](https://github.com/angular/angular/commit/17b862c)), closes [#33799](https://github.com/angular/angular/issues/33799)
* **zone.js** support passive event options by defining global variables in zone.js config file ([#34503](https://github.com/angular/angular/issues/34503)) ([d7d359e](https://github.com/angular/angular/commit/d7d359e))
### Performance Improvements
* **core:** avoid recursive scope recalculation when TestBed.overrideModule is used ([#35454](https://github.com/angular/angular/issues/35454)) ([0a1a989](https://github.com/angular/angular/commit/0a1a989))
* **ivy:** remove unused event argument in listener instructions ([#35097](https://github.com/angular/angular/issues/35097)) ([9228d7f](https://github.com/angular/angular/commit/9228d7f))
<a name="9.0.3"></a>
## [9.0.3](https://github.com/angular/angular/compare/9.0.2...9.0.3) (2020-02-27)
@ -251,28 +723,6 @@
<a name="9.1.0-next.1"></a>
# [9.1.0-next.1](https://github.com/angular/angular/compare/9.1.0-next.0...9.1.0-next.1) (2020-02-19)
### Bug Fixes
* **core:** better handing of ICUs outside of i18n blocks ([#35347](https://github.com/angular/angular/issues/35347)) ([c013dd4](https://github.com/angular/angular/commit/c013dd4))
* **core:** correctly concatenate static and dynamic binding to `class` when shadowed ([#35350](https://github.com/angular/angular/issues/35350)) ([8c75f21](https://github.com/angular/angular/commit/8c75f21)), closes [#35335](https://github.com/angular/angular/issues/35335)
* **core:** remove support for `Map`/`Set` in `[class]`/`[style]` bindings ([#35392](https://github.com/angular/angular/issues/35392)) ([2ca7984](https://github.com/angular/angular/commit/2ca7984))
* **ivy:** `LFrame` needs to release memory on `leaveView()` ([#35156](https://github.com/angular/angular/issues/35156)) ([b9b512f](https://github.com/angular/angular/commit/b9b512f)), closes [#35148](https://github.com/angular/angular/issues/35148)
* **ivy:** add attributes and classes to host elements based on selector ([#34481](https://github.com/angular/angular/issues/34481)) ([f95b8ce](https://github.com/angular/angular/commit/f95b8ce))
* **ivy:** error if directive with synthetic property binding is on same node as directive that injects ViewContainerRef ([#35343](https://github.com/angular/angular/issues/35343)) ([d6bc63f](https://github.com/angular/angular/commit/d6bc63f)), closes [#35342](https://github.com/angular/angular/issues/35342)
* **ivy:** queries should match elements inside ng-container with the descendants: false option ([#35384](https://github.com/angular/angular/issues/35384)) ([3f4e02b](https://github.com/angular/angular/commit/3f4e02b)), closes [#34768](https://github.com/angular/angular/issues/34768)
* **ivy:** wrong context passed to ngOnDestroy when resolved multiple times ([#35249](https://github.com/angular/angular/issues/35249)) ([5fbfe69](https://github.com/angular/angular/commit/5fbfe69)), closes [#35167](https://github.com/angular/angular/issues/35167)
### Features
* **ngcc:** pause async ngcc processing if another process has the lockfile ([#35131](https://github.com/angular/angular/issues/35131)) ([eef0753](https://github.com/angular/angular/commit/eef0753))
<a name="9.0.2"></a>
## [9.0.2](https://github.com/angular/angular/compare/9.0.1...9.0.2) (2020-02-19)
@ -290,29 +740,6 @@
<a name="9.1.0-next.0"></a>
## [9.1.0-next.0](https://github.com/angular/angular/compare/9.0.0...9.1.0-next.0) (2020-02-12)
### Bug Fixes
* **bazel:** devserver shows blank page in Windows ([#35159](https://github.com/angular/angular/issues/35159)) ([727f92f](https://github.com/angular/angular/commit/727f92f))
* **bazel:** spawn prod server using port 4200 ([#35160](https://github.com/angular/angular/issues/35160)) ([829f506](https://github.com/angular/angular/commit/829f506))
* **bazel:** update ibazel to 0.11.1 ([#35158](https://github.com/angular/angular/issues/35158)) ([4e6d237](https://github.com/angular/angular/commit/4e6d237))
* **compiler:** report errors for missing binding names ([#34595](https://github.com/angular/angular/issues/34595)) ([d13cab7](https://github.com/angular/angular/commit/d13cab7))
* **elements:** schematics fail with schema.json not found error ([#35211](https://github.com/angular/angular/issues/35211)) ([94d002b](https://github.com/angular/angular/commit/94d002b)), closes [#35154](https://github.com/angular/angular/issues/35154)
* **forms:** change Array.reduce usage to Array.forEach ([#35349](https://github.com/angular/angular/issues/35349)) ([554c2cb](https://github.com/angular/angular/commit/554c2cb))
* **ivy:** ensure module imports are instantiated before the module being declared ([#35172](https://github.com/angular/angular/issues/35172)) ([b6a3a73](https://github.com/angular/angular/commit/b6a3a73))
* **ivy:** repeat template guards to narrow types in event handlers ([#35193](https://github.com/angular/angular/issues/35193)) ([dea1b96](https://github.com/angular/angular/commit/dea1b96)), closes [#35073](https://github.com/angular/angular/issues/35073)
* **ivy:** set namespace for host elements of dynamically created components ([#35136](https://github.com/angular/angular/issues/35136)) ([480a4c3](https://github.com/angular/angular/commit/480a4c3))
* **language-service:** Suggest ? and ! operator on nullable receiver ([#35200](https://github.com/angular/angular/issues/35200)) ([3cc24a9](https://github.com/angular/angular/commit/3cc24a9))
* **ngcc:** ensure that path-mapped secondary entry-points are processed correctly ([#35227](https://github.com/angular/angular/issues/35227)) ([c3c1140](https://github.com/angular/angular/commit/c3c1140)), closes [#35188](https://github.com/angular/angular/issues/35188)
### Features
* **compiler-cli:** implement NgTscPlugin on top of the NgCompiler API ([#34792](https://github.com/angular/angular/issues/34792)) ([3c69442dbd](https://github.com/angular/angular/commit/3c69442dbd))
<a name="9.0.1"></a>
## [9.0.1](https://github.com/angular/angular/compare/9.0.0...9.0.1) (2020-02-12)

View File

@ -1,5 +1,4 @@
[![CircleCI](https://circleci.com/gh/angular/angular/tree/master.svg?style=shield)](https://circleci.com/gh/angular/workflows/angular/tree/master)
[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
[![Join the chat at https://gitter.im/angular/angular](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![npm version](https://badge.fury.io/js/%40angular%2Fcore.svg)](https://www.npmjs.com/@angular/core)
@ -21,7 +20,6 @@ Angular is a development platform for building mobile and desktop web applicatio
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
[quickstart]: https://angular.io/start
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md

View File

@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Fetch rules_nodejs so we can install our npm dependencies
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "2eca5b934dee47b5ff304f502ae187c40ec4e33e12bcbce872a2eeb786e23269",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.4.1/rules_nodejs-1.4.1.tar.gz"],
sha256 = "f9e7b9f42ae202cc2d2ce6d698ccb49a9f7f7ea572a78fd451696d03ef2ee116",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.6.0/rules_nodejs-1.6.0.tar.gz"],
)
# Check the rules_nodejs version and download npm dependencies
@ -17,7 +17,7 @@ http_archive(
# assert on that.
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
check_rules_nodejs_version(minimum_version_string = "1.4.1")
check_rules_nodejs_version(minimum_version_string = "1.6.0")
# Setup the Node.js toolchain
node_repositories(

View File

@ -18,8 +18,8 @@ Here are the most important tasks you might need to use:
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` mode in aio.
(Note: Docs examples run in `ViewEngine` mode by default. To turn on `ivy` mode in examples, see `yarn boilerplate:add` below.)
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` (pre-Ivy) mode in aio.
(Note: To turn on `ViewEngine` mode in docs examples, see `yarn boilerplate:add:viewengine` below.)
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
@ -34,7 +34,7 @@ Here are the most important tasks you might need to use:
* `yarn docs-test` - run the unit tests for the doc generation code.
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
* `yarn boilerplate:add:ivy` - same as `boilerplate:add` but also turns on `ivy` mode.
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
@ -44,7 +44,7 @@ Here are the most important tasks you might need to use:
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
_Requires `--setup` in order to take effect._
- `--ivy`: run e2e tests in `ivy` mode.
- `--viewengine`: run e2e tests in `ViewEngine` (pre-Ivy) mode.
- `--filter=foo`: limit e2e tests to those containing the word "foo".
> **Note for Windows users**

View File

@ -1,5 +1,5 @@
# Image metadata and config
FROM debian:stretch
FROM debian:buster
LABEL name="angular.io PR preview" \
description="This image implements the PR preview functionality for angular.io." \
@ -37,9 +37,9 @@ ARG TEST_AIO_NGINX_PORT_HTTPS=4433
ARG AIO_SIGNIFICANT_FILES_PATTERN='^(?:aio|packages)/(?!.*[._]spec\\.[jt]s$)'
ARG TEST_AIO_SIGNIFICANT_FILES_PATTERN=$AIO_SIGNIFICANT_FILES_PATTERN
ARG AIO_TRUSTED_PR_LABEL="aio: preview"
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
ARG TEST_AIO_TRUSTED_PR_LABEL=$AIO_TRUSTED_PR_LABEL
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=$AIO_PREVIEW_SERVER_HOSTNAME
ARG AIO_ARTIFACT_MAX_SIZE=26214400
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
ARG AIO_PREVIEW_SERVER_PORT=3000
@ -72,24 +72,29 @@ RUN mkdir /var/log/aio
# Add extra package sources
RUN apt-get update -y && apt-get install -y curl
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get update -y && apt-get install -y curl=7.64.0-4+deb10u1
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_12.x | bash -
RUN curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN echo "deb http://ftp.debian.org/debian stretch-backports main" | tee /etc/apt/sources.list.d/backports.list
# Install packages
# NOTE: Some packages (such as `nginx`, `nodejs`, `openssl`) make older versions unavailable on the
# repositories, so we cannot pin to specific versions for these packages :(
# See for example:
# - https://github.com/nodesource/distributions/issues/33
# - https://askubuntu.com/questions/715104/how-can-i-downgrade-openssl-via-apt-get
RUN apt-get update -y && apt-get install -y \
cron=3.0pl1-128+deb9u1 \
dnsmasq=2.76-5+deb9u2 \
nano=2.7.4-1 \
nginx=1.10.3-1+deb9u2 \
nodejs=10.15.3-1nodesource1 \
openssl=1.1.0j-1~deb9u1 \
rsyslog=8.24.0-1 \
yarn=1.15.2-1
RUN yarn global add pm2@3.5.0
cron=3.0pl1-134+deb10u1 \
dnsmasq=2.80-1 \
nano=3.2-3 \
nginx \
nodejs \
openssl \
rsyslog=8.1901.0-1 \
vim=2:8.1.0875-5 \
yarn=1.22.4-1
RUN yarn global add pm2@4.4.0
# Set up log rotation
@ -162,8 +167,7 @@ RUN find $AIO_SCRIPTS_SH_DIR -maxdepth 1 -type f -printf "%P\n" \
# Set up the Node.js scripts
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
WORKDIR $AIO_SCRIPTS_JS_DIR/
RUN yarn install --production --frozen-lockfile
RUN yarn --cwd="$AIO_SCRIPTS_JS_DIR/" install --production --frozen-lockfile
# Set up health check

View File

@ -35,6 +35,7 @@ export class BuildCleaner {
]);
} catch (error) {
this.logger.error('ERROR:', error);
throw error;
}
}

View File

@ -1,5 +1,4 @@
import * as express from 'express';
import {promisify} from 'util';
import {PreviewServerError} from './preview-error';
/**
@ -13,7 +12,7 @@ export async function respondWithError(res: express.Response, err: any): Promise
}
res.status(err.status);
await promisify(res.end.bind(res))(err.message);
return new Promise(resolve => res.end(err.message, resolve));
}
/**

View File

@ -93,7 +93,7 @@ class Helper {
return fs.readFileSync(absFilePath, 'utf8');
}
public runCmd(cmd: string, opts: cp.ExecFileOptions = {}): Promise<CmdResult> {
public runCmd(cmd: string, opts: cp.ExecOptions = {}): Promise<CmdResult> {
return new Promise(resolve => {
const proc = cp.exec(cmd, opts, (err, stdout, stderr) => resolve({success: !err, err, stdout, stderr}));
this.createCleanUpFn(() => proc.kill());
@ -101,7 +101,7 @@ class Helper {
}
public runForAllSupportedSchemes(suiteFactory: TestSuiteFactory): void {
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
Object.entries(this.portPerScheme).forEach(([scheme, port]) => suiteFactory(scheme, port));
}
public verifyResponse(status: number, regex: string | RegExp = /^/): VerifyCmdResultFn {

View File

@ -15,7 +15,7 @@ describe(`nginx`, () => {
afterEach(() => h.cleanUp());
it('should redirect HTTP to HTTPS', done => {
it('should redirect HTTP to HTTPS', async () => {
const httpHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTP}`;
const httpsHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTPS}`;
const urlMap = {
@ -24,16 +24,15 @@ describe(`nginx`, () => {
[`http://foo.${httpHost}/`]: `https://foo.${httpsHost}/`,
};
const verifyRedirection = (httpUrl: string) => h.runCmd(`curl -i ${httpUrl}`).then(result => {
const verifyRedirection = async (fromUrl: string, toUrl: string) => {
const result = await h.runCmd(`curl -i ${fromUrl}`);
h.verifyResponse(307)(result);
const headers = result.stdout.split(/(?:\r?\n){2,}/)[0];
expect(headers).toContain(`Location: ${urlMap[httpUrl]}`);
});
expect(headers).toContain(`Location: ${toUrl}`);
};
Promise.
all(Object.keys(urlMap).map(verifyRedirection)).
then(done);
await Promise.all(Object.entries(urlMap).map(urls => verifyRedirection(...urls)));
});
@ -62,15 +61,15 @@ describe(`nginx`, () => {
});
it('should return /index.html', done => {
it('should return /index.html', async () => {
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
Promise.all([
await Promise.all([
h.runCmd(`curl -iL ${origin}/index.html`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}/`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}`).then(h.verifyResponse(200, bodyRegex)),
]).then(done);
]);
});
@ -90,12 +89,11 @@ describe(`nginx`, () => {
});
it('should return /foo/bar.js', done => {
it('should return /foo/bar.js', async () => {
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /foo/bar\\.js$`);
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
then(h.verifyResponse(200, bodyRegex)).
then(done);
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
then(h.verifyResponse(200, bodyRegex));
});
@ -111,47 +109,46 @@ describe(`nginx`, () => {
});
it('should respond with 403 for directories', done => {
Promise.all([
it('should respond with 403 for directories', async () => {
await Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/`).then(h.verifyResponse(403)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo`).then(h.verifyResponse(403)),
]).then(done);
]);
});
it('should respond with 404 for unknown paths to files', done => {
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
then(h.verifyResponse(404)).
then(done);
it('should respond with 404 for unknown paths to files', async () => {
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
then(h.verifyResponse(404));
});
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', done => {
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', async () => {
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
Promise.all([
await Promise.all([
h.runCmd(`curl -iL ${origin}/foo/baz`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}/foo/baz/`).then(h.verifyResponse(200, bodyRegex)),
]).then(done);
]);
});
it('should respond with 404 for unknown PRs/SHAs', done => {
it('should respond with 404 for unknown PRs/SHAs', async () => {
const otherPr = 54321;
const otherShortSha = computeShortSha('8'.repeat(40));
Promise.all([
await Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}9-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${otherPr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}9.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${otherShortSha}.${host}`).then(h.verifyResponse(404)),
]).then(done);
]);
});
it('should respond with 404 if the subdomain format is wrong', done => {
Promise.all([
it('should respond with 404 if the subdomain format is wrong', async () => {
await Promise.all([
h.runCmd(`curl -iL ${scheme}://xpr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://prx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://xx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
@ -160,26 +157,25 @@ describe(`nginx`, () => {
h.runCmd(`curl -iL ${scheme}://${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}_${shortSha9}.${host}`).then(h.verifyResponse(404)),
]).then(done);
]);
});
it('should reject PRs with leading zeros', done => {
h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
then(h.verifyResponse(404)).
then(done);
it('should reject PRs with leading zeros', async () => {
await h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
then(h.verifyResponse(404));
});
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
it('should accept SHAs with leading zeros (but not trim the zeros)', async () => {
const bodyRegex9 = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
const bodyRegex0 = new RegExp(`^PR: ${pr} | SHA: ${sha0} | File: /index\\.html$`);
Promise.all([
await Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-0${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(200, bodyRegex9)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha0}.${host}`).then(h.verifyResponse(200, bodyRegex0)),
]).then(done);
]);
});
});
@ -231,23 +227,23 @@ describe(`nginx`, () => {
describe(`${host}/health-check`, () => {
it('should respond with 200', done => {
Promise.all([
it('should respond with 200', async () => {
await Promise.all([
h.runCmd(`curl -iL ${scheme}://${host}/health-check`).then(h.verifyResponse(200)),
h.runCmd(`curl -iL ${scheme}://${host}/health-check/`).then(h.verifyResponse(200)),
]).then(done);
]);
});
it('should respond with 404 if the path does not match exactly', done => {
Promise.all([
it('should respond with 404 if the path does not match exactly', async () => {
await Promise.all([
h.runCmd(`curl -iL ${scheme}://${host}/health-check/foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/health-check-foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/health-checknfoo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foo/health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foo-health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foonhealth-check`).then(h.verifyResponse(404)),
]).then(done);
]);
});
});
@ -291,29 +287,28 @@ describe(`nginx`, () => {
describe(`${host}/circle-build`, () => {
it('should disallow non-POST requests', done => {
it('should disallow non-POST requests', async () => {
const url = `${scheme}://${host}/circle-build`;
Promise.all([
await Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]).then(done);
]);
});
it('should pass requests through to the preview server', done => {
h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/)).
then(done);
it('should pass requests through to the preview server', async () => {
await h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/));
});
it('should respond with 404 for unknown paths', done => {
it('should respond with 404 for unknown paths', async () => {
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
Promise.all([
await Promise.all([
h.runCmd(`${cmdPrefix}/foo/circle-build/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-circle-build/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/fooncircle-build/`).then(h.verifyResponse(404)),
@ -322,7 +317,7 @@ describe(`nginx`, () => {
h.runCmd(`${cmdPrefix}/circle-buildnfoo/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/circle-build/pr`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/circle-build/42`).then(h.verifyResponse(404)),
]).then(done);
]);
});
});
@ -332,38 +327,33 @@ describe(`nginx`, () => {
const url = `${scheme}://${host}/pr-updated`;
it('should disallow non-POST requests', done => {
Promise.all([
it('should disallow non-POST requests', async () => {
await Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]).then(done);
]);
});
it('should pass requests through to the preview server', done => {
const cmdPrefix = `curl -iLX POST --header "Content-Type: application/json"`;
const cmd1 = `${cmdPrefix} ${url}`;
Promise.all([
h.runCmd(cmd1).then(h.verifyResponse(400, /Missing or empty 'number' field/)),
]).then(done);
it('should pass requests through to the preview server', async () => {
await h.runCmd(`curl -iLX POST --header "Content-Type: application/json" ${url}`).
then(h.verifyResponse(400, /Missing or empty 'number' field/));
});
it('should respond with 404 for unknown paths', done => {
it('should respond with 404 for unknown paths', async () => {
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
Promise.all([
await Promise.all([
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
]).then(done);
]);
});
});
@ -374,7 +364,7 @@ describe(`nginx`, () => {
beforeEach(() => {
['index.html', 'foo.js', 'foo/index.html'].forEach(relFilePath => {
const absFilePath = path.join(AIO_BUILDS_DIR, relFilePath);
return h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
});
});

View File

@ -105,9 +105,9 @@ describe('preview-server', () => {
describe(`${host}/circle-build`, () => {
const curl = makeCurl(`${host}/circle-build`);
it('should disallow non-POST requests', async () => {
const bodyRegex = /^Unknown resource/;
@ -189,8 +189,7 @@ describe('preview-server', () => {
});
it('should respond with 201 if a new public build is created', async () => {
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER))
.then(h.verifyResponse(201));
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).then(h.verifyResponse(201));
expect({ prNum: PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER }).toExistAsABuild();
});
@ -199,7 +198,7 @@ describe('preview-server', () => {
expect({ prNum: PrNums.TRUST_CHECK_UNTRUSTED, isPublic: false }).toExistAsABuild();
});
[true].forEach(isPublic => {
[true, false].forEach(isPublic => {
const build = isPublic ? BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : BuildNums.TRUST_CHECK_UNTRUSTED;
const prNum = isPublic ? PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : PrNums.TRUST_CHECK_UNTRUSTED;
const label = isPublic ? 'public' : 'non-public';
@ -364,23 +363,23 @@ describe('preview-server', () => {
describe(`${host}/health-check`, () => {
it('should respond with 200', done => {
Promise.all([
it('should respond with 200', async () => {
await Promise.all([
h.runCmd(`curl -iL ${host}/health-check`).then(h.verifyResponse(200)),
h.runCmd(`curl -iL ${host}/health-check/`).then(h.verifyResponse(200)),
]).then(done);
]);
});
it('should respond with 404 if the path does not match exactly', done => {
Promise.all([
it('should respond with 404 if the path does not match exactly', async () => {
await Promise.all([
h.runCmd(`curl -iL ${host}/health-check/foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/health-check-foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/health-checknfoo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foo/health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foo-health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foonhealth-check`).then(h.verifyResponse(404)),
]).then(done);
]);
});
});
@ -426,18 +425,18 @@ describe('preview-server', () => {
});
it('should respond with 404 for unknown paths', done => {
it('should respond with 404 for unknown paths', async () => {
const mockPayload = JSON.stringify({number: 1}); // MockExternalApiFlags.TRUST_CHECK_ACTIVE_TRUSTED_USER });
const cmdPrefix = `curl -iLX POST --data "${mockPayload}" ${host}`;
Promise.all([
await Promise.all([
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
]).then(done);
]);
});
@ -551,10 +550,10 @@ describe('preview-server', () => {
describe(`${host}/*`, () => {
it('should respond with 404 for requests to unknown URLs', done => {
it('should respond with 404 for requests to unknown URLs', async () => {
const bodyRegex = /^Unknown resource/;
Promise.all([
await Promise.all([
h.runCmd(`curl -iL ${host}/index.html`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iL ${host}/`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iL ${host}`).then(h.verifyResponse(404, bodyRegex)),
@ -562,7 +561,7 @@ describe('preview-server', () => {
h.runCmd(`curl -iLX POST ${host}`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iLX PATCH ${host}`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iLX DELETE ${host}`).then(h.verifyResponse(404, bodyRegex)),
]).then(done);
]);
});
});

View File

@ -14,42 +14,41 @@
"predev": "yarn build || true",
"dev": "run-p ~~build-watch ~~test-watch",
"lint": "tslint --project tsconfig.json",
"pretest": "yarn build",
"pretest": "run-s build lint",
"test": "yarn ~~test-only",
"pretest-watch": "yarn pretest",
"test-watch": "yarn ~~test-watch",
"~~build": "tsc",
"~~build-watch": "yarn ~~build --watch",
"pre~~test-only": "yarn lint",
"~~test-only": "node dist/test",
"~~test-watch": "nodemon --delay 1 --exec \"yarn ~~test-only\" --watch dist"
},
"dependencies": {
"body-parser": "^1.18.3",
"delete-empty": "^2.0.0",
"express": "^4.16.3",
"jasmine": "^3.2.0",
"nock": "^9.6.1",
"node-fetch": "^2.2.0",
"shelljs": "^0.8.2",
"source-map-support": "^0.5.9",
"tar-stream": "^1.6.1",
"tslib": "^1.10.0"
"body-parser": "^1.19.0",
"delete-empty": "^3.0.0",
"express": "^4.17.1",
"jasmine": "^3.5.0",
"nock": "^12.0.3",
"node-fetch": "^2.6.0",
"shelljs": "^0.8.4",
"source-map-support": "^0.5.19",
"tar-stream": "^2.1.2",
"tslib": "^1.11.1"
},
"devDependencies": {
"@types/body-parser": "^1.17.0",
"@types/express": "^4.16.0",
"@types/jasmine": "^2.8.8",
"@types/nock": "^9.3.0",
"@types/node": "^10.9.2",
"@types/node-fetch": "^2.1.2",
"@types/shelljs": "^0.8.0",
"@types/supertest": "^2.0.5",
"nodemon": "^1.18.3",
"@types/body-parser": "^1.19.0",
"@types/express": "^4.17.6",
"@types/jasmine": "^3.5.10",
"@types/nock": "^11.1.0",
"@types/node": "^13.13.2",
"@types/node-fetch": "^2.5.7",
"@types/shelljs": "^0.8.7",
"@types/supertest": "^2.0.8",
"nodemon": "^2.0.3",
"npm-run-all": "^4.1.5",
"supertest": "^3.1.0",
"tslint": "^5.11.0",
"supertest": "^4.0.2",
"tslint": "^6.1.1",
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
"typescript": "^3.0.1"
"typescript": "^3.8.3"
}
}

View File

@ -15,7 +15,6 @@ const EXISTING_DOWNLOADS = [
'20-1234567-build.zip',
];
const OPEN_PRS = [10, 40];
const ANY_DATE = jasmine.any(String);
// Tests
describe('BuildCleaner', () => {
@ -77,22 +76,18 @@ describe('BuildCleaner', () => {
let cleanerRemoveUnnecessaryDownloadsSpy: jasmine.Spy;
beforeEach(() => {
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers')
.and.callFake(() => Promise.resolve(EXISTING_BUILDS));
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers')
.and.callFake(() => Promise.resolve(OPEN_PRS));
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads')
.and.callFake(() => Promise.resolve(EXISTING_DOWNLOADS));
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers').and.resolveTo(EXISTING_BUILDS);
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers').and.resolveTo(OPEN_PRS);
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads').and.resolveTo(EXISTING_DOWNLOADS);
cleanerRemoveUnnecessaryBuildsSpy = spyOn(cleaner, 'removeUnnecessaryBuilds');
cleanerRemoveUnnecessaryDownloadsSpy = spyOn(cleaner, 'removeUnnecessaryDownloads');
});
it('should return a promise', async () => {
const promise = cleaner.cleanUp();
expect(promise).toEqual(jasmine.any(Promise));
expect(promise).toBeInstanceOf(Promise);
// Do not complete the test and release the spies synchronously, to avoid running the actual implementations.
await promise;
@ -130,52 +125,32 @@ describe('BuildCleaner', () => {
it('should reject if \'getOpenPrNumbers()\' rejects', async () => {
try {
cleanerGetOpenPrNumbersSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
cleanerGetOpenPrNumbersSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
});
it('should reject if \'getExistingBuildNumbers()\' rejects', async () => {
try {
cleanerGetExistingBuildNumbersSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
cleanerGetExistingBuildNumbersSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
});
it('should reject if \'getExistingDownloads()\' rejects', async () => {
try {
cleanerGetExistingDownloadsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
cleanerGetExistingDownloadsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
});
it('should reject if \'removeUnnecessaryBuilds()\' rejects', async () => {
try {
cleanerRemoveUnnecessaryBuildsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
cleanerRemoveUnnecessaryBuildsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
});
it('should reject if \'removeUnnecessaryDownloads()\' rejects', async () => {
try {
cleanerRemoveUnnecessaryDownloadsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
cleanerRemoveUnnecessaryDownloadsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
});
});
@ -187,13 +162,15 @@ describe('BuildCleaner', () => {
let promise: Promise<number[]>;
beforeEach(() => {
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
);
promise = cleaner.getExistingBuildNumbers();
});
it('should return a promise', () => {
expect(promise).toEqual(jasmine.any(Promise));
expect(promise).toBeInstanceOf(Promise);
});
@ -203,43 +180,27 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while getting the files', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
it('should reject if an error occurs while getting the files', async () => {
readdirCb('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the returned files (as numbers)', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
it('should resolve with the returned files (as numbers)', async () => {
readdirCb(null, ['12', '34', '56']);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', async () => {
readdirCb(null, [`${HIDDEN_DIR_PREFIX}12`, '34', `${HIDDEN_DIR_PREFIX}56`]);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
it('should ignore files with non-numeric (or zero) names', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
it('should ignore files with non-numeric (or zero) names', async () => {
readdirCb(null, ['12', 'foo', '34', 'bar', '56', '000']);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
});
@ -259,7 +220,7 @@ describe('BuildCleaner', () => {
it('should return a promise', () => {
expect(promise).toEqual(jasmine.any(Promise));
expect(promise).toBeInstanceOf(Promise);
});
@ -268,31 +229,15 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while fetching PRs', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
it('should reject if an error occurs while fetching PRs', async () => {
prDeferred.reject('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the numbers of the fetched PRs', done => {
promise.then(prNumbers => {
expect(prNumbers).toEqual([1, 2, 3]);
done();
});
it('should resolve with the numbers of the fetched PRs', async () => {
prDeferred.resolve([{id: 0, number: 1}, {id: 1, number: 2}, {id: 2, number: 3}]);
});
it('should log the number of open PRs', () => {
promise.then(prNumbers => {
expect(loggerLogSpy).toHaveBeenCalledWith(
ANY_DATE, 'BuildCleaner: ', `Open pull requests: ${prNumbers}`);
});
await expectAsync(promise).toBeResolvedTo([1, 2, 3]);
});
});
@ -304,13 +249,15 @@ describe('BuildCleaner', () => {
let promise: Promise<string[]>;
beforeEach(() => {
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
);
promise = cleaner.getExistingDownloads();
});
it('should return a promise', () => {
expect(promise).toEqual(jasmine.any(Promise));
expect(promise).toBeInstanceOf(Promise);
});
@ -320,33 +267,21 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while getting the files', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
it('should reject if an error occurs while getting the files', async () => {
readdirCb('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the returned file names', done => {
promise.then(result => {
expect(result).toEqual(EXISTING_DOWNLOADS);
done();
});
it('should resolve with the returned file names', async () => {
readdirCb(null, EXISTING_DOWNLOADS);
await expectAsync(promise).toBeResolvedTo(EXISTING_DOWNLOADS);
});
it('should ignore files that do not match the artifactPath', done => {
promise.then(result => {
expect(result).toEqual(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
done();
});
it('should ignore files that do not match the artifactPath', async () => {
readdirCb(null, ['10-ABCDEF-build.zip', '20-AAAAAAA-otherfile.zip', '30-FFFFFFF-build.zip']);
await expectAsync(promise).toBeResolvedTo(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
});
});
@ -364,7 +299,7 @@ describe('BuildCleaner', () => {
});
it('should test if the directory exists (and return if is does not)', () => {
it('should test if the directory exists (and return if it does not)', () => {
shellTestSpy.and.returnValue(false);
cleaner.removeDir('/foo/bar');
@ -381,22 +316,19 @@ describe('BuildCleaner', () => {
it('should make the directory and its content writable before removing', () => {
shellRmSpy.and.callFake(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar'));
cleaner.removeDir('/foo/bar');
expect(shellChmodSpy).toHaveBeenCalledBefore(shellRmSpy);
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar');
expect(shellRmSpy).toHaveBeenCalled();
});
it('should catch errors and log them', () => {
shellRmSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
shellRmSpy.and.throwError('Test');
cleaner.removeDir('/foo/bar');
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', 'Test');
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', new Error('Test'));
});
});
@ -449,7 +381,7 @@ describe('BuildCleaner', () => {
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(0);
cleanerRemoveDirSpy.calls.reset();
(cleaner as any).removeUnnecessaryBuilds([1, 2, 3, 4], []);
cleaner.removeUnnecessaryBuilds([1, 2, 3, 4], []);
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(8);
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/1'));
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/2'));

View File

@ -45,25 +45,15 @@ describe('CircleCIApi', () => {
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/${buildNum}?circle-token=${TOKEN}`);
try {
request.replyWithError(errorMessage);
await api.getBuildInfo(buildNum);
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
request.replyWithError(errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
try {
request.reply(404, errorMessage);
await api.getBuildInfo(buildNum);
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
request.reply(404, errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
});
});
@ -78,8 +68,7 @@ describe('CircleCIApi', () => {
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
.reply(200, [artifact0, artifact1, artifact2]);
const artifactUrl = await api.getBuildArtifactUrl(buildNum, 'some/path/1');
expect(artifactUrl).toEqual('https://url/1');
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeResolvedTo('https://url/1');
request.done();
});
@ -90,25 +79,15 @@ describe('CircleCIApi', () => {
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/${buildNum}/artifacts?circle-token=${TOKEN}`);
try {
request.replyWithError(errorMessage);
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
request.replyWithError(errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
try {
request.reply(404, errorMessage);
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
request.reply(404, errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
});
it('should throw an error if the response does not contain the specified artifact', async () => {
@ -121,14 +100,9 @@ describe('CircleCIApi', () => {
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
.reply(200, [artifact0, artifact1, artifact2]);
try {
await api.getBuildArtifactUrl(buildNum, 'some/path/3');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/3')).toBeRejectedWithError(
`CircleCI artifact URL request failed ` +
`(Missing artifact (some/path/3) for CircleCI build: ${buildNum})`);
}
});
});
});

View File

@ -118,7 +118,7 @@ describe('GithubApi', () => {
it('should return a promise', () => {
expect((api as any).getPaginated()).toEqual(jasmine.any(Promise));
expect((api as any).getPaginated()).toBeInstanceOf(Promise);
});
@ -131,45 +131,30 @@ describe('GithubApi', () => {
});
it('should reject if the request fails', done => {
(api as any).getPaginated('/foo/bar').catch((err: any) => {
expect(err).toBe('Test');
done();
});
it('should reject if the request fails', async () => {
const responsePromise = (api as any).getPaginated('/foo/bar');
deferreds[0].reject('Test');
await expectAsync(responsePromise).toBeRejectedWith('Test');
});
it('should resolve with the returned items', done => {
it('should resolve with the returned items', async () => {
const items = [{id: 1}, {id: 2}];
(api as any).getPaginated('/foo/bar').then((data: any) => {
expect(data).toEqual(items);
done();
});
const responsePromise = (api as any).getPaginated('/foo/bar');
deferreds[0].resolve(items);
await expectAsync(responsePromise).toBeResolvedTo(items);
});
it('should iteratively call \'get()\' to fetch all items', done => {
it('should iteratively call \'get()\' to fetch all items', async () => {
// Create an array or 250 objects.
const allItems = '.'.repeat(250).split('').map((_, i) => ({id: i}));
const allItems = new Array(250).fill(null).map((_, i) => ({id: i}));
const apiGetSpy = api.get as jasmine.Spy;
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
(api as any).getPaginated('/foo/bar', {baz: 'qux'}).then((data: any) => {
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
expect(apiGetSpy).toHaveBeenCalledTimes(3);
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
expect(data).toEqual(allItems);
done();
});
const responsePromise = (api as any).getPaginated('/foo/bar', {baz: 'qux'});
deferreds[0].resolve(allItems.slice(0, 100));
setTimeout(() => {
@ -178,6 +163,13 @@ describe('GithubApi', () => {
deferreds[2].resolve(allItems.slice(200));
}, 0);
}, 0);
await expectAsync(responsePromise).toBeResolvedTo(allItems);
expect(apiGetSpy).toHaveBeenCalledTimes(3);
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
});
});
@ -217,8 +209,8 @@ describe('GithubApi', () => {
describe('request()', () => {
it('should return a promise', () => {
nock('https://api.github.com').get('').reply(200);
expect((api as any).request()).toEqual(jasmine.any(Promise));
nock('https://api.github.com').get('/').reply(200);
expect((api as any).request()).toBeInstanceOf(Promise);
});
@ -247,9 +239,8 @@ describe('GithubApi', () => {
nock('https://api.github.com')
.intercept('/path', 'method')
.replyWithError('Test');
let message = 'Failed to reject error';
await (api as any).request('method', '/path').catch((err: any) => message = err.message);
expect(message).toEqual('Test');
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError('Test');
});
@ -263,81 +254,69 @@ describe('GithubApi', () => {
});
it('should reject if response statusCode is <200', done => {
it('should reject if response statusCode is <200', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(199);
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 199'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('failed');
expect(err).toContain('status: 199');
done();
});
requestHandler.done();
});
it('should reject if response statusCode is >=400', done => {
it('should reject if response statusCode is >=400', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(400);
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 400'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('failed');
expect(err).toContain('status: 400');
done();
});
requestHandler.done();
});
it('should include the response text in the rejection message', done => {
it('should include the response text in the rejection message', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(500, 'Test');
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('Test'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('Test');
done();
});
requestHandler.done();
});
it('should resolve if returned statusCode is >=200 and <400', done => {
it('should resolve if returned statusCode is >=200 and <400', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(200);
(api as any).request('method', '/path').then(done);
await expectAsync((api as any).request('method', '/path')).toBeResolved();
requestHandler.done();
});
it('should parse the response body into an object using \'JSON.parse\'', done => {
it('should parse the response body into an object using \'JSON.parse\'', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(300, '{"foo": "bar"}');
(api as any).request('method', '/path').then((data: any) => {
expect(data).toEqual({foo: 'bar'});
done();
});
await expectAsync((api as any).request('method', '/path')).toBeResolvedTo({foo: 'bar'});
requestHandler.done();
});
it('should reject if the response text is malformed JSON', done => {
it('should reject if the response text is malformed JSON', async () => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(300, '}');
(api as any).request('method', '/path').catch((err: any) => {
expect(err).toEqual(jasmine.any(SyntaxError));
done();
});
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError(SyntaxError);
requestHandler.done();
});

View File

@ -1,6 +1,6 @@
// Imports
import {GithubApi} from '../../lib/common/github-api';
import {GithubPullRequests} from '../../lib/common/github-pull-requests';
import {GithubPullRequests, PullRequest} from '../../lib/common/github-pull-requests';
// Tests
describe('GithubPullRequests', () => {
@ -47,27 +47,21 @@ describe('GithubPullRequests', () => {
it('should make a POST request to Github with the correct pathname, params and data', () => {
githubApi.post.and.callFake(() => Promise.resolve());
githubApi.post.and.resolveTo();
prs.addComment(42, 'body');
expect(githubApi.post).toHaveBeenCalledWith('/repos/foo/bar/issues/42/comments', null, {body: 'body'});
});
it('should reject if the request fails', done => {
githubApi.post.and.callFake(() => Promise.reject('Test'));
prs.addComment(42, 'body').catch(err => {
expect(err).toBe('Test');
done();
});
it('should reject if the request fails', async () => {
githubApi.post.and.rejectWith('Test');
await expectAsync(prs.addComment(42, 'body')).toBeRejectedWith('Test');
});
it('should resolve with the data from the Github POST', done => {
githubApi.post.and.callFake(() => Promise.resolve('Test'));
prs.addComment(42, 'body').then(data => {
expect(data).toBe('Test');
done();
});
it('should resolve with the data from the Github POST', async () => {
githubApi.post.and.resolveTo('Test');
await expectAsync(prs.addComment(42, 'body')).toBeResolvedTo('Test');
});
});
@ -87,13 +81,11 @@ describe('GithubPullRequests', () => {
});
it('should resolve with the data returned from GitHub', done => {
it('should resolve with the data returned from GitHub', async () => {
const expected: any = {number: 42};
githubApi.get.and.callFake(() => Promise.resolve(expected));
prs.fetch(42).then(data => {
expect(data).toEqual(expected);
done();
});
githubApi.get.and.resolveTo(expected);
await expectAsync(prs.fetch(42)).toBeResolvedTo(expected);
});
});
@ -125,9 +117,14 @@ describe('GithubPullRequests', () => {
});
it('should forward the value returned by \'getPaginated()\'', () => {
githubApi.getPaginated.and.returnValue('Test');
expect(prs.fetchAll() as any).toBe('Test');
it('should forward the value returned by \'getPaginated()\'', async () => {
const mockPrs: PullRequest[] = [
{number: 1, user: {login: 'foo'}, labels: []},
{number: 2, user: {login: 'bar'}, labels: []},
];
githubApi.getPaginated.and.resolveTo(mockPrs);
expect(await prs.fetchAll()).toBe(mockPrs);
});
});
@ -147,13 +144,11 @@ describe('GithubPullRequests', () => {
});
it('should resolve with the data returned from GitHub', done => {
it('should resolve with the data returned from GitHub', async () => {
const expected: any = [{sha: 'ABCDE', filename: 'a/b/c'}, {sha: '12345', filename: 'x/y/z'}];
githubApi.getPaginated.and.callFake(() => Promise.resolve(expected));
prs.fetchFiles(42).then(data => {
expect(data).toEqual(expected);
done();
});
githubApi.getPaginated.and.resolveTo(expected);
await expectAsync(prs.fetchFiles(42)).toBeResolvedTo(expected);
});
});

View File

@ -1,5 +1,5 @@
import {GithubApi} from '../../lib/common/github-api';
import {GithubTeams} from '../../lib/common/github-teams';
import {GithubTeams, Team} from '../../lib/common/github-teams';
// Tests
describe('GithubTeams', () => {
@ -16,6 +16,7 @@ describe('GithubTeams', () => {
expect(() => new GithubTeams(githubApi, '')).
toThrowError('Missing or empty required parameter \'githubOrg\'!');
});
});
@ -33,9 +34,14 @@ describe('GithubTeams', () => {
});
it('should forward the value returned by \'getPaginated()\'', () => {
githubApi.getPaginated.and.returnValue('Test');
expect(teams.fetchAll() as any).toBe('Test');
it('should forward the value returned by \'getPaginated()\'', async () => {
const mockTeams: Team[] = [
{id: 1, slug: 'foo'},
{id: 2, slug: 'bar'},
];
githubApi.getPaginated.and.resolveTo(mockTeams);
expect(await teams.fetchAll()).toBe(mockTeams);
});
});
@ -50,100 +56,77 @@ describe('GithubTeams', () => {
it('should return a promise', () => {
githubApi.get.and.callFake(() => Promise.resolve());
githubApi.get.and.resolveTo();
const promise = teams.isMemberById('user', [1]);
expect(promise).toEqual(jasmine.any(Promise));
expect(promise).toBeInstanceOf(Promise);
});
it('should resolve with false if called with an empty array', done => {
teams.isMemberById('user', []).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).not.toHaveBeenCalled();
done();
});
it('should resolve with false if called with an empty array', async () => {
await expectAsync(teams.isMemberById('user', [])).toBeResolvedTo(false);
expect(githubApi.get).not.toHaveBeenCalled();
});
it('should call \'get()\' with the correct pathname', done => {
githubApi.get.and.callFake(() => Promise.resolve());
teams.isMemberById('user', [1]).then(() => {
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
done();
});
it('should call \'get()\' with the correct pathname', async () => {
githubApi.get.and.resolveTo();
await teams.isMemberById('user', [1]);
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
});
it('should resolve with false if \'get()\' rejects', done => {
githubApi.get.and.callFake(() => Promise.reject(null));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).toHaveBeenCalled();
done();
});
it('should resolve with false if \'get()\' rejects', async () => {
githubApi.get.and.rejectWith(null);
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
expect(githubApi.get).toHaveBeenCalled();
});
it('should resolve with false if the membership is not active', done => {
githubApi.get.and.callFake(() => Promise.resolve({state: 'pending'}));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).toHaveBeenCalled();
done();
});
it('should resolve with false if the membership is not active', async () => {
githubApi.get.and.resolveTo({state: 'pending'});
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
expect(githubApi.get).toHaveBeenCalled();
});
it('should resolve with true if the membership is active', done => {
githubApi.get.and.callFake(() => Promise.resolve({state: 'active'}));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(true);
done();
});
it('should resolve with true if the membership is active', async () => {
githubApi.get.and.resolveTo({state: 'active'});
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(true);
});
it('should sequentially call \'get()\' until an active membership is found', done => {
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
'/teams/2/memberships/user': Promise.reject(null),
'/teams/3/memberships/user': Promise.resolve({state: 'active'}),
};
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
it('should sequentially call \'get()\' until an active membership is found', async () => {
githubApi.get.
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
withArgs('/teams/2/memberships/user').and.rejectWith(null).
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'active'});
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
expect(isMember).toBe(true);
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(true);
expect(githubApi.get).toHaveBeenCalledTimes(3);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
done();
});
expect(githubApi.get).toHaveBeenCalledTimes(3);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
});
it('should resolve with false if no active membership is found', done => {
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
'/teams/2/memberships/user': Promise.reject(null),
'/teams/3/memberships/user': Promise.resolve({state: 'not active'}),
'/teams/4/memberships/user': Promise.reject(null),
};
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
it('should resolve with false if no active membership is found', async () => {
githubApi.get.
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
withArgs('/teams/2/memberships/user').and.rejectWith(null).
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'not active'}).
withArgs('/teams/4/memberships/user').and.rejectWith(null);
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
expect(isMember).toBe(false);
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(false);
expect(githubApi.get).toHaveBeenCalledTimes(4);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
done();
});
expect(githubApi.get).toHaveBeenCalledTimes(4);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
});
});
@ -157,14 +140,13 @@ describe('GithubTeams', () => {
beforeEach(() => {
teams = new GithubTeams(githubApi, 'foo');
const mockResponse = Promise.resolve([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.returnValue(mockResponse);
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.resolveTo([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
teamsIsMemberByIdSpy = spyOn(teams, 'isMemberById');
});
it('should return a promise', () => {
expect(teams.isMemberBySlug('user', ['team-slug'])).toEqual(jasmine.any(Promise));
expect(teams.isMemberBySlug('user', ['team-slug'])).toBeInstanceOf(Promise);
});
@ -174,55 +156,46 @@ describe('GithubTeams', () => {
});
it('should resolve with false if \'fetchAll()\' rejects', done => {
teamsFetchAllSpy.and.callFake(() => Promise.reject(null));
teams.isMemberBySlug('user', ['team-slug']).then(isMember => {
expect(isMember).toBe(false);
done();
});
it('should resolve with false if \'fetchAll()\' rejects', async () => {
teamsFetchAllSpy.and.rejectWith(null);
await expectAsync(teams.isMemberBySlug('user', ['team-slug'])).toBeResolvedTo(false);
});
it('should call \'isMemberById()\' with the correct params if no team is found', done => {
teams.isMemberBySlug('user', ['no-match']).then(() => {
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
done();
});
it('should call \'isMemberById()\' with the correct params if no team is found', async () => {
await teams.isMemberBySlug('user', ['no-match']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
});
it('should call \'isMemberById()\' with the correct params if teams are found', done => {
const spy = teamsIsMemberByIdSpy;
it('should call \'isMemberById()\' with the correct params if teams are found', async () => {
await teams.isMemberBySlug('userA', ['team1']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
Promise.all([
teams.isMemberBySlug('user', ['team1']).then(() => expect(spy).toHaveBeenCalledWith('user', [1])),
teams.isMemberBySlug('user', ['team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [2])),
teams.isMemberBySlug('user', ['team1', 'team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [1, 2])),
]).then(done);
await teams.isMemberBySlug('userB', ['team2']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [2]);
await teams.isMemberBySlug('userC', ['team1', 'team2']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userC', [1, 2]);
});
it('should resolve with false if \'isMemberById()\' rejects', done => {
teamsIsMemberByIdSpy.and.callFake(() => Promise.reject(null));
teams.isMemberBySlug('user', ['team1']).then(isMember => {
expect(isMember).toBe(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
done();
});
it('should resolve with false if \'isMemberById()\' rejects', async () => {
teamsIsMemberByIdSpy.and.rejectWith(null);
await expectAsync(teams.isMemberBySlug('user', ['team1'])).toBeResolvedTo(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
});
it('should resolve with the value \'isMemberById()\' resolves with', async () => {
teamsIsMemberByIdSpy.and.resolveTo(true);
await expectAsync(teams.isMemberBySlug('userA', ['team1'])).toBeResolvedTo(true);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(true));
const isMember1 = await teams.isMemberBySlug('user', ['team1']);
expect(isMember1).toBe(true);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(false));
const isMember2 = await teams.isMemberBySlug('user', ['team1']);
expect(isMember2).toBe(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
teamsIsMemberByIdSpy.and.resolveTo(false);
await expectAsync(teams.isMemberBySlug('userB', ['team1'])).toBeResolvedTo(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [1]);
});
});

View File

@ -9,7 +9,8 @@ import {Logger} from '../../lib/common/utils';
import {BuildCreator} from '../../lib/preview-server/build-creator';
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
import {PreviewServerError} from '../../lib/preview-server/preview-error';
import {expectToBePreviewServerError} from './helpers';
import {customAsyncMatchers} from './jasmine-custom-async-matchers';
// Tests
describe('BuildCreator', () => {
@ -24,6 +25,7 @@ describe('BuildCreator', () => {
const publicShaDir = path.join(publicPrDir, shortSha);
let bc: BuildCreator;
beforeEach(() => jasmine.addAsyncMatchers(customAsyncMatchers));
beforeEach(() => bc = new BuildCreator(buildsDir));
@ -35,8 +37,8 @@ describe('BuildCreator', () => {
it('should extend EventEmitter', () => {
expect(bc).toEqual(jasmine.any(BuildCreator));
expect(bc).toEqual(jasmine.any(EventEmitter));
expect(bc).toBeInstanceOf(BuildCreator);
expect(bc).toBeInstanceOf(EventEmitter);
expect(Object.getPrototypeOf(bc)).toBe(BuildCreator.prototype);
});
@ -67,47 +69,43 @@ describe('BuildCreator', () => {
const shaDir = isPublic ? publicShaDir : hiddenShaDir;
it('should return a promise', done => {
it('should return a promise', async () => {
const promise = bc.create(pr, sha, archive, isPublic);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `extractArchive()`.
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
// Do not complete the test (and release the spies) synchronously to avoid running the actual
// `extractArchive()`.
await promise;
});
it('should update the PR\'s visibility first if necessary', done => {
bcUpdatePrVisibilitySpy.and.callFake(() => expect(shellMkdirSpy).not.toHaveBeenCalled());
it('should update the PR\'s visibility first if necessary', async () => {
await bc.create(pr, sha, archive, isPublic);
bc.create(pr, sha, archive, isPublic).
then(() => {
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
expect(shellMkdirSpy).toHaveBeenCalled();
}).
then(done);
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledBefore(shellMkdirSpy);
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
expect(shellMkdirSpy).toHaveBeenCalled();
});
it('should create the build directory (and any parent directories)', done => {
bc.create(pr, sha, archive, isPublic).
then(() => expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir)).
then(done);
it('should create the build directory (and any parent directories)', async () => {
await bc.create(pr, sha, archive, isPublic);
expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir);
});
it('should extract the archive contents into the build directory', done => {
bc.create(pr, sha, archive, isPublic).
then(() => expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir)).
then(done);
it('should extract the archive contents into the build directory', async () => {
await bc.create(pr, sha, archive, isPublic);
expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir);
});
it('should emit a CreatedBuildEvent on success', done => {
it('should emit a CreatedBuildEvent on success', async () => {
let emitted = false;
bcEmitSpy.and.callFake((type: string, evt: CreatedBuildEvent) => {
expect(type).toBe(CreatedBuildEvent.type);
expect(evt).toEqual(jasmine.any(CreatedBuildEvent));
expect(evt).toBeInstanceOf(CreatedBuildEvent);
expect(evt.pr).toBe(+pr);
expect(evt.sha).toBe(shortSha);
expect(evt.isPublic).toBe(isPublic);
@ -115,130 +113,108 @@ describe('BuildCreator', () => {
emitted = true;
});
bc.create(pr, sha, archive, isPublic).
then(() => expect(emitted).toBe(true)).
then(done);
await bc.create(pr, sha, archive, isPublic);
expect(emitted).toBe(true);
});
describe('on error', () => {
let existsValues: {[dir: string]: boolean};
beforeEach(() => {
existsValues = {
[prDir]: false,
[shaDir]: false,
};
bcExistsSpy.and.callFake((dir: string) => existsValues[dir]);
bcExistsSpy.and.returnValue(false);
});
it('should abort and skip further operations if changing the PR\'s visibility fails', done => {
it('should abort and skip further operations if changing the PR\'s visibility fails', async () => {
const mockError = new PreviewServerError(543, 'Test');
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject(mockError));
bcUpdatePrVisibilitySpy.and.rejectWith(mockError);
bc.create(pr, sha, archive, isPublic).catch(err => {
expect(err).toBe(mockError);
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWith(mockError);
expect(bcExistsSpy).not.toHaveBeenCalled();
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
expect(bcExistsSpy).not.toHaveBeenCalled();
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if the build does already exist', done => {
existsValues[shaDir] = true;
bc.create(pr, sha, archive, isPublic).catch(err => {
const publicOrNot = isPublic ? 'public' : 'non-public';
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
it('should abort and skip further operations if the build does already exist', async () => {
bcExistsSpy.withArgs(shaDir).and.returnValue(true);
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should detect existing build directory after visibility change', done => {
bcUpdatePrVisibilitySpy.and.callFake(() => existsValues[prDir] = existsValues[shaDir] = true);
it('should detect existing build directory after visibility change', async () => {
bcUpdatePrVisibilitySpy.and.callFake(() => bcExistsSpy.and.returnValue(true));
expect(bcExistsSpy(prDir)).toBe(false);
expect(bcExistsSpy(shaDir)).toBe(false);
bc.create(pr, sha, archive, isPublic).catch(err => {
const publicOrNot = isPublic ? 'public' : 'non-public';
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to create the directories', done => {
it('should abort and skip further operations if it fails to create the directories', async () => {
shellMkdirSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to extract the archive', done => {
bcExtractArchiveSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should delete the PR directory (for new PR)', done => {
bcExtractArchiveSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
done();
});
});
it('should delete the SHA directory (for existing PR)', done => {
existsValues[prDir] = true;
it('should abort and skip further operations if it fails to extract the archive', async () => {
bcExtractArchiveSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
done();
});
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should reject with an PreviewServerError', done => {
it('should delete the PR directory (for new PR)', async () => {
bcExtractArchiveSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
});
it('should delete the SHA directory (for existing PR)', async () => {
bcExistsSpy.withArgs(prDir).and.returnValue(true);
bcExtractArchiveSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
});
it('should reject with an PreviewServerError', async () => {
// tslint:disable-next-line: no-string-throw
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
bc.create(pr, sha, archive, isPublic).catch(err => {
expectToBePreviewServerError(err, 500, `Error while creating preview at: ${shaDir}\nTest`);
done();
});
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
500, `Error while creating preview at: ${shaDir}\nTest`);
});
it('should pass PreviewServerError instances unmodified', done => {
it('should pass PreviewServerError instances unmodified', async () => {
shellMkdirSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
bc.create(pr, sha, archive, isPublic).catch(err => {
expectToBePreviewServerError(err, 543, 'Test');
done();
});
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(543, 'Test');
});
});
@ -265,12 +241,12 @@ describe('BuildCreator', () => {
});
it('should return a promise', done => {
it('should return a promise', async () => {
const promise = bc.updatePrVisibility(pr, true);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `extractArchive()`.
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
// Do not complete the test (and release the spies) synchronously to avoid running the actual `extractArchive()`.
await promise;
});
@ -279,58 +255,53 @@ describe('BuildCreator', () => {
const newPrDir = makePublic ? publicPrDir : hiddenPrDir;
it('should rename the directory', done => {
bc.updatePrVisibility(pr, makePublic).
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
then(done);
it('should rename the directory', async () => {
await bc.updatePrVisibility(pr, makePublic);
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
});
describe('when the visibility is updated', () => {
it('should resolve to true', done => {
bc.updatePrVisibility(pr, makePublic).
then(result => expect(result).toBe(true)).
then(done);
it('should resolve to true', async () => {
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(true);
});
it('should rename the directory', done => {
bc.updatePrVisibility(pr, makePublic).
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
then(done);
it('should rename the directory', async () => {
await bc.updatePrVisibility(pr, makePublic);
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
});
it('should emit a ChangedPrVisibilityEvent on success', done => {
it('should emit a ChangedPrVisibilityEvent on success', async () => {
let emitted = false;
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
expect(type).toBe(ChangedPrVisibilityEvent.type);
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
expect(evt.pr).toBe(+pr);
expect(evt.shas).toEqual(jasmine.any(Array));
expect(evt.shas).toBeInstanceOf(Array);
expect(evt.isPublic).toBe(makePublic);
emitted = true;
});
bc.updatePrVisibility(pr, makePublic).
then(() => expect(emitted).toBe(true)).
then(done);
await bc.updatePrVisibility(pr, makePublic);
expect(emitted).toBe(true);
});
it('should include all shas in the emitted event', done => {
it('should include all shas in the emitted event', async () => {
const shas = ['foo', 'bar', 'baz'];
let emitted = false;
bcListShasByDate.and.callFake(() => Promise.resolve(shas));
bcListShasByDate.and.resolveTo(shas);
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
expect(bcListShasByDate).toHaveBeenCalledWith(newPrDir);
expect(type).toBe(ChangedPrVisibilityEvent.type);
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
expect(evt.pr).toBe(+pr);
expect(evt.shas).toBe(shas);
expect(evt.isPublic).toBe(makePublic);
@ -338,94 +309,82 @@ describe('BuildCreator', () => {
emitted = true;
});
bc.updatePrVisibility(pr, makePublic).
then(() => expect(emitted).toBe(true)).
then(done);
await bc.updatePrVisibility(pr, makePublic);
expect(emitted).toBe(true);
});
});
it('should do nothing if the visibility is already up-to-date', done => {
it('should do nothing if the visibility is already up-to-date', async () => {
bcExistsSpy.and.callFake((dir: string) => dir === newPrDir);
bc.updatePrVisibility(pr, makePublic).
then(result => {
expect(result).toBe(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
}).
then(done);
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should do nothing if the PR directory does not exist', done => {
it('should do nothing if the PR directory does not exist', async () => {
bcExistsSpy.and.returnValue(false);
bc.updatePrVisibility(pr, makePublic).
then(result => {
expect(result).toBe(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
}).
then(done);
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
describe('on error', () => {
it('should abort and skip further operations if both directories exist', done => {
it('should abort and skip further operations if both directories exist', async () => {
bcExistsSpy.and.returnValue(true);
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 409,
`Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
409, `Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to rename the directory', done => {
it('should abort and skip further operations if it fails to rename the directory', async () => {
shellMvSpy.and.throwError('');
bc.updatePrVisibility(pr, makePublic).catch(() => {
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to list the SHAs', done => {
it('should abort and skip further operations if it fails to list the SHAs', async () => {
bcListShasByDate.and.throwError('');
bc.updatePrVisibility(pr, makePublic).catch(() => {
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
});
it('should reject with an PreviewServerError', done => {
it('should reject with an PreviewServerError', async () => {
// tslint:disable-next-line: no-string-throw
shellMvSpy.and.callFake(() => { throw 'Test'; });
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 500,
`Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
done();
});
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
});
it('should pass PreviewServerError instances unmodified', done => {
it('should pass PreviewServerError instances unmodified', async () => {
shellMvSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 543, 'Test');
done();
});
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(543, 'Test');
});
});
@ -443,12 +402,14 @@ describe('BuildCreator', () => {
beforeEach(() => {
fsAccessCbs = [];
fsAccessSpy = spyOn(fs, 'access').and.callFake((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb));
fsAccessSpy = spyOn(fs, 'access').and.callFake(
((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb)) as unknown as typeof fs.access,
);
});
it('should return a promise', () => {
expect((bc as any).exists('foo')).toEqual(jasmine.any(Promise));
expect((bc as any).exists('foo')).toBeInstanceOf(Promise);
});
@ -458,25 +419,29 @@ describe('BuildCreator', () => {
});
it('should resolve with \'true\' if \'fs.access()\' succeeds', done => {
Promise.
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
then(results => expect(results).toEqual([true, true])).
then(done);
it('should resolve with \'true\' if \'fs.access()\' succeeds', async () => {
const existsPromises = [
(bc as any).exists('foo'),
(bc as any).exists('bar'),
];
fsAccessCbs[0]();
fsAccessCbs[1](null);
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([true, true]);
});
it('should resolve with \'false\' if \'fs.access()\' errors', done => {
Promise.
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
then(results => expect(results).toEqual([false, false])).
then(done);
it('should resolve with \'false\' if \'fs.access()\' errors', async () => {
const existsPromises = [
(bc as any).exists('foo'),
(bc as any).exists('bar'),
];
fsAccessCbs[0]('Error');
fsAccessCbs[1](new Error());
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([false, false]);
});
});
@ -495,12 +460,15 @@ describe('BuildCreator', () => {
consoleWarnSpy = spyOn(Logger.prototype, 'warn');
shellChmodSpy = spyOn(shell, 'chmod');
shellRmSpy = spyOn(shell, 'rm');
cpExecSpy = spyOn(cp, 'exec').and.callFake((_: string, cb: (...args: any[]) => void) => cpExecCbs.push(cb));
cpExecSpy = spyOn(cp, 'exec').and.callFake(
((_: string, cb: (...args: any[]) => void) =>
cpExecCbs.push(cb)) as unknown as typeof cp.exec,
);
});
it('should return a promise', () => {
expect((bc as any).extractArchive('foo', 'bar')).toEqual(jasmine.any(Promise));
expect((bc as any).extractArchive('foo', 'bar')).toBeInstanceOf(Promise);
});
@ -512,78 +480,68 @@ describe('BuildCreator', () => {
});
it('should log (as a warning) any stderr output if extracting succeeded', done => {
(bc as any).extractArchive('foo', 'bar').
then(() => expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr')).
then(done);
it('should log (as a warning) any stderr output if extracting succeeded', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0](null, 'This is stdout', 'This is stderr');
await expectAsync(extractPromise).toBeResolved();
expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr');
});
it('should make the build directory non-writable', done => {
(bc as any).extractArchive('foo', 'bar').
then(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar')).
then(done);
it('should make the build directory non-writable', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeResolved();
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar');
});
it('should delete the build artifact file on success', done => {
(bc as any).extractArchive('input/file', 'output/dir').
then(() => expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file')).
then(done);
it('should delete the build artifact file on success', async () => {
const extractPromise = (bc as any).extractArchive('input/file', 'output/dir');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeResolved();
expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file');
});
describe('on error', () => {
it('should abort and skip further operations if it fails to extract the archive', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).not.toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
it('should abort and skip further operations if it fails to extract the archive', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]('Test');
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).not.toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to make non-writable', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
shellChmodSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
it('should abort and skip further operations if it fails to make non-writable', async () => {
// tslint:disable-next-line: no-string-throw
shellChmodSpy.and.callFake(() => { throw 'Test'; });
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
});
it('should abort and reject if it fails to remove the build artifact file', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
shellRmSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
it('should abort and reject if it fails to remove the build artifact file', async () => {
// tslint:disable-next-line: no-string-throw
shellRmSpy.and.callFake(() => { throw 'Test'; });
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).toHaveBeenCalled();
});
});
@ -600,62 +558,54 @@ describe('BuildCreator', () => {
});
beforeEach(() => {
shellLsSpy = spyOn(shell, 'ls').and.returnValue([]);
shellLsSpy = spyOn(shell, 'ls').and.returnValue([] as unknown as shell.ShellArray);
});
it('should return a promise', done => {
it('should return a promise', async () => {
const promise = (bc as any).listShasByDate('input/dir');
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `ls()`.
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
// Do not complete the test (and release the spies) synchronously to avoid running the actual `ls()`.
await promise;
});
it('should `ls()` files with their metadata', done => {
(bc as any).listShasByDate('input/dir').
then(() => expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir')).
then(done);
it('should `ls()` files with their metadata', async () => {
await (bc as any).listShasByDate('input/dir');
expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir');
});
it('should reject if listing files fails', done => {
shellLsSpy.and.callFake(() => Promise.reject('Test'));
(bc as any).listShasByDate('input/dir').catch((err: string) => {
expect(err).toBe('Test');
done();
});
it('should reject if listing files fails', async () => {
shellLsSpy.and.rejectWith('Test');
await expectAsync((bc as any).listShasByDate('input/dir')).toBeRejectedWith('Test');
});
it('should return the filenames', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
it('should return the filenames', async () => {
shellLsSpy.and.resolveTo([
lsResult('foo', 100),
lsResult('bar', 200),
lsResult('baz', 300),
]));
]);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['foo', 'bar', 'baz'])).
then(done);
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'bar', 'baz']);
});
it('should sort by date', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
it('should sort by date', async () => {
shellLsSpy.and.resolveTo([
lsResult('foo', 300),
lsResult('bar', 100),
lsResult('baz', 200),
]));
]);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['bar', 'baz', 'foo'])).
then(done);
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
});
it('should not break with ShellJS\' custom `sort()` method', done => {
it('should not break with ShellJS\' custom `sort()` method', async () => {
const mockArray = [
lsResult('foo', 300),
lsResult('bar', 100),
@ -663,26 +613,21 @@ describe('BuildCreator', () => {
];
mockArray.sort = jasmine.createSpy('sort');
shellLsSpy.and.callFake(() => Promise.resolve(mockArray));
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => {
expect(shas).toEqual(['bar', 'baz', 'foo']);
expect(mockArray.sort).not.toHaveBeenCalled();
}).
then(done);
shellLsSpy.and.resolveTo(mockArray);
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
expect(mockArray.sort).not.toHaveBeenCalled();
});
it('should only include directories', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
it('should only include directories', async () => {
shellLsSpy.and.resolveTo([
lsResult('foo', 100),
lsResult('bar', 200, false),
lsResult('baz', 300),
]));
]);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['foo', 'baz'])).
then(done);
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'baz']);
});
});

View File

@ -32,18 +32,18 @@ describe('BuildRetriever', () => {
};
api = new CircleCiApi('ORG', 'REPO', 'TOKEN');
spyOn(api, 'getBuildInfo').and.callFake(() => Promise.resolve(BUILD_INFO));
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl')
.and.callFake(() => Promise.resolve(BASE_URL + ARTIFACT_PATH));
spyOn(api, 'getBuildInfo').and.resolveTo(BUILD_INFO);
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl').and.resolveTo(BASE_URL + ARTIFACT_PATH);
WRITEFILE_RESULT = undefined;
writeFileSpy = spyOn(fs, 'writeFile').and.callFake(
(_path: string, _buffer: Buffer, callback: (err?: any) => {}) => callback(WRITEFILE_RESULT),
((_path: string, _buffer: Buffer, callback: fs.NoParamCallback) =>
callback(WRITEFILE_RESULT)) as typeof fs.writeFile,
);
EXISTS_RESULT = false;
existsSpy = spyOn(fs, 'exists').and.callFake(
(_path: string, callback: (exists: boolean) => {}) => callback(EXISTS_RESULT),
((_path, callback) => callback(EXISTS_RESULT)) as typeof fs.exists,
);
});
@ -56,6 +56,7 @@ describe('BuildRetriever', () => {
expect(() => new BuildRetriever(api, -1, DOWNLOAD_DIR))
.toThrowError(`Invalid parameter "downloadSizeLimit" should be a number greater than 0.`);
});
it('should fail if the "downloadDir" is missing', () => {
expect(() => new BuildRetriever(api, MAX_DOWNLOAD_SIZE, ''))
.toThrowError(`Missing or empty required parameter 'downloadDir'!`);
@ -72,14 +73,10 @@ describe('BuildRetriever', () => {
});
it('should error if it is not possible to extract the PR number from the branch', async () => {
BUILD_INFO.branch = 'master';
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
try {
BUILD_INFO.branch = 'master';
await retriever.getGithubInfo(12345);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('No PR found in branch field: master');
}
await expectAsync(retriever.getGithubInfo(12345)).toBeRejectedWithError('No PR found in branch field: master');
});
});
@ -110,12 +107,10 @@ describe('BuildRetriever', () => {
it('should fail if the artifact is too large', async () => {
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
retriever = new BuildRetriever(api, 10, DOWNLOAD_DIR);
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.status).toEqual(413);
}
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWith(jasmine.objectContaining({status: 413}));
artifactRequest.done();
});
@ -143,50 +138,40 @@ describe('BuildRetriever', () => {
artifactRequest.done();
});
it('should fail if the CircleCI API fails', async () => {
try {
getBuildArtifactUrlSpy.and.callFake(() => Promise.reject('getBuildArtifactUrl failed'));
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (getBuildArtifactUrl failed)');
}
it('should fail if the CircleCI API fails', async () => {
getBuildArtifactUrlSpy.and.rejectWith('getBuildArtifactUrl failed');
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (getBuildArtifactUrl failed)');
});
it('should fail if the URL fetch errors', async () => {
it('should fail if the URL fetch errors', async () => {
// create a new handler that errors
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).replyWithError('Artifact Request Failed');
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed ' +
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).toBeRejectedWithError(
'CircleCI artifact download failed ' +
'(request to http://test.com/some/path/build.zip failed, reason: Artifact Request Failed)');
}
artifactRequest.done();
});
it('should fail if the URL fetch 404s', async () => {
it('should fail if the URL fetch 404s', async () => {
// create a new handler that errors
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(404, 'No such artifact');
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (Error 404 - Not Found)');
}
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (Error 404 - Not Found)');
artifactRequest.done();
});
it('should fail if file write fails', async () => {
it('should fail if file write fails', async () => {
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
try {
WRITEFILE_RESULT = 'Test Error';
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (Test Error)');
}
WRITEFILE_RESULT = 'Test Error';
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (Test Error)');
artifactRequest.done();
});
});

View File

@ -51,7 +51,10 @@ describe('BuildVerifier', () => {
describe('getSignificantFilesChanged', () => {
it('should return false if none of the fetched files match the given pattern', async () => {
const fetchFilesSpy = spyOn(prs, 'fetchFiles');
fetchFilesSpy.and.callFake(() => Promise.resolve([{filename: 'a/b/c'}, {filename: 'd/e/f'}]));
fetchFilesSpy.and.resolveTo([
{filename: 'a/b/c', sha: 'a1'},
{filename: 'd/e/f', sha: 'b2'},
]);
expect(await bv.getSignificantFilesChanged(777, /^x/)).toEqual(false);
expect(fetchFilesSpy).toHaveBeenCalledWith(777);
@ -78,37 +81,30 @@ describe('BuildVerifier', () => {
user: {login: 'username'},
};
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').
and.callFake(() => Promise.resolve(mockPrInfo));
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').
and.callFake(() => Promise.resolve(true));
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').and.resolveTo(mockPrInfo);
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').and.resolveTo(true);
});
it('should return a promise', done => {
it('should return a promise', async () => {
const promise = bv.getPrIsTrusted(pr);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `GithubTeams#isMemberBySlug()`.
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
// Do not complete the test (and release the spies) synchronously to avoid running the actual
// `GithubTeams#isMemberBySlug()`.
await promise;
});
it('should fetch the corresponding PR', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
done();
});
it('should fetch the corresponding PR', async () => {
await bv.getPrIsTrusted(pr);
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
});
it('should fail if fetching the PR errors', done => {
prsFetchSpy.and.callFake(() => Promise.reject('Test'));
bv.getPrIsTrusted(pr).catch(err => {
expect(err).toBe('Test');
done();
});
it('should fail if fetching the PR errors', async () => {
prsFetchSpy.and.rejectWith('Test');
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
});
@ -117,19 +113,14 @@ describe('BuildVerifier', () => {
beforeEach(() => mockPrInfo.labels.push({name: 'trusted: pr-label'}));
it('should resolve to true', done => {
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(true);
done();
});
it('should resolve to true', async () => {
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
});
it('should not try to verify the author\'s membership status', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
done();
});
it('should not try to verify the author\'s membership status', async () => {
await expectAsync(bv.getPrIsTrusted(pr));
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
});
});
@ -137,40 +128,27 @@ describe('BuildVerifier', () => {
describe('when the PR does not have the "trusted PR" label', () => {
it('should verify the PR author\'s membership in the specified teams', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
done();
});
it('should verify the PR author\'s membership in the specified teams', async () => {
await bv.getPrIsTrusted(pr);
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
});
it('should fail if verifying membership errors', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.reject('Test'));
bv.getPrIsTrusted(pr).catch(err => {
expect(err).toBe('Test');
done();
});
it('should fail if verifying membership errors', async () => {
teamsIsMemberBySlugSpy.and.rejectWith('Test');
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
});
it('should resolve to true if the PR\'s author is a member', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(true));
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(true);
done();
});
it('should resolve to true if the PR\'s author is a member', async () => {
teamsIsMemberBySlugSpy.and.resolveTo(true);
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
});
it('should resolve to false if the PR\'s author is not a member', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(false));
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(false);
done();
});
it('should resolve to false if the PR\'s author is not a member', async () => {
teamsIsMemberBySlugSpy.and.resolveTo(false);
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(false);
});
});

View File

@ -1,11 +0,0 @@
import {PreviewServerError} from '../../lib/preview-server/preview-error';
export const expectToBePreviewServerError = (actual: PreviewServerError, status?: number, message?: string) => {
expect(actual).toEqual(jasmine.any(PreviewServerError));
if (status != null) {
expect(actual.status).toBe(status);
}
if (message != null) {
expect(actual.message).toBe(message);
}
};

View File

@ -0,0 +1,5 @@
declare module jasmine {
interface AsyncMatchers {
toBeRejectedWithPreviewServerError(status: number, message?: string | RegExp): Promise<void>;
}
}

View File

@ -0,0 +1,59 @@
import {PreviewServerError} from '../../lib/preview-server/preview-error';
// Matchers
const toBeRejectedWithPreviewServerError: jasmine.CustomAsyncMatcherFactory = () => {
return {
async compare(actualPromise: Promise<never>, expectedStatus: number, expectedMessage?: string | RegExp) {
if (!(actualPromise instanceof Promise)) {
throw new Error(`Expected '${toBeRejectedWithPreviewServerError.name}()' to be called on a promise.`);
}
try {
await actualPromise;
return {
pass: false,
message: `Expected a promise to be rejected with a '${PreviewServerError.name}', but it was resolved.`,
};
} catch (actualError) {
const actualPrintValue = stringify(actualError);
const expectedPrintValue =
stringify(new PreviewServerError(expectedStatus, expectedMessage && `${expectedMessage}`));
const pass = errorMatches(actualError, expectedStatus, expectedMessage);
const message =
`Expected a promise ${pass ? 'not ' : ''}to be rejected with ${expectedPrintValue}, but is was` +
`${pass ? '' : ` rejected with ${actualPrintValue}`}.`;
return {pass, message};
}
},
};
// Helpers
function errorMatches(actualErr: unknown, expectedStatus: number, expectedMsg?: string | RegExp): boolean {
if (!(actualErr instanceof PreviewServerError)) return false;
if (actualErr.status !== expectedStatus) return false;
return messageMatches(actualErr.message, expectedMsg);
}
function messageMatches(actualMsg: string, expectedMsg?: string | RegExp): boolean {
if (typeof expectedMsg === 'undefined') return true;
if (typeof expectedMsg === 'string') return actualMsg === expectedMsg;
return expectedMsg.test(actualMsg);
}
function stringify(value: unknown): string {
if (value instanceof PreviewServerError) {
return `${PreviewServerError.name}(${value.status}${value.message ? `, ${value.message}` : ''})`;
}
return jasmine.pp(value);
}
};
// Exports
export const customAsyncMatchers: jasmine.CustomAsyncMatcherFactories = {
toBeRejectedWithPreviewServerError,
};

View File

@ -9,8 +9,8 @@ describe('PreviewServerError', () => {
it('should extend Error', () => {
expect(err).toEqual(jasmine.any(PreviewServerError));
expect(err).toEqual(jasmine.any(Error));
expect(err).toBeInstanceOf(PreviewServerError);
expect(err).toBeInstanceOf(Error);
expect(Object.getPrototypeOf(err)).toBe(PreviewServerError.prototype);
});

View File

@ -1,5 +1,4 @@
// Imports
import * as express from 'express';
import * as http from 'http';
import * as supertest from 'supertest';
import {CircleCiApi} from '../../lib/common/circle-ci-api';
@ -134,7 +133,7 @@ describe('PreviewServerFactory', () => {
const buildCreator = jasmine.any(BuildCreator);
expect(usfCreateMiddlewareSpy).toHaveBeenCalledWith(buildRetriever, buildVerifier, buildCreator, defaultConfig);
const middleware: express.Express = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
const middleware = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
expect(httpCreateServerSpy).toHaveBeenCalledWith(middleware);
});
@ -230,7 +229,7 @@ describe('PreviewServerFactory', () => {
expect(prsAddCommentSpy).toHaveBeenCalledTimes(2);
expect(prs).toBe(allCalls[1].object);
expect(prs).toEqual(jasmine.any(GithubPullRequests));
expect(prs).toBeInstanceOf(GithubPullRequests);
expect(prs.repoSlug).toBe('organisation/repo');
});
@ -302,9 +301,8 @@ describe('PreviewServerFactory', () => {
let bvGetSignificantFilesChangedSpy: jasmine.Spy;
beforeEach(() => {
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.returnValue(Promise.resolve(true));
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').
and.returnValue(Promise.resolve(true));
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.resolveTo(true);
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').and.resolveTo(true);
});
@ -331,7 +329,7 @@ describe('PreviewServerFactory', () => {
it('should respond appropriately if the PR did not touch any significant files', async () => {
bvGetSignificantFilesChangedSpy.and.returnValue(Promise.resolve(false));
bvGetSignificantFilesChangedSpy.and.resolveTo(false);
const expectedResponse = {canHavePublicPreview: false, reason: 'No significant files touched.'};
const expectedLog = `PR:${pr} - Cannot have a public preview, because it did not touch any significant files.`;
@ -345,7 +343,7 @@ describe('PreviewServerFactory', () => {
it('should respond appropriately if the PR is not automatically verifiable as "trusted"', async () => {
bvGetPrIsTrustedSpy.and.returnValue(Promise.resolve(false));
bvGetPrIsTrustedSpy.and.resolveTo(false);
const expectedResponse = {canHavePublicPreview: false, reason: 'Not automatically verifiable as "trusted".'};
const expectedLog =
@ -372,7 +370,7 @@ describe('PreviewServerFactory', () => {
it('should respond with error if `getSignificantFilesChanged()` fails', async () => {
bvGetSignificantFilesChangedSpy.and.callFake(() => Promise.reject('getSignificantFilesChanged error'));
bvGetSignificantFilesChangedSpy.and.rejectWith('getSignificantFilesChanged error');
await agent.get(url).expect(500, 'getSignificantFilesChanged error');
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', 'getSignificantFilesChanged error');
@ -380,11 +378,10 @@ describe('PreviewServerFactory', () => {
it('should respond with error if `getPrIsTrusted()` fails', async () => {
const error = new Error('getPrIsTrusted error');
bvGetPrIsTrustedSpy.and.callFake(() => { throw error; });
bvGetPrIsTrustedSpy.and.throwError('getPrIsTrusted error');
await agent.get(url).expect(500, 'getPrIsTrusted error');
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', error);
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', new Error('getPrIsTrusted error'));
});
});
@ -497,7 +494,7 @@ describe('PreviewServerFactory', () => {
// Note it is important to put the `reject` into `and.callFake`;
// If you just `and.returnValue` the rejected promise
// then you get an "unhandled rejection" message in the console.
getGithubInfoSpy.and.callFake(() => Promise.reject('Test Error'));
getGithubInfoSpy.and.rejectWith('Test Error');
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
@ -518,7 +515,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if the artifact fetch request fails', async () => {
downloadBuildArtifactSpy.and.callFake(() => Promise.reject('Test Error'));
downloadBuildArtifactSpy.and.rejectWith('Test Error');
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -527,7 +524,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if verifying the PR fails', async () => {
getPrIsTrustedSpy.and.callFake(() => Promise.reject('Test Error'));
getPrIsTrustedSpy.and.rejectWith('Test Error');
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -536,7 +533,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if creating the preview build fails', async () => {
createBuildSpy.and.callFake(() => Promise.reject('Test Error'));
createBuildSpy.and.rejectWith('Test Error');
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -605,7 +602,7 @@ describe('PreviewServerFactory', () => {
it('should propagate errors from BuildVerifier', async () => {
bvGetPrIsTrustedSpy.and.callFake(() => Promise.reject('Test'));
bvGetPrIsTrustedSpy.and.rejectWith('Test');
await createRequest(+pr).expect(500, 'Test');
@ -615,7 +612,9 @@ describe('PreviewServerFactory', () => {
it('should call \'BuildCreator#updatePrVisibility()\' with the correct arguments', async () => {
bvGetPrIsTrustedSpy.and.callFake((pr2: number) => Promise.resolve(pr2 === 42));
bvGetPrIsTrustedSpy.
withArgs(24).and.resolveTo(false).
withArgs(42).and.resolveTo(true);
await createRequest(24);
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(24, false);
@ -626,7 +625,7 @@ describe('PreviewServerFactory', () => {
it('should propagate errors from BuildCreator', async () => {
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject('Test'));
bcUpdatePrVisibilitySpy.and.rejectWith('Test');
await createRequest(+pr).expect(500, 'Test');
});
@ -634,7 +633,9 @@ describe('PreviewServerFactory', () => {
describe('on success', () => {
it('should respond with 200 (action: undefined)', async () => {
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
const reqs = [4, 2].map(num => createRequest(num).expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);
@ -642,7 +643,9 @@ describe('PreviewServerFactory', () => {
it('should respond with 200 (action: labeled)', async () => {
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
const reqs = [4, 2].map(num => createRequest(num, 'labeled').expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);
@ -650,7 +653,9 @@ describe('PreviewServerFactory', () => {
it('should respond with 200 (action: unlabeled)', async () => {
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
const reqs = [4, 2].map(num => createRequest(num, 'unlabeled').expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);

View File

@ -39,7 +39,7 @@ describe('preview-server/utils', () => {
throwRequestError(505, 'ERROR MESSAGE', request);
} catch (error) {
caught = true;
expect(error).toEqual(jasmine.any(PreviewServerError));
expect(error).toBeInstanceOf(PreviewServerError);
expect(error.status).toEqual(505);
expect(error.message).toEqual(`ERROR MESSAGE in request: POST some.domain.com/path "The request body"`);
}

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,32 @@ exitCode=0
# Helpers
function checkCert {
local certPath=$1
if [[ ! -f "$certPath" ]]; then
echo "Certificate '$certPath' does not exist. Skipping expiration check..."
return
fi
openssl x509 -checkend 0 -in "$certPath" -noout > /dev/null
reportStatus "Certificate '$certPath'"
if [[ $? -ne 0 ]]; then
echo " [WARN]"
echo " If you did not provide the certificate explicitly, try running the"
echo " 'docker build' command again with the '--no-cache' option to generate"
echo " a new self-signed certificate."
fi
}
function reportStatus {
local lastExitCode=$?
echo "$1: $([[ $lastExitCode -eq 0 ]] && echo OK || echo NOT OK)"
[[ $lastExitCode -eq 0 ]] || exitCode=1
return $lastExitCode
}
@ -28,6 +50,16 @@ for s in ${services[@]}; do
done
# Check SSL/TLS certificates expiration
certs=(
"$AIO_LOCALCERTS_DIR/$AIO_DOMAIN_NAME.crt"
"$TEST_AIO_LOCALCERTS_DIR/$TEST_AIO_DOMAIN_NAME.crt"
)
for c in ${certs[@]}; do
checkCert $c
done
# Check servers
origins=(
http://$AIO_PREVIEW_SERVER_HOSTNAME:$AIO_PREVIEW_SERVER_PORT

View File

@ -3,7 +3,7 @@
## Create `aio-builds` persistent disk (if not already exists)
- Follow instructions [here](https://cloud.google.com/compute/docs/disks/add-persistent-disk#create_disk).
- `sudo mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
- `sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
## Mount disk
@ -14,7 +14,7 @@
## Mount disk on boot
- Run:
```
```sh
echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
/mnt/disks/aio-builds ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab
/mnt/disks/aio-builds ext4 defaults,discard,nofail 0 2 | sudo tee -a /etc/fstab
```

View File

@ -1,10 +1,12 @@
# VM setup - Create docker image
## Install node and yarn
- Install [nvm](https://github.com/creationix/nvm#installation).
- Install node.js: `nvm install 8`
- Install yarn: `npm -g install yarn`
## Install git, Node.js and yarn
- `sudo apt-get update`
- `sudo apt-get install -y git`
- Install [nvm](https://github.com/nvm-sh/nvm#installing-and-updating).
- Install Node.js: `nvm install 12`
- Install yarn: `npm install --global yarn`
## Checkout repository
@ -26,7 +28,7 @@ The following commands would create a docker image from GitHub repo `foo/bar` to
- `git clone https://github.com/foo/bar.git foobar`
- Run:
```
```sh
./foobar/aio-builds-setup/scripts/create-image.sh foobar-builds \
--build-arg AIO_REPO_SLUG=foo/bar \
--build-arg AIO_DOMAIN_NAME=foobar-builds.io \

View File

@ -3,24 +3,17 @@
## Install docker
_Debian (jessie):_
- `sudo apt-get update`
- `sudo apt-get install -y apt-transport-https ca-certificates curl git software-properties-common`
- `curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -`
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ debian-$(lsb_release -cs) main"`
- `sudo apt-get update`
- `sudo apt-get -y install docker-engine`
Official installation instructions: https://docs.docker.com/engine/install
Example:
_Ubuntu (16.04):_
_Debian (buster):_
- `sudo apt-get update`
- `sudo apt-get install -y curl git linux-image-extra-$(uname -r) linux-image-extra-virtual`
- `sudo apt-get install -y apt-transport-https ca-certificates`
- `curl -fsSL https://yum.dockerproject.org/gpg | sudo apt-key add -`
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ ubuntu-$(lsb_release -cs) main"`
- `sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common`
- `curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -`
- `sudo apt-key fingerprint 0EBFCD88`
- `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"`
- `sudo apt-get update`
- `sudo apt-get -y install docker-engine`
- `sudo apt-get -y install docker-ce docker-ce-cli containerd.io`
## Start the docker

View File

@ -15,9 +15,9 @@ The script assumes that the preview server source code is in the repository's
`aio/aio-builds-setup/` directory and expects the following inputs:
- **$1**: `HOST_REPO_DIR`
- **$2**: `HOST_LOCALCERTS_DIR`
- **$3**: `HOST_SECRETS_DIR`
- **$4**: `HOST_BUILDS_DIR`
- **$2**: `HOST_SECRETS_DIR`
- **$3**: `HOST_BUILDS_DIR`
- **$4**: `HOST_LOCALCERTS_DIR`
- **$5**: `HOST_LOGS_DIR`
See [here](vm-setup--create-host-dirs-and-files.md) for more info on what each input directory is
@ -31,22 +31,22 @@ used for.
## Run the script manually
You may choose to manually run the script, when necessary. Example:
```
```sh
update-preview-server.sh \
/path/to/repo \
/path/to/localcerts \
/path/to/secrets \
/path/to/builds \
/path/to/localcerts \
/path/to/logs
```
## Run the script automatically
You may choose to automatically trigger the script, e.g. using a cronjob. For example, the following
cronjob entry would run the script every hour and update the preview server (assuming the user has
the necessary permissions):
cronjob entry would run the script every 30 minutes, update the preview server (if necessary) and
log its output to `update-preview-server.log` (assuming the user has the necessary permissions):
```
# Periodically check for changes and update the preview server (if necessary)
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/localcerts /path/to/secrets /path/to/builds /path/to/logs
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/secrets /path/to/builds /path/to/localcerts /path/to/logs >> /path/to/update-preview-server.log 2>&1
```

View File

@ -7,9 +7,9 @@ echo -e "\n\n[`date`] - Updating the preview server..."
# Input
readonly HOST_REPO_DIR=$1
readonly HOST_LOCALCERTS_DIR=$2
readonly HOST_SECRETS_DIR=$3
readonly HOST_BUILDS_DIR=$4
readonly HOST_SECRETS_DIR=$2
readonly HOST_BUILDS_DIR=$3
readonly HOST_LOCALCERTS_DIR=$4
readonly HOST_LOGS_DIR=$5
# Constants
@ -60,9 +60,9 @@ readonly CONTAINER_NAME=aio
--publish 80:80 \
--publish 443:443 \
--restart unless-stopped \
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
--volume $HOST_SECRETS_DIR:/aio-secrets:ro \
--volume $HOST_BUILDS_DIR:/var/www/aio-builds \
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
--volume $HOST_LOGS_DIR:/var/log/aio \
"$LATEST_IMAGE_NAME"

View File

@ -82,9 +82,6 @@ upgrade-phonecat-2-hybrid/aot/**/*
# styleguide
!styleguide/src/systemjs.custom.js
# universal
!universal/webpack.server.config.js
# stackblitz
*stackblitz.no-link.html
@ -97,4 +94,4 @@ upgrade-phonecat-3-final/rollup-config.js
!upgrade-phonecat-*/**/karma-test-shim.js
# schematics
!schematics-for-libraries/projects/my-lib/package.json
!schematics-for-libraries/projects/my-lib/package.json

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Accessibility Example</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>AttributeBinding</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

View File

@ -1,32 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
});

View File

@ -1,8 +0,0 @@
import { ItemDirective } from './item.directive';
describe('ItemDirective', () => {
it('should create an instance', () => {
const directive = new ItemDirective();
expect(directive).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>NgmoduleDemo</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemDetailComponent } from './item-detail.component';
describe('ItemDetailComponent', () => {
let component: ItemDetailComponent;
let fixture: ComponentFixture<ItemDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>BuiltInDirectives</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,16 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Built-in Template Functions Example</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,5 +1,5 @@
{
"e2e": [
"tests": [
{
"cmd": "yarn",
"args": [

View File

@ -1,13 +0,0 @@
{
"e2e": [
{
"cmd": "yarn",
"args": [
"e2e",
"--protractor-config=e2e/protractor-puppeteer.conf.js",
"--no-webdriver-update",
"--port={PORT}"
]
}
]
}

View File

@ -39,7 +39,7 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
`]
})
export class PopupComponent {
private state: 'opened' | 'closed' = 'closed';
state: 'opened' | 'closed' = 'closed';
@Input()
set message(message: string) {

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'Featured product:'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('Featured product:');
}));
it('should render title in a p tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('p').textContent).toContain('Featured product:');
}));
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemDetailComponent } from './item-detail.component';
describe('ItemDetailComponent', () => {
let component: ItemDetailComponent;
let fixture: ComponentFixture<ItemDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>EventBinding</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,4 +0,0 @@
{
"build": "build:cli",
"run": "serve:cli"
}

View File

@ -1,32 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CustomerDashboardComponent } from './customer-dashboard.component';
describe('CustomerDashboardComponent', () => {
let component: CustomerDashboardComponent;
let fixture: ComponentFixture<CustomerDashboardComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CustomerDashboardComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CustomerDashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Feature Modules</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -0,0 +1,6 @@
{
"tests": [
{"cmd": "yarn", "args": ["test", "--browsers=ChromeHeadless", "--no-watch"]},
{"cmd": "yarn", "args": ["e2e", "--prod", "--protractor-config=e2e/protractor-puppeteer.conf.js", "--no-webdriver-update", "--port={PORT}"]}
]
}

View File

@ -16,12 +16,12 @@ describe('AppComponent', () => {
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
const app = fixture.componentInstance;
expect(app).toBeTruthy();
}));
it('should render title in a h1 tag', async(() => {
it('should render title', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();

View File

@ -1,13 +0,0 @@
import { ReactiveModule } from './reactive.module';
describe('ReactiveModule', () => {
let reactiveModule: ReactiveModule;
beforeEach(() => {
reactiveModule = new ReactiveModule();
});
it('should create an instance', () => {
expect(reactiveModule).toBeTruthy();
});
});

View File

@ -1,13 +0,0 @@
import { TemplateModule } from './template.module';
describe('TemplateModule', () => {
let templateModule: TemplateModule;
beforeEach(() => {
templateModule = new TemplateModule();
});
it('should create an instance', () => {
expect(templateModule).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Forms Overview</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,3 +1,7 @@
{
"projectType": "testing"
"projectType": "testing",
"tests": [
{"cmd": "yarn", "args": ["test", "--browsers=ChromeHeadless", "--no-watch"]},
{"cmd": "yarn", "args": ["e2e", "--prod", "--protractor-config=e2e/protractor-puppeteer.conf.js", "--no-webdriver-update", "--port={PORT}"]}
]
}

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>HttpClient Demo</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,6 +1,6 @@
{
"projectType": "i18n",
"e2e": [
"tests": [
{
"cmd": "yarn",
"args": [

View File

@ -1,11 +1,9 @@
{
"files":[
"files": [
"!dist/",
"!**/*.d.ts",
"!src/**/*.js",
"!doc-files/**/*",
"**/*.xlf"
],
"removeSystemJsConfig": true,
"type": "i18n"
]
}

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AliasingComponent } from './aliasing.component';
describe('AliasingComponent', () => {
let component: AliasingComponent;
let fixture: ComponentFixture<AliasingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AliasingComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AliasingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InTheMetadataComponent } from './in-the-metadata.component';
describe('InTheMetadataComponent', () => {
let component: InTheMetadataComponent;
let fixture: ComponentFixture<InTheMetadataComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InTheMetadataComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(InTheMetadataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InputOutputComponent } from './input-output.component';
describe('InputOutputComponent', () => {
let component: InputOutputComponent;
let fixture: ComponentFixture<InputOutputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InputOutputComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(InputOutputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemDetailComponent } from './item-detail.component';
describe('ItemDetailComponent', () => {
let component: ItemDetailComponent;
let fixture: ComponentFixture<ItemDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemOutputComponent } from './item-output.component';
describe('ItemOutputComponent', () => {
let component: ItemOutputComponent;
let fixture: ComponentFixture<ItemOutputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemOutputComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemOutputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Inputs and Outputs</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -30,7 +30,7 @@ describe('Interpolation e2e tests', () => {
let pottedPlant = element.all(by.css('img')).get(0);
let lamp = element.all(by.css('img')).get(1);
expect(pottedPlant.getAttribute('src')).toContain('pottedPlant');
expect(pottedPlant.getAttribute('src')).toContain('potted-plant');
expect(pottedPlant.isDisplayed()).toBe(true);
expect(lamp.getAttribute('src')).toContain('lamp');

View File

@ -1,16 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});

View File

@ -12,7 +12,7 @@ export class AppComponent {
currentCustomer = 'Maria';
title = 'Featured product:';
itemImageUrl = '../assets/pottedPlant.png';
itemImageUrl = '../assets/potted-plant.png';
recommended = 'You might also like:';
itemImageUrl2 = '../assets/lamp.png';

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Interpolation</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -1,4 +0,0 @@
{
"build": "build:cli",
"run": "serve:cli"
}

View File

@ -1,36 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'customer-app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('customer-app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('customer-app');
}));
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CustomersComponent } from './customers.component';
describe('CustomerListComponent', () => {
let component: CustomersComponent;
let fixture: ComponentFixture<CustomersComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CustomersComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CustomersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { OrdersComponent } from './orders.component';
describe('OrderListComponent', () => {
let component: OrdersComponent;
let fixture: ComponentFixture<OrdersComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ OrdersComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(OrdersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -4,7 +4,6 @@
<meta charset="utf-8">
<title>Lazy loading feature modules</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

View File

@ -3,6 +3,7 @@ import {
AfterContentInit,
AfterViewChecked,
AfterViewInit,
Directive,
DoCheck,
OnChanges,
OnDestroy,
@ -15,7 +16,8 @@ import { LoggerService } from './logger.service';
let nextId = 1;
// #docregion ngOnInit
export class PeekABoo implements OnInit {
@Directive()
export class PeekABooDirective implements OnInit {
constructor(private logger: LoggerService) { }
// implement OnInit's `ngOnInit` method
@ -34,7 +36,7 @@ export class PeekABoo implements OnInit {
})
// Don't HAVE to mention the Lifecycle Hook interfaces
// unless we want typing and tool support.
export class PeekABooComponent extends PeekABoo implements
export class PeekABooComponent extends PeekABooDirective implements
OnChanges, OnInit, DoCheck,
AfterContentInit, AfterContentChecked,
AfterViewInit, AfterViewChecked,

View File

@ -1,41 +0,0 @@
// #docplaster
// #docregion
/* Angular Imports */
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
/* App Imports */
// #enddocregion
import { AppComponent } from './app.component.3';
/*
// #docregion
import { AppComponent } from './app.component';
// #enddocregion
*/
// #docregion
import { HighlightDirective } from './highlight.directive.1';
import { TitleComponent } from './title.component.1';
import { UserService } from './user.service';
/* Routing Module */
// #enddocregion
import { AppRoutingModule } from './app-routing.module.3';
/*
// #docregion
import { AppRoutingModule } from './app-routing.module';
// #enddocregion
*/
// #docregion
@NgModule({
// #docregion imports
imports: [
BrowserModule,
AppRoutingModule
],
// #enddocregion imports
providers: [ UserService ],
declarations: [ AppComponent, HighlightDirective, TitleComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

View File

@ -1,15 +0,0 @@
// #docplaster
// #docregion
import { Directive, ElementRef } from '@angular/core';
// Highlight the host element in gold
@Directive({ selector: '[highlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'gold';
// #enddocregion
console.log(`* AppRoot highlight called for ${el.nativeElement.tagName}`);
// #docregion
}
}
// #enddocregion

View File

@ -1,10 +0,0 @@
<!-- #docregion -->
<!-- #docregion v1 -->
<h1 highlight>{{title}}</h1>
<!-- #enddocregion v1 -->
<!-- #docregion ngIf -->
<p *ngIf="user">
<i>Welcome, {{user}}</i>
<p>
<!-- #enddocregion ngIf -->

View File

@ -1,23 +0,0 @@
// #docplaster
// #docregion
// #docregion v1
import { Component } from '@angular/core';
// #enddocregion v1
import { UserService } from './user.service';
// #docregion v1
@Component({
selector: 'app-title',
templateUrl: './title.component.1.html'
})
export class TitleComponent {
title = 'Angular Modules';
// #enddocregion v1
user = '';
constructor(userService: UserService) {
this.user = userService.userName;
}
// #docregion v1
}
// #enddocregion v1

View File

@ -1,4 +0,0 @@
{
"build": "build:cli",
"run": "serve:cli"
}

View File

@ -1,32 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
});

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactComponent } from './contact.component';
describe('ContactComponent', () => {
let component: ContactComponent;
let fixture: ComponentFixture<ContactComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContactComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContactComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

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