Compare commits

...

154 Commits

Author SHA1 Message Date
Alex Rickabaugh b0854e2ec6 release: cut the v12.1.3 release (#42914)
PR Close #42914
2021-07-21 14:32:51 -07:00
George Kalpakas 29f50976db fix(docs-infra): fix keyword color in CLI pages code blocks (#42889)
Previously, names of CLI commands that also happened to be keywords were
shown in black color in the code block demonstrating the command's
usage. This worked fine when in light mode (where the code block
background is white) but not in the recently introduced dark mode (where
the code block background is dark gray).

This commit fixes this by ensuring the `.kwd` token color is inherited
from its parent (which has an appropriate color for the current theme).
Previously, the `.kwd` token was reset to its initial value (which is
`black` regardless of the theme).

**Before:** ![CLI pages keyword before][1]
**After:** ![cli-pages-keyword after][2]

[1]: https://user-images.githubusercontent.com/8604205/126073803-af317f0c-d04f-4c3a-9a83-e92541d7dd5a.png
[2]: https://user-images.githubusercontent.com/8604205/126073806-1d57e3ed-90b1-4735-ae2a-d0a39862bb95.png

PR Close #42889
2021-07-20 11:56:34 -07:00
JoostK d207ea06d1 fix(compiler-cli): use correct module import for types behind a forwardRef (#42887)
The static interpreter assumed that a foreign function expression would
have to be imported from the absolute module specifier that was used for
the foreign function itself. This assumption does not hold for the
`forwardRef` foreign function resolver, as that extracts the resolved
expression from the function's argument, which is not behind the
absolute module import of the `forwardRef` function.

The prior behavior has worked for the typical usage of `forwardRef`,
when it is contained within the same source file as where the static
evaluation started. In that case, the resulting reference would
incorrectly have an absolute module guess of `@angular/core`, but the
local identifier emit strategy was capable of emitting the reference
without generating an import using the absolute module guess.

In the scenario where the static interpreter would first have to follow
a reference to a different source that contained the `forwardRef` would
the compilation fail. In that case, there is no local identifier
available such that the absolute module emitter would try to locate the
imported symbol from `@angular/core`. which fails as the symbol is not
exported from there.

This commit fixes the issue by checking whether a foreign expression
occurs in the same source file as the call expression. If it does, then
the absolute module specifier that was used to resolve the call
expression is ignored.

Fixes #42865

PR Close #42887
2021-07-20 11:56:07 -07:00
Joey Perrott 18e2dba7ae fix(dev-infra): use the version from package.json rather than tags (#42872)
Use the version value from the primary package.json file rather than
checking the branch for the latest semver tag.  This allows for us
to explictly create changelogs from the previous version to the new
version.

PR Close #42872
2021-07-20 11:30:34 -07:00
Joey Perrott e31eaf8595 feat(dev-infra): update package version verification to allow for experimental version (#42898)
The angular-cli repo publishes experimental versioned packages in addition to standard
versioned packages.  Both experimental and standard verions, based on the expected new
version provided are treated as valid and correct.

PR Close #42898
2021-07-20 11:30:01 -07:00
dario-piotrowicz e6b7472d11 build(docs-infra): improve @usageNotes message (#42888)
improve the @usageNotes message by adding the word "is"
(outcome: "Further information is available in...", compared to
"Further information available in...")

PR Close #42888
2021-07-19 17:37:57 -07:00
JoostK a6db152c78 fix(core): use correct injector when resolving DI tokens from within a directive provider factory (#42886)
When a directive provides a DI token using a factory function and
interacting with a standalone injector from within that factory, the
standalone injector should not have access to either the directive
injector nor the NgModule injector; only the standalone injector should
be used.

This commit ensures that a standalone injector never reaches into the
directive-level injection context while resolving DI tokens.

Fixes #42651

PR Close #42886
2021-07-19 17:36:30 -07:00
George Kalpakas 778edfc63c fix(docs-infra): prevent main content from overlapping with ToC (#42884)
Previously, if there was more content than what would horizontally fit
in the main content area, it would overflow to the right and overlap
with the Table of Contents (ToC).
This was accidentally introduced in #42787.

This commit fixes it by ensuring that the main content area will not
overlap with ToC and the necessary space for the ToC will be reserved
using `margin` (instead of `padding`, which contributes to the element's
size).

Fixes #42867

PR Close #42884
2021-07-19 17:35:36 -07:00
George Kalpakas 89893972c8 fix(docs-infra): correctly handle reported errors (#42883)
Error-handling in AIO happens mainly in two places:
1. For errors happening inside the app we have a custom `ErrorHandler`
   implementation, `ReportingErrorHandler`. `ReportingErrorHandler`
   passes errors to the default `ErrorHandler` (for them to be logged to
   the console) and also forwards them to `window.onerror()`.
2. Errors happening outside the app and errors forwarded by
   `ReportingErrorHandler` are handled by `window.onerror()`, which in
   turn reports them to Google analytics.

Previously, we were making some assumptions (which turned out to be
incorrect based on the info captured in Google analytics - see #28106):
- `ReportingErrorHandler` assumed that the errors passed to its
  `handleError()` method would be either strings or `Error` instances.
  _Apparently, other values (such as `null` or `undefined`) may also be
  passed._
- `window.onerror()` assumed that if an `Error` instance was passed in,
  it would always have a stacktrace (i.e. its `stack` property would be
  defined).
  _This is not necessarily true, although it is not clear (based on the
  logs) whether reported errors of this type are caused by `Error`
  instance with no stacktrace or by non-string error objects which are
  incorrectly treated as `Error` instances.

This commit ensures that all types of error arguments can be handled
correctly, including `Error` instances with no stacktrace and other
types of objects or primitives.

NOTE:
PR #42881 is related as it fixes handling `null` and `undefined`
arguments in the default `ErrorHandler`.

Fixes #28106

PR Close #42883
2021-07-19 17:35:03 -07:00
Paul Gschwendtner aeff926381 feat(dev-infra): add option to setup global types in API golden test (#42876)
Previously we disabled automatic type-resolution for the API
extractor because in non-sandbox environments this resulted in
different API reports. There are cases where global types are
still needed for analysis of an entry-point. To support this,
we add a new property called `types` which allows for explicit
type targets being specified.

Note that we do not want to determine types from the `data`
runfiles because API extractor itself also brings in types
which should not always be part of the API report analysis.

PR Close #42876
2021-07-19 17:33:20 -07:00
Paul Gschwendtner 24cc1441f5 ci: remove RBE workaround from components-repo-unit-tests job (#42875)
In the past when we had issues with our RBE instance, we wanted
to get CI green as soon as possible, and couldn't wait on the
components repo to land their RBE instance fix. We manually
fixed the RBE instance name using a CI step using `sed`.

This is no longer needed if we update to the most recent
state of the components repository.

PR Close #42875
2021-07-19 17:32:44 -07:00
Paul Gschwendtner 6eea132952 build: remove unnecessary husky gitignore file (#42870)
We recently updated to Husky v7 through Renovate, but
as of Husky v7, a `.gitignore` file is no longer needed.

This commit removes the file.

PR Close #42870
2021-07-19 17:31:55 -07:00
Paul Gschwendtner a47ea85c5e ci: exempt bazel scope from merge tool target label checks (#42869)
Currently, changes with the `bazel` scope are guarded by the
merge tool target label checks. i.e. feature commits with
the `bazel` scope cannot land in the patch branch. This is
expected for all public packages, but given the `bazel`
package being used internal-only, it should be possible
to land these in a patch branch. Especially since we want
tooling to be in sync between version branches as much
as possible.

PR Close #42869
2021-07-19 17:29:02 -07:00
Joey Perrott 9ee4441c55 fix(dev-infra): prevent verbose messaging of git checkout and commit for release (#42871)
Prevent logging verbose messages to the output for commit and checkout during
the release process.

PR Close #42871
2021-07-19 17:15:55 -07:00
Joey Perrott e7b3b34e62 fix(dev-infra): perform actual npm login verification for wombot proxy (#42871)
Previously the wombot proxy was not able to be queried for login state, now
that it is able to be checked via `npm whoami` a specific alternate flow
is no longer needed.

PR Close #42871
2021-07-19 17:15:54 -07:00
Joey Perrott ca2165e8df refactor(dev-infra): provide entire pull request object to waitForPullRequestToBeMerged (#42871)
`waitForPullRequestToBeMerged` should get the entire `PullRequest` object rather than
just the id to allow it to have more information/context for logging and messaging.

PR Close #42871
2021-07-19 17:15:54 -07:00
Joey Perrott d845643ba1 fix(dev-infra): don't pollute standard out during commit message hooks (#42871)
When a commit message is not restored, there is not need to log this to
stdout.  It is a better experience to silently succeed.

PR Close #42871
2021-07-19 17:15:54 -07:00
dario-piotrowicz 8f109da1c8 refactor(animations): remove unused animation trigger imports (#42763)
in the animation_trigger.ts file there are unused imports
remove them to clean up the file

PR Close #42763
2021-07-19 17:13:46 -07:00
dario-piotrowicz 6de37b8f0a refactor(animations): remove publicApi annotations from triggers (#42763)
the buildTrigger function and AnimationTrigger class are annotated
as publicApi which seems wrong and makes changes to the two
problematic, so they are being removed here

see: https://github.com/angular/angular/pull/42763/files#r671481902

PR Close #42763
2021-07-19 17:13:46 -07:00
dario-piotrowicz 3cddc3d6bc fix(animations): normalize final styles in buildStyles (#42763)
the final styles created in buildStyles lack normalization, meaning that pixel values remain as numbers (without "px") and so such properties fail to be correctly set/applied

Example: "width: 300" is applies as "width": "300" (and thus ignored) instead of the correct "width": "300px"

PR Close #42763
2021-07-19 17:13:46 -07:00
dario-piotrowicz 0dfb4e8c8b refactor(animations): fix typo in transition animations spec file (#42763)
fix the typo "mean't" in the transition_animation_engine spec file
to "meant" (the typo is simply in a code comment so the change
does not have any impact)

PR Close #42763
2021-07-19 17:13:46 -07:00
Joey Perrott 97fa1cf544 build: add configuration for caretaker handoff (#42859)
Add configuration information about groups for caretaker handoff assistant.

PR Close #42859
2021-07-15 13:34:59 -07:00
Joey Perrott 9d4b580c12 feat(dev-infra): create caretaker handoff assistant to update github team membership (#42859)
Create a handoff assistant, currently only assists in updating github team membership
for caretaking team.

PR Close #42859
2021-07-15 13:34:59 -07:00
Minko Gechev 0ef8b01804 docs: remove reference to an obsolete design doc (#42842)
The type checking design document is no longer relevant. This PR
removes the reference to it. Close #42424.

PR Close #42842
2021-07-15 13:24:58 -07:00
David Shevitz c06cbb2ec4 docs: remove references to future in topic (#42841)
Fixes #25704

PR Close #42841
2021-07-15 13:23:28 -07:00
dario-piotrowicz 688b1c5b53 docs(docs-infra): remove unnecessary "Podcast" from happy-angular podcast's title (#42756)
PR Close #42756
2021-07-15 13:22:04 -07:00
dario-piotrowicz 12ad314d5a docs(docs-infra): add the angular show to the podcast resources (#42756)
PR Close #42756
2021-07-15 13:22:04 -07:00
dario-piotrowicz 8b9aea9503 docs(docs-infra): podcast keys cleanup in resources.json (#42756)
PR Close #42756
2021-07-15 13:22:04 -07:00
dario-piotrowicz 1d9d74a2d1 docs(docs-infra): remove deep dive from podcast resources (#42756)
PR Close #42756
2021-07-15 13:22:03 -07:00
JoostK d4567b28f7 refactor(core): expand error logging when the JIT compiler is not available (#42693)
If a decorator or partial declaration has not been AOT compiled, then
the compiler is needed at runtime to be able to JIT compile the code.
However, it may occur that the compiler is not available, if it has not
been loaded into the application. The error that was reported in this
case did not provide insight into which class requested compilation, nor
did it differentiate between decorators vs. partial declarations.

This commit expands the error logging to provide better insight into the
class that initiated JIT compilation and offers a specialized error
message for partial declarations. This should help a developer better
understand why the error occurs and what can be done to resolve it.

Closes #40609

PR Close #42693
2021-07-15 13:19:05 -07:00
JoostK e6d520f3d9 perf(compiler-cli): optimize cycle detection using a persistent cache (#41271)
For the compilation of a component, the compiler verifies that the
imports it needs to generate to reference the used directives and pipes
would not create an import cycle in the program. This requires visiting
the transitive import graphs of all directive/pipe usage in search of
the component file. The observation can be made that all directive/pipe
usages can leverage the exploration work in search of the component
file, thereby allowing sub-graphs of the import graph to be only visited
once instead of repeatedly per usage. Additionally, the transitive
imports of a file are no longer collected into a set to reduce memory
pressure.

PR Close #41271
2021-07-15 13:13:49 -07:00
Krzysztof Kotowicz e6f01d777d revert: docs: remove references to Trusted Types due to incompatibility with Webpack 5 (#42796)
Re-add reference to Trusted Types since the issue #41754 is resolved in 12.1.1.

This reverts commit 7254fbc2baa1455e3b24400597342843df3017f2.

PR Close #42796
2021-07-14 11:14:08 -07:00
Alan Agius fa3e7f87e7 docs: remove End-to-end test files structure (#42844)
Since version 12, the Angular CLI no longer generates end-to-end tests.

PR Close #42844
2021-07-14 11:12:42 -07:00
David Shevitz 8d184f9a31 docs: update incorrect bullet text (#42839)
Fixes #42286

PR Close #42839
2021-07-14 11:11:56 -07:00
Andrew Kushnir 2a61728137 release: cut the v12.1.2 release (#42856) 2021-07-14 10:47:57 -07:00
JoostK 63013546e1 fix(core): associate the NgModule scope for an overridden component (#42817)
When using `TestBed.overrideComponent`, the overridden component would
incorrectly lose access to its NgModule's declaration scope if the
NgModule had been imported into the testing NgModule as a
`ModuleWithProviders`, e.g. using a `forRoot` call.

The issue occurred as the `TestBed` compiler did not consider NgModules
that had been imported as a `ModuleWithProviders` when associating
NgModules with component overrides. This caused the overridden component
to be compiled standalone, meaning that it does not have access to
its NgModule's declarations. This commit extends the logic for
traversing the NgModule graph to also consider `ModuleWithProviders`
imports.

Fixes #42734

PR Close #42817
2021-07-13 15:59:28 -07:00
JoostK 9ebd41e39c fix(core): allow proper type inference when ngFor is used with a trackBy function (#42692)
In #41995 the type of `TrackByFunction` was changed such that the
declaration of a `trackBy` function did not cause the item type to be
widened to the `trackBy`'s item type, which may be a supertype of the
iterated type. This has introduced situations where the template type
checker is now reporting errors for cases where a `trackBy` function is
no longer assignable to `TrackByFunction`.

This commit fixes the error by also including the item type `T` in
addition to the constrained type parameter `U`, allowing TypeScript to
infer an appropriate `T`.

Fixes #42609

PR Close #42692
2021-07-13 14:08:06 -07:00
David Shevitz 34b2669d3a docs: update routing-overview topic with link to custom route matches tutorial (#42837)
PR Close #42837
2021-07-13 14:07:16 -07:00
Meir Blumenfeld d654c7933a fix(common): re-sort output of KeyValuePipe when compareFn changes (#42821)
Previously, if only the `compareFn` changed but the data itself did not, then
the `KeyValuePipe` did not re-sort the output.

Fixes #42819

PR Close #42821
2021-07-13 11:33:21 -07:00
Mark Goho b101ad0d98 docs: clarify voting phase for feature requests (#42663)
PR Close #42663
2021-07-12 15:25:46 -07:00
Andrew Kushnir 75a11d9ac8 Revert "refactor(dev-infra): add spawnSync to child process utils, normalize naming of child-process utils (#42394)" (#42829)
This reverts commit 08444c6679.

PR Close #42829
2021-07-12 15:24:55 -07:00
Andrew Kushnir 2cdf074034 Revert "refactor(dev-infra): remove usages and dependency on shelljs (#42394)" (#42829)
This reverts commit f0d857eff8.

PR Close #42829
2021-07-12 15:24:55 -07:00
Kristiyan Kostadinov 2566cbb48c fix(compiler): add mappings for all HTML entities (#42818)
Angular inserts text either through text nodes (`document.createTextNode`) or using `textContent`, but the drawback of doing so is that HTML entities won't be decoded. In order to work around it, the compiler has some logic that maps the entities to their unicode representation which can safely be inserted. The problem is that our current mapping is arbitrarily limited which means that some entities will be mapped while others will throw an error, even though they're valid.

These changes expand the list to cover all entities that are supported by the HTML spec.

Fixes #41186.

PR Close #42818
2021-07-12 14:41:21 -07:00
Joey Perrott afeab76497 refactor(dev-infra): remove usages and dependency on shelljs (#42394)
Remove usages of shelljs and instead use spawn/spawnSync.

PR Close #42394
2021-07-12 14:39:08 -07:00
Joey Perrott bfb738c3c3 refactor(dev-infra): add spawnSync to child process utils, normalize naming of child-process utils (#42394)
Create a `spawnSync` command for common usage, additionally update naming to use `spawn` instead of
`spawnWithDebugOutput`

PR Close #42394
2021-07-12 14:39:08 -07:00
Paul Gschwendtner eeef3e7479 fix(dev-infra): transitive targets cannot be resolved by API extractor (#42828)
For API golden tests not running against a NPM package, we extract
all transitive declarations of the specified `data` targets. This is
necessary because API extractor needs to resolve other targets that have
been linked by the Bazel NodeJS rules. The linker by default only
provides access to JavaScript sources, but the API extractor is
specifically concerned with type definitions that we need to manually
extract.

PR Close #42828
2021-07-12 14:38:05 -07:00
Paul Gschwendtner c2e5d76674 fix(dev-infra): do not include all types in api golden test (#42828)
The API golden test tool should not include all types
from the `node_modules/`. This results in unnecessary
type resolution when the API golden tool is run outside
of sandbox (i.e. on windows or with `bazel run` for accept).

PR Close #42828
2021-07-12 14:38:05 -07:00
Paul Gschwendtner d249665bd2 feat(dev-infra): better caching for browser archive contents (#42814)
Adds better caching for browser archives and their extraction.
This is done because the archives are currently extracted as a build
action and these are actions are invalidated frequently, causing
flakiness on the CI and slow-down in local development.

Here is an example flaky error on the CI (that surfaces often
with RBE execution):

```
ERROR:
/home/circleci/.cache/bazel/_bazel_circleci/9ce5c2144ecf75d11717c0aa41e45a8d/external/npm/@angular/dev-infra-private/bazel/browsers/chromium/BUILD.bazel:22:17:
Extracting ../org_chromium_chromium_amd64/file/chrome-linux.zip failed:
(Exit 34): extract.sh failed: error executing command
external/io_bazel_rules_webtesting/web/internal/extract.sh
external/org_chromium_chromium_amd64/file/chrome-linux.zip ...
(remaining 2 argument(s) skipped). Note: Remote connection/protocol
failed with: execution failed
```

We fix this by introducing a new rule that downloads a browser
archive and unpacks it directly into a Bazel repository. Before
this change, the archive would just be downloaded but extracted
later as part of a build action. This is unnecessary and results
in less efficient caching as build actions are invalidated more
often, especially if developers run `bazel clean` in between.

The root cause on why the extraction often fails in RBE containers
is unclear. It's unclear why the extacted archive is not cached
properly as part of a build action (most likely some hermeticity
issue within `rules_webtesting`, but it seems more Bazel-idiomatic
to unpack the archives as part of the repository anyway, and this solves
the flakiness issue.

PR Close #42814
2021-07-12 14:37:10 -07:00
Pete Bacon Darwin 4f8a7280c1 docs: move start tutorial alert for clarity (#42764)
The alert was placed in the middle of a set of steps, which
was causing some confusion. This has been moved to the
above the steps in the section and slightly reworded to
make it clearer.

Fixes #42752

PR Close #42764
2021-07-12 13:20:13 -07:00
Paul Gschwendtner 04472d23c2 refactor: add override keyword to members implementing abstract declarations (#42512)
In combination with the TS `noImplicitOverride` compatibility changes,
we also want to follow the best-practice of adding `override` to
members which are implemented as part of abstract classes. This
commit fixes all instances which will be flagged as part of the
custom `no-implicit-override-abstract` TSLint rule.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner 8dbae89ed4 feat(dev-infra): add lint rule to enforce no-implicit-override abstract members (#42512)
TypeScript introduced a new flag called `noImplicitOverride` as part
of TypeScript v4.3. This flag introduces a new keyword called `override`
that can be applied to members which override declarations from a base
class. This helps with code health as TS will report an error if e.g.
the base class changes the method name but the override would still
have the old method name. Similarly, if the base class removes the method
completely, TS would complain that the memeber with `override` no longer
overrides any method.

A similar concept applies to abstract methods, with the exception that
TypeScript's builtin `noImplicitOverride` option does not flag members
which are implemented as part of an abstract class. We want to enforce
this as a best-practice in the repository as adding `override` to such
implemented members will cause TS to complain if an abstract member is
removed, but still implemented by derived classes.

More details: https://github.com/microsoft/TypeScript/issues/44457.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner 6e13179fe1 refactor: ensure compatibility with noImplicitOverride for examples (#42512)
Adds the `override` keyword to the `examples` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner 1a66199a7f refactor(zone.js): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `zone.js` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner 9e8a919385 refactor(localize): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `localize` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner 367ef56224 refactor(language-service): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `language-service` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner fdc6786b22 refactor(service-worker): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `service-worker` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:20 -07:00
Paul Gschwendtner b9c1604399 refactor(forms): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `forms` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner 859eb13f98 refactor(elements): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `elements` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner 1f84f01ff9 refactor(common): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `common` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner 462c157e8a refactor(benchpress): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `benchpress` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner 91366401f0 refactor(upgrade): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `upgrade` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner b98b0da37e refactor(router): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `router` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner dffb7c5218 refactor(platform-server): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `platform-server` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner a926402b4c refactor(platform-browser-dynamic): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `platform-browser-dynamic` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner 9067d362d4 refactor(platform-browser): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `platform-browser` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:19 -07:00
Paul Gschwendtner dc661ebda8 refactor(core): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `core` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:18 -07:00
Paul Gschwendtner c1f9d807e6 refactor(animations): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `animations` sources to ensure
 compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:18 -07:00
Paul Gschwendtner 2afaaf0bf9 refactor(dev-infra): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `dev-infra` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:18 -07:00
Paul Gschwendtner 0c9c8f51df refactor(compiler-cli): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `compiler-cli` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:18 -07:00
Paul Gschwendtner cf27076918 refactor(compiler): ensure compatibility with noImplicitOverride (#42512)
Adds the `override` keyword to the `compiler` sources to ensure
compatibility with `noImplicitOverride`.

PR Close #42512
2021-07-12 13:11:18 -07:00
Paul Gschwendtner 48010b3c73 build: enable noImplicitOverride in project (#42512)
Enables the `noImplicitOverride` option to improve
overall codehealth in the repository.

PR Close #42512
2021-07-12 13:11:18 -07:00
Arthur Ming 91a576db20 refactor(core): optimize the implementation about finding context from error in ErrorHandler (#42581)
in _findContext method, use conditional operator check whether the params 'error' exists and then us reccursion way to find context in original error  if getDebugContext's result does not exist.

PR Close #42581
2021-07-12 12:00:20 -07:00
Arthur Ming 2050d8408d build: update all symbol extractor (#42581)
update all symbol extractor by running 'yarn symbol-extractor:update' script

PR Close #42581
2021-07-12 12:00:19 -07:00
Arthur Ming e1d61243bd refactor(core): optimize the implementation about finding context from error in ErrorHandler (#42581)
in _findContext method, use conditional operator  check whether the params 'error' exists and then use nullish coalescing operator instead conditional operator when getDebugContext's result does not exist.

PR Close #42581
2021-07-12 12:00:19 -07:00
Kristiyan Kostadinov 65330f03a9 fix(compiler): incorrect context object being referenced from listener instructions inside embedded views (#42755)
Currently unless a listener inside of an embedded view tries to reference something from the parent view, or if the reference is a local ref, we don't generate the view restoration instructions and we allow for the value to be picked up from the context object in the function parameters. The problem is that the listener is only run during creation mode and the context object may have been swapped out afterwards.

These changes fix the issue by always generating the view restoration instructions for listeners inside templates.

Fixes #42698.

PR Close #42755
2021-07-12 11:58:19 -07:00
JoostK 17d3de25da fix(compiler-cli): properly emit literal types when recreating type parameters in a different file (#42761)
In #42492 the template type checker became capable of replicating a
wider range of generic type parameters for use in template type-check
files. Any literal types within a type parameter would however emit
invalid code, as TypeScript was emitting the literals using the text as
extracted from the template type-check file instead of the original
source file where the type node was taken from.

This commit works around the issue by cloning any literal types and
marking them as synthetic, signalling to TypeScript that the literal
text has to be extracted from the node itself instead from the source
file.

This commit also excludes `import()` type nodes from being supported,
as their module specifier may potentially need to be rewritten.

Fixes #42667

PR Close #42761
2021-07-12 11:48:34 -07:00
behrooz bozorg chami 2ed5a2db79 docs(core): fix ViewChildren code examples to avoid TS error (#42816)
Add a non-null assertion (`!`) in `ViewChildren` code examples to avoid
a TypeScript error due to uninitialized property.

Fixes #42811

PR Close #42816
2021-07-12 09:48:30 -07:00
Paul Gschwendtner 7dad7dfecd build: update to rules_nodejs v4.0.0-beta.0 (#42813)
Updates the Bazel NodeJS rules to v4.0.0-beta.0. This is necessary
so that the Angular components repo can update, and it's generally
good to stay as up-to-date as possible with the Bazel rules as it's
easy to fall behind, and updating early allows us to discover issues
affecting our tooling earlier (where they are easier to address due to
e.g. potential breaking change policy).

PR Close #42813
2021-07-12 09:46:34 -07:00
Paul Gschwendtner 88b2ff25d7 refactor(bazel): compatibility with rules_nodejs v4.0.0 (#42813)
This commit applies changes to `@angular/bazel` which are necessary
to support the Bazel NodeJS rules v4.0.0. The Bazel NodeJS rules
no longer support the `_tslibrary` option for the `LinkablePackageInfo`
provider and therefore we need to stop using it. Due to this removal,
we also need to add two new attributes called `package_name` and
`package_path` so that the API of `ng_module` matches `ts_library`.

Note: This is denoted as `refactor` as we currently are not able to
merge feature commits into patch branches, but we want the tooling
to not diverge significantly between the patch and next branch. It is
planned to update the merge tooling to allow for such changes to land.

PR Close #42813
2021-07-12 09:46:34 -07:00
Paul Gschwendtner 7b5405b070 build: remove skydoc and rules_sass from repository (#42813)
Skydoc is no longer used as `@angular/bazel` is no longer a
public API. The Sass rules were only used in a single place
in the repo where Sass is not really needed and has just been
added by accident most likely. We want to remove the Sass dependency
in preparation for Rules NodeJS v4.x where the Sass rules currently
still use an older version of `@bazel/worker` that is incompatible.

PR Close #42813
2021-07-12 09:46:34 -07:00
Paul Gschwendtner d8d7784b3a build: remove outdated note when updating bazel version (#42813)
We removed `bazel-toolchains` from the repository since dev-infra
provides the RBE platforms now (in a way where they are not reliant
on the Bazel version), so the comment in `.bazelversion` can be
removed.

PR Close #42813
2021-07-12 09:46:34 -07:00
Paul Gschwendtner f6957b24cd fix(dev-infra): ng_rollup_bundle rule should error if import cannot be resolved (#42813)
Rollup just prints a warning if an import cannot be resolved and ends up
being treated as an external dependency. This in combination with the
`silent = True` attribute for `rollup_bundle` means that bundles might
end up being extremely small without people noticing that it misses
actual imports.

To improve this situation, the warning is replaced by an error if
an import cannot be resolved.

This unveiles an issue with the `ng_rollup_bundle` macro from
dev-infra where imports in View Engine were not resolved but ended
up being treated as external. This did not prevent benchmarks using
this macro from working because the ConcatJS devserver had builtin
resolution for workspace manifest paths. Though given the new check
for no unresolved imports, this will now cause errors within Rollup, and
we need to fix the resolution. We can fix the issue by temporarily
enabling workspace linking. This does not have any performance
downsides.

To enable workspace linking (which we might need more often in the
future given the linker taking over patched module resolution), we
had to rename the `angular` dependency to a more specific one so
that the Angular linker could link into `node_modules/angular`.

PR Close #42813
2021-07-12 09:46:34 -07:00
Paul Gschwendtner 8267d25dfd build: no longer ship ecmascript module files within NPM packages (#42809)
We accidentally started shipping `.mjs` files for the following
modules (or module paths) as of the v12.1.0-next.2 tag:

- `@angular/compiler-cli`
- `@angular/common/locales`
- `@angular/bazel`
- `@angular/benchpress`
- `@angular/core/schematics`
- `@angular/elements/schematics`
- `@angular/language-service`
- `@angular/localize/schematics`,
- `@angular/localize/tools`
- `zone.js`

This did not cause any issues for consumers but we
want to not ship these files without having them wired
up in `package.json` files. We accidentally started shipping
these `.mjs` files due to a NodeJS update which wired up the
other JavaScript module output flavors in the `pkg_npm` rule.

https://github.com/bazelbuild/rules_nodejs/commit/911529fd364eb3ee1b8ecdc568a9fcf38a8b55ca

PR Close #42809
2021-07-12 09:42:02 -07:00
Paul Gschwendtner 71f428679b feat(dev-infra): add bazel rule for extracting JavaScript module flavors from targets (#42809)
Introduces a rule that collects declared JavaScript module output files
from a list of dependencies based on a configurable JavaScript module
provider. The extracted outputs are exposed within the `DefaultInfo` provider.

Targets defined using this rule can be used as input for rules that
require JavaScript sources, or if there are multiple JavaScript output
variants defined for a target while for example only the `JSModuleInfo`
outputs are of interest.

As an example: This rule is helpful in combination with `ts_library` and
`ng_module` as those rule expose multiple output flavors (which are
distinguishable by the JavaScript module providers as imported from `providers.bzl`).
i.e. these rules expose flavors for named AMD modules and ECMAScript module output.
If we want to ship a NPM package only using ECMAScript modules for
example, we could extract all `JSEcmaScriptModuleInfo`-denoted output
and feed that into the `pkg_npm` rule, compared to bringing in all
output flavors.

For reference:
https://github.com/bazelbuild/rules_nodejs/blob/stable/packages/typescript/internal/build_defs.bzl#L334-L337

PR Close #42809
2021-07-12 09:42:01 -07:00
dario-piotrowicz 12a9d2152e docs(core): edit and add docs for ng-template (#42704)
PR Close #42704
2021-07-12 09:39:30 -07:00
Andrew Scott 1c31828620 refactor(router): Adjust behavior for computed navigation restoration (#42751)
When another navigation is triggered during an in-process navigation and
the `canceledNavigationResolution` is `'computed'`, we should not
attempt to restore the browser history using `history.go`. Doing that
would trigger a third navigation through the router which would conflict
with the new navigation that we were trying to process. Instead, we
treat this as a redirect and skip the history restoration attempt. This
acts similarly to returning `UrlTree` from a guard.

Fixes issue described in https://github.com/angular/angular/pull/38884#issuecomment-863767152

PR Close #42751
2021-07-09 10:19:10 -07:00
George Kalpakas 51fd5e3742 fix(docs-infra): fix margin of social icon on small screens (#42790)
This commit fixes the margin of the social icons on small screens. This
mainly affects screens between 420px and 480px, where only one social
icon is show (due to limited space) but not necessarily the first one
(in DOM order).

**Before:** ![social icon before][1]
**After:** ![social icon after][2]

[1]: https://user-images.githubusercontent.com/8604205/124788616-2f5f0200-df52-11eb-9ec2-9e46b90cd286.png
[2]: https://user-images.githubusercontent.com/8604205/124788623-2ff79880-df52-11eb-90ec-31b04973de68.png

PR Close #42790
2021-07-09 10:15:28 -07:00
Bastian 723342a60a docs: fix http example to show actual message in console (#42773)
Previously, the error message in the console would print `[object Object]`
and not the actual error message. With this change, the error message is
printed in the console.

PR Close #42773
2021-07-09 10:14:35 -07:00
Gabriele Franchitto a8d5a31356 docs(core): initializeApp method should return function (#42743)
Update packages/core/src/application_init.ts

Update application_init.ts

Update application_init.ts

Co-Authored-By: George Kalpakas <kalpakas.g@gmail.com>

PR Close #42743
2021-07-08 14:50:18 -07:00
Borislav Ivanov 9ceadb0903 docs(core): fix spelling error (#42783)
Fix spelling error in migration schematics.

PR Close #42783
2021-07-08 14:49:47 -07:00
Joey Perrott f6bce3158a ci: use issue forms for issue creation (#42099)
Use new issue forms from Github for creating issues.

PR Close #42099
2021-07-08 14:07:31 -07:00
mgechev ca4df9c334 ci: update the feature request bot (#42791)
Introduce latest fixes in logging and labeling.

PR Close #42791
2021-07-08 14:06:10 -07:00
George Kalpakas d87917542a fix(service-worker): correctly handle unrecoverable state when a client no longer exists (#42736)
Previously, the ServiceWorker assumed that a client found in
`clientVersionMap` would exist (i.e. it could be retrieved via
`clients.get()`). However, if a browser tab had been closed, the
corresponding client (while present in `clientVersionMap`, which is only
updated on ServiceWorker initialization) would not be retrievable via
`clients.get()`.

This commit fixes it by checking whether the client exists before trying
to notify it about an unrecoverable state.

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas c7a2d76722 refactor(service-worker): switch to the official TypeScript typings (#42736)
Previously, we used custom typings for the ServiceWorker environment.
This was necessary back when the ServiceWorker package was introduced,
since there were no official typings.

Since there are now official typings for Web Workers (including
ServiceWorkers) offered by TypeScript as [lib.webworker.d.ts][1], this
commit gets rid of our custom typings in favor of using the official
ones.

[1]: https://github.com/microsoft/TypeScript/blob/v4.3.4/lib/lib.webworker.d.ts

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 7b7dce358d test(service-worker): better align mock global scope implementation with actual implementation (#42736)
This commit better aligns the mock `ServiceWorkerGlobalScope`
implementation used in ServiceWorker tests (and the associated typings)
with the actual implementation (and the official TypeScript typings).
This allows verifying the ServiceWorker behavior in a slightly more
realistic environment.

This is in preparation of switching from our custom typings to the
official TypeScript typings (`lib.webworker.d.ts`).

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 1670798aa8 test(service-worker): better align mock client implementations with actual implementations (#42736)
This commit better aligns the mock client implementations used in
ServiceWorker tests (and the associated typings) with the actual
implementations (and the official TypeScript typings). This allows
verifying the ServiceWorker behavior in a slightly more realistic
environment.

This is in preparation of switching from our custom typings to the
official TypeScript typings (`lib.webworker.d.ts`).

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 305042a945 refactor(service-worker): move mock client classes to their own file (#42736)
In the ServiceWorker tests, we use mock implementations of the various
client APIs that the ServiceWorker interacts with. Previously, these
mock implementations were defined in the `testing/scope.ts` file. This
added several extra classes to a file that already contains a few,
making it harder to maintain.

Therefore, this commit moves these mock client classes to a separate
`testing/clients.ts` file.

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 8493eb7e65 test(service-worker): better align mock event implementations with actual implementations (#42736)
This commit better aligns the mock event implementations used in
ServiceWorker tests (and the associated typings) with the actual
implementations (and the official TypeScript typings). This allows
verifying the ServiceWorker behavior in a slightly more realistic
environment.

This is in preparation of switching from our custom typings to the
official TypeScript typings (`lib.webworker.d.ts`).

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 7fe7836925 refactor(service-worker): move mock event classes to their own file (#42736)
In the ServiceWorker tests, we use mock implementations of the various
events emitted during the ServiceWorker lifecycle. Previously, these
mock implementations were defined in the `testing/scope.ts` file. This
added several extra classes to a file that already contains a few,
making it harder to maintain.

Therefore, this commit moves these mock event classes to a separate
`testing/events.ts` file.

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 60104086ba refactor(service-worker): make SwTestHarness.envIsSupported() a standalone function (#42736)
This commit makes the `SwTestHarness.envIsSupported()` static method a
standalone function. This function is used to determine whether the
current environment provides the necessary APIs to run the SW tests and
is independent of `SwTestHarness`, so is no need for it to be a static
method of `SwTestHarness`.

This is in preparation of switching from our custom typings to the
official TypeScript typings (`lib.webworker.d.ts`).

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 8a79690fdc refactor(service-worker): remove duplicate Context type (in favor of ExtendableEvent) (#42736)
This commit removes the duplicate `Context` interface and uses the
`ExtendableEvent` interface instead.

This is in preparation of switching from our custom typings to the
official TypeScript typings (`lib.webworker.d.ts`).

PR Close #42736
2021-07-08 10:28:23 -07:00
George Kalpakas 0562eae68e refactor(service-worker): remove unused variables and imports from tests (#42736)
This commit removes some unused variables (and associated imports) from
`integration_spec.ts`.

PR Close #42736
2021-07-08 10:28:22 -07:00
David Gilson fbc53e7c2d docs(forms): add diff between add and set control (#42638)
PR Close #42638
2021-07-08 10:27:43 -07:00
George Kalpakas f2523a8fef fix(service-worker): avoid storing redundant metadata for hashed assets (#42606)
The ServiceWorker needs to keep track of some metadata for unhashed
asset resources to know if/when they might need to be revalidated. This
applies to resources that do not exist on the filesystem at build-time
(and thus cannot be hashed), such as fonts or images loaded from
external sources. For hashed resources, this metadata is irrelevant,
because the hash is enough to verify that the content hasn't changed and
no revalidation is necessary.

Previously, the ServiceWorker would store such metadata for hashed
resources as well, even though it would never be used (thus taking up
space unnecessarily).

This commit fixes it by not storing metadata for hashed resources, i.e.
those that are included in an asset-group's `hashes` array.

PR Close #42606
2021-07-08 10:27:16 -07:00
George Kalpakas e6088ab736 docs(service-worker): add missing comma in example JSON data (#42606)
PR Close #42606
2021-07-08 10:27:16 -07:00
JoostK 0a17e98ae2 fix(compiler-cli): inline type checking instructions no longer prevent incremental reuse (#42759)
Source files that contain directives or components that need an inline
type constructor or inline template type-check block would always be
considered as affected in incremental rebuilds. The inline operations
cause the source file to be updated in the TypeScript program that is
created for template type-checking, which becomes the reuse program
in a subsequent incremental rebuild.

In an incremental rebuild, the source files from the new user program
are compared to those from the reuse program. The updated source files
are not the same as the original source file from the user program, so
the incremental engine would mark the file which needed inline
operations as affected. This prevents incremental reuse for these files,
causing sub-optimal rebuild performance.

This commit attaches the original source file for source files that have
been updated with inline operations, such that the incremental engine
is able to compare source files using the original source file.

Fixes #42543

PR Close #42759
2021-07-07 15:17:25 -07:00
George Kalpakas fe602c9c4e fix(docs-infra): ensure the sidenav backdrop covers the floating ToC (#42787)
Previously, on narrow pages where the sidenav was in `over` mode, the
sidenav's backdrop only covered the main docs content but not the
floating Table of Contents (ToC) on the right. This was inconsistent and
confusing to the user, because they could interact with the ToC and
scroll to different area of the main content while the sidenav and
backdrop were still covering the content.

This commit fixes it by ensuring the sidenav backdrop covers both the
main content and the floating ToC (when present).

Fixes #42778

PR Close #42787
2021-07-07 13:40:01 -07:00
George Kalpakas b9ab8b99a1 fix(docs-infra): log more SW debug info (#42776)
This commit expands the info printed to the console to help diagnose
ServiceWorker issues to include the [internal debug info][1] retrieved
from `/ngsw/state`. This will provide more useful data, such as the
activated SW's version, state, clients, recent operations and any recent
errors.

NOTE:
This temporarily increases the payload size. Removing this code and
reclaiming the payload size is being tracked in #41117.

[1]: https://angular.io/guide/service-worker-devops#locating-and-analyzing-debugging-information

PR Close #42776
2021-07-07 13:37:06 -07:00
George Kalpakas 0540a0339e refactor(docs-infra): replace deprecated Sass / division with math.div() (#42776)
This commit replaces the deprecated `/` operators used for division in
Sass files with the [recommended][1] `math.div()` function to get rid of
build warnings ([example][2]).

[1]: https://sass-lang.com/documentation/breaking-changes/slash-div
[2]: https://circleci.com/gh/angular/angular/1017640

PR Close #42776
2021-07-07 13:37:06 -07:00
George Kalpakas 89e7e52041 test(docs-infra): prevent warning due to missing expectation (#42776)
Fix a unit test warning due to Jasmine not realizing that
`httpMock.expectOne()` is an expectation.

[Example][1]:

> WARN: 'Spec 'DocumentService currentDocument should encode the request
> path to be case-insensitive' has no expectations.'

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

PR Close #42776
2021-07-07 13:37:06 -07:00
George Kalpakas bdac537852 build(docs-infra): update @angular/* to 12.1.1 (#42776)
Update `@angular/*` packages to latest 12.1.x versions (mainly to take
advantage of recent ServiceWorker improvements, such as #42607
and #42622).

PR Close #42776
2021-07-07 13:37:06 -07:00
George Kalpakas 80e602ca5c build(docs-infra): update payload sizes (#42776)
This commit updates the payload sizes for angular.io to make it easier
to identify payload size changes from an imminent update of `@angular/*`
packages.

PR Close #42776
2021-07-07 13:37:06 -07:00
dario-piotrowicz 9619255dd5 fix(docs-infra): slightly improve top-menu responsiveness (#42753)
make sure that the top-menu links don't get overlapped by
the search input, regardless on the browser's font-size and
the window's width

make also sure that the header's logo does not overlap the search
input on narrow windows, again regardless on the browser's font-size

PR Close #42753
2021-07-07 13:36:38 -07:00
Ryan Andersen eca48016c4 docs: add missing import to CartService tutorial instructions (#42701)
PR Close #42701
2021-07-07 09:54:55 -07:00
Theoklitos Bampouris ec60d10422 docs: change misspelled function (#42742)
Change the router.navigateUrl() to the correct function router.navigate() according to code example.
PR Close #42742
2021-07-07 09:54:24 -07:00
Paul Gschwendtner 9557e87ad8 fix(dev-infra): missing pkg_npm substitution for top-level targets being accessed (#42754)
Currently if a top-level target or file within `//dev-infra` is
being referenced. like `//dev-infra:tsconfig`, then the label
is not subsituted properly and breaks consumption of the built
NPM package.

PR Close #42754
2021-07-02 17:15:18 -07:00
Alan Agius 45116097c1 fix(compiler-cli): support reflecting namespace declarations (#42728)
DTS bundling, will cause originally namespaced imports become namespace declarations within the same file. Example:

Before bundling
```ts
import * as i1 from './router';

export declare class RouterModule {
    constructor(guard: any, router: Router);

    static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet...]>;
}
```

After bundling
```
declare namespace i1 {
  export {
    RouterOutletContract,
    RouterOutlet
  }
}

export declare class RouterModule {
    constructor(guard: any, router: Router);

    static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet...]>;
}
```

And therefore this commit adds support for reflecting types that are defined in such namespace declarations.

Closes #42064

PR Close #42728
2021-07-02 15:15:05 -07:00
Alan Agius 4a8ab4f149 fix(bazel): enable dts bundling for Ivy packages (#42728)
It is now possible to bundle DTS files of Ivy libraries since the blocker https://github.com/microsoft/rushstack/issues/1029 has been addressed upstream.

PR Close #42728
2021-07-02 15:15:04 -07:00
Alan Agius 9f8a256467 ci: remove @microsoft/api-extractor from ignoreDeps (#42728)
We can now allow Renovate to manage this dependency.

PR Close #42728
2021-07-02 15:15:04 -07:00
Paul Gschwendtner 6da24e6451 build: update API goldens after api-extractor update (#42749)
Given we have updated API extractor to the most recent
version, we need to update the API goldens because the
latest version uses alias exports to avoid collisions with
default library globals (like `Event`).

PR Close #42749
2021-07-02 12:32:23 -07:00
Paul Gschwendtner f78ab1ed43 build: update api-extractor dependency to support typescript 4.3 (#42749)
Updates the api-extractor dependencies of the repository, and within
the `@angular/bazel` package so that TypeScript 4.3 is supported when
a flattened typings file is generated. Without this update, the api
extractor could fail if a referenced tsconfig use a TS 4.3-only option such as
`noImplicitOverride`.

Note: This could also be considered a `feat:` for `@angular/bazel`,
but this package is not part of the public API anyway and we'd want
that change to land in the patch branches too (to keep the goldens
in sync between release branches as much as possible)

PR Close #42749
2021-07-02 12:32:23 -07:00
Paul Gschwendtner 3df4d898fa fix(dev-infra): api-golden tool does not specify a tsconfig and breaks for consumers (#42749)
Tools that are shipped as a Bazel rule with the shared dev-infra
tool require a specific `tsconfig` as otherwise `ts_library` will
accidentally look for a tsconfig in `@npm//:tsconfig` and the build
will fail. We bring in our dev-infra tsconfig and reference it
explicitly.

PR Close #42749
2021-07-02 12:32:23 -07:00
Paul Gschwendtner a1e9ccb340 fix(dev-infra): use API pagination for retrieving project branches (#42749)
We rely on a Github API `/branches` request to determine the active
release trains. Currently this logic is broken if more than 100
protected branches exist within a repository. This issue surfaced
recently where the `items_per_page` setting was set to `30`, causing
the merge tooling and release tooling to not detect the proper "latest"
release train.

This commit uses Github pagination for retrieving branches to determine
the active release trains, and makes the logic more long-term proof.

PR Close #42749
2021-07-02 12:32:23 -07:00
Paul Gschwendtner 7c9c54922c refactor(dev-infra): update octokit to latest version v18 (#42749)
We previously held off with updating Octokit to v18 due to
their more noticable issues with typings. This commit updates
us to the latest version in order to take advantage of the new
pagination API (which is also strongly-typed), and to not fall
behind too much over time (Octokit seems to change quite often..)

We work around the problem with the types for `getContent` by just
using a type cast with a TODO (and link to the issue). Similarly we
work around a problem where the Octokit types have an incorrect type
for the name of the labels array in an API response.

PR Close #42749
2021-07-02 12:32:23 -07:00
George Kalpakas aa261e7e01 fix(docs-infra): correctly configure top-menu nav-item in the sidenav (#42747)
Previously, the condition for showing the top-menu nav-menu in the
sidenav was the same as that for switching the sidenav mode from docked
(`mode: side`) to floating (`mode: over`). Therefore, the `isWide` input
of the corresponding `NavMenuComponent` could be hard-coded to `false`
(since the component would only be shown when the sidenav was in
floating mode).

In 61f6ed2fdf, these two desicions were
decoupled, which would result in the top-menu nav-item being shown in
the sidenav while the sidenav is in docked mode (and thus the `isWide`
input should be set to `true`).

This commit fixes it by setting the `isWide` input based on the value of
the `dockSideNav` property, as happens for the rest of the nav-menus.

PR Close #42747
2021-07-02 09:23:05 -07:00
George Kalpakas ee3fe6b8a2 refactor(docs-infra): simplify condition for determining sidenav mode (#42747)
Previously, the `AppComponent#showTopMenu` property was taken into
account when determining the `MatSidenav#mode` value. However, this was
redundant, because in the only case in which the use of `showTopMenu`
would make a difference (i.e. when `dockSideNav` was true and
`isSideNavDoc` was false) the sidenav would be closed and the hamburger
menu button would not be visible (thus there would be no way to open it
manually).

This commit simplifies the condition for determining the sidenav mode by
removing `showTopMenu` from the expression.

PR Close #42747
2021-07-02 09:23:05 -07:00
Andrew Scott 97c18f4527 fix(language-service): Do not override TS LS methods not supported by VE NgLS (#42727)
Historically, our Language Service was built with the potential to be a
drop-in replacement for the TypeScript Language Service with the added
benefit of being able to provide Angular-specific information as well.
While our VSCode extension does not use the Language Service in this
way, it appears that other community-contributed plugins do. We don't
really officially support this use-case but there's not real reason for
us to override the TypeScript Language Service's
implementation in the VE Angular Language Service so that it returns
`undefined`. As with other non-implemented methods, we can just allow
this to be deferred to TSLS.

fixes #42715

PR Close #42727
2021-07-01 15:23:50 -07:00
ivanwonder df5cc1fbbf fix(compiler-cli): return directives for an element on a microsyntax template (#42640)
When the template type checker try to get a symbol of a template node, it will
not return the directives intended for an element on a microsyntax template,
for example, `<div *ngFor="let user of users;" dir>`, the `dir` will be skipped,
but it's needed in language service.

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

PR Close #42640
2021-07-01 09:35:24 -07:00
dario-piotrowicz 723d21455a fix(docs-infra): move dots inside Usage Notes anchor tag (#42725)
in the html generated aio docs the dots of "Usage Notes..."
should be part of the anchor tag, same as it is for "See More..."

PR Close #42725
2021-07-01 09:34:05 -07:00
Renovate Bot 72073cfb16 build: update dependency husky to v7 (#42730)
PR Close #42730
2021-07-01 09:32:34 -07:00
Kristiyan Kostadinov 41c6877c01 fix(core): error in TestBed if module is reset mid-compilation in ViewEngine (#42669)
When `TestBed.compileComponents` is called under ViewEngine, we kick off a compilation and return a promise that resolves once the compilation is done. In most cases the consumer doesn't _have_ to await the returned promise, unless their components have external resources.

The problem is that the test could be over by the time the promise has resolved, in which case we still cache the factory of the test module. This becomes a problem if another compilation is triggered right afterwards, because it'll see that we still have a `_moduleFactory` and it won't recreate the factory.

These changes resolve the issue by saving a reference to the module type that is being compiled and checking against it when the promise resolves.

Note that while this problem was discovered while trying to roll out the new test module teardown behavior in the Components repo (https://github.com/angular/components/pull/23070), it has been there for a long time. The new test behavior made it more apparent.

PR Close #42669
2021-06-30 14:32:23 -07:00
Joey Perrott 12e0cfab54 release: cut the v12.1.1 release (#42721) 2021-06-30 13:13:53 -07:00
Paul Gschwendtner aab41ca42f build: update API goldens to reflect new tool (#42688)
Updates the TS API guardian goldens with their equivalents
based on the new shared dev-infra tool.

PR Close #42688
2021-06-30 11:43:49 -07:00
Paul Gschwendtner 3482636b5a build: use api-golden tool from dev-infra for testing public API (#42688)
Switches our TS API guardian targets to rather use the new tool from
dev-infra that relies on Microsoft's API extractor.

PR Close #42688
2021-06-30 11:43:49 -07:00
Paul Gschwendtner b11923cd7a feat(dev-infra): introduce shared tool for validating API signature (#42688)
For the last years the Angular repositories relied on `ts-api-guardian`
for testing the public API signature. This project worked well in
general but its another inconvenience to maintain if we could rely on
Microsoft's `api-extractor` tool.

Especially since with TypeScript 4.3 issues with export aliases appeared
that would require us to extend TS API guardian to support such exports.
This is not as straightforward as it sounds, given it requires rewriting
of declarations to show-case the proper name in the API golden. Microsoft's
API extractor has integrated support for this.

As of TypeScript 4.3, we want to start using the new `override` keyword.
We are not able to use that keyword currently because an old version of
API extractor is used in the `ng_module` rule to flatten the types into
a single file. To fix this, we need to update `api-extractor`, but this
unveils the issue with TS API guardian because the most recent version
of api-extractor uses alias exports to avoid potential conflicts
with globals available through the TypeScript default libraries (e.g.
`dom.d.ts`).

PR Close #42688
2021-06-30 11:43:48 -07:00
mgechev 0cf388e882 docs: add last updated date to roadmap (#42615)
PR Close #42615
2021-06-30 11:41:57 -07:00
Pete Bacon Darwin d19ddd1a87 fix(platform-browser): in Meta.addTag() do not add duplicate meta tags (#42703)
Previously, if there were two tags with the same "name" or "property" attribute selector,
then only the first was checked for duplicates when deciding whether to add a new meta
tag.

Fixes #42700
Fixes #19606

PR Close #42703
2021-06-30 10:35:30 -07:00
pavlenko c380d56c6d docs: setting context value inside an interceptor (#42699)
Usage of `get`/`set` methods should be done on a context object instead of a `HttpRequest` instance.

PR Close #42699
2021-06-30 09:13:46 -07:00
Alan Agius f84d826a3a fix(dev-infra): remove bots from special thanks section (#42697)
With this change we remove known used bots from special thanks section in the changelog.

PR Close #42697
2021-06-29 11:13:51 -07:00
George Kalpakas 78cf10b28b refactor(docs-infra): make angular.io and docs examples compatible with RxJS v7 (#42660)
This commit applies the necessary changes to make angular.io and (most)
docs examples compatible with both RxJS v6 and v7. It also adds new
steps to relevant CI jobs to test angular.io and docs examples against
RxJS v7 as well (to catch potential regressions).

NOTE:
Some of the docs examples are not compatible with RxJS v7 and are
therefore excluded from the tests. The SystemJS-based ngUpgrade
examples in particular are excluded, since they require a different
SystemJS configs to run against RxJS v6 and v7 and the extra complexity
of managing that is not worth it for the 4 affected examples.

PR Close #42660
2021-06-29 10:29:58 -07:00
George Kalpakas a0e5b85694 test(docs-infra): allow excluding certain docs examples from tests (#42660)
This commit adds support for excluding certain docs examples from the
command used to run tests. This is useful to run extra tests on CI that
might not be compatible with all examples (for example, run tests with
different versions of a dependency).

In a subsequent commit, this will be used to run tests against RxJS v7
as a quick way to catch potential regressions.

PR Close #42660
2021-06-29 10:29:58 -07:00
George Looshch ace0a50646 docs: remove duplicate link to guide/inputs-outputs.md (#42654)
When you click on `Understanding Angular > Components > Sharing data between
child and parent directives and components` in navigation sidebar, another
item gets selected: `Understanding Angular > Templates > Inputs and Outputs`
Both of them are linked to the same guide but the view cannot handle
situations when several entries point to the same guide.

This commit fixes that by removing the second entry.

Fixes #42652

PR Close #42654
2021-06-29 09:27:48 -07:00
Paul Gschwendtner 0f27f89d38 feat(dev-infra): add command for printing release train information (#42644)
Currently the active release trains are printed when a developer
runs `ng-dev publish release`. This is not ideal because it requires
the developer to provide an OAuth token, to be on the next branch, and
to have no uncommitted changes, while the actual release train
information is not dependent on these checks.

This commit introduces a new command called `ng-dev release info` that
can be used to retrieve relase information without the aforementioned
requirements. Note that this command provides more detailed information
about release branches than the `ng-dev caretaker check` command (which
also requires on authentication as a side note). The `release info`
command also prints active LTS branches for example.

PR Close #42644
2021-06-28 11:50:57 -07:00
Lars Gyrup Brink Nielsen a1e036cfd1 docs: correct literal string example (#42623)
Change literal string example `pi` to `'pi'`.

PR Close #42623
2021-06-28 10:05:10 -07:00
codebriefcase 7ea1d4720a fix(docs-infra): styling fix on error pages (#42627)
Add Center Aligment for heading texts and additional styles on 404 (not found) related pages

PR Close #42627
2021-06-28 09:50:24 -07:00
Dario Piotrowicz 560dd44de4 docs(core): add context jsdoc param to createEmbeddedView (#42675)
PR Close #42675
2021-06-28 09:34:17 -07:00
George Kalpakas 87cdd84c17 docs: update Roadmap section header from "Done" to "Completed" (#42620)
"Completed" just sounds better (to me).

PR Close #42620
2021-06-28 09:33:18 -07:00
George Kalpakas 4059ecaed1 fix(docs-infra): fix styling of <summary> elements on dark theme (#42620)
Previously, the color of `<summary>` elements was hard-coded to `black`.
This did not work well on the dark theme, where the background color of
the page is also very dark.

This commit fixes it by removing the explicit color style, thus letting
`<summary>` elements inherit the color of their container.

Closes #42616

PR Close #42620
2021-06-28 09:33:18 -07:00
George Kalpakas e03291bc34 fix(docs-infra): improve styling of completed Roadmap projects (#42620)
This commit improves the styling of the "Completed projects" section of
the Roadmap by (a) making it consistent with the rest of the Roadmap
sections and (b) making it more similar with `<details>` elements on
other pages.

**Before:**
  _Collapsed:_ ![completed projects collapsed (before)][1]
  _Expanded:_ ![completed projects expanded (before)][2]
**After:**
  _Collapsed:_ ![completed projects collapsed (after)][3]
  _Expanded:_ ![completed projects expanded (after)][4]

[1]: https://user-images.githubusercontent.com/8604205/122917101-50c2ca00-d366-11eb-8348-01efd69cedf2.png
[2]: https://user-images.githubusercontent.com/8604205/122917109-515b6080-d366-11eb-9f18-c794fcea8dd1.png
[3]: https://user-images.githubusercontent.com/8604205/122917115-528c8d80-d366-11eb-947a-2d7da3950069.png
[4]: https://user-images.githubusercontent.com/8604205/122917117-53252400-d366-11eb-93e7-9384a7431c0d.png

PR Close #42620
2021-06-28 09:33:18 -07:00
George Kalpakas ffebb3e785 refactor(docs-infra): make <details> styles more re-usable (#42620)
This commit makes the styling for `<details>` elements (including
expand/collapse actions in their `<summary>`) more re-usable.

PR Close #42620
2021-06-28 09:33:18 -07:00
George Kalpakas 0f435a3cf9 refactor(docs-infra): merge duplicate code.scss files (#42620)
PR #41129 reorganized the SCSS files of the angular.io app moving most
of them in sub-directories. Due to incorrectly resolved merge conflicts
for PRs targeting the SCSS files around that time, we ended up with
duplicate style files for `<code>` elements:
- `styles/2-modules/_code.scss`
- `styles/2-modules/code/_code.scss` +
  `styles/2-modules/code/_code-theme.scss`

This commit gets rid of the extra file (`styles/2-modules/_code.scss`)
and ports any changes from it to the correct files inside the `code/`
sub-directory.

PR Close #42620
2021-06-28 09:33:18 -07:00
dario-piotrowicz 1c50869792 docs(compiler): interally typo fixed (#42676)
PR Close #42676
2021-06-28 09:32:23 -07:00
Zach Arend f6b828e292 fix(compiler-cli): add support for partially evaluating types (#41661)
Add support to the partial evaluator for evaluating literal types and
tuples.

resolves #41338

PR Close #41661
2021-06-25 09:59:27 -07:00
marvinbeckert bd42b795f7 docs: remove default linting tool in workspace guide (#42655)
PR Close #42655
2021-06-25 09:55:53 -07:00
584 changed files with 12436 additions and 5985 deletions
-2
View File
@@ -1,3 +1 @@
4.0.0
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
+11 -8
View File
@@ -24,19 +24,19 @@ version: 2.1
# **NOTE 2 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
# **NOTE 3 **: 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-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
var_3: &cache_key v4-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ 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 v4-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
# Windows needs its own cache key because binaries in node_modules are different.
var_3_win: &cache_key_win v4-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
var_3_win: &cache_key_win v4-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "aio/yarn.lock" }}
var_4_win: &cache_key_win_fallback v4-angular-win-node-14-{{ checksum "month.txt" }}-{{ 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 v1-angular-components-{{ checksum "month.txt" }}-7cc42f5d835b7971e9ff73e220b801cf7834d515
var_5: &components_repo_unit_tests_cache_key v1-angular-components-{{ checksum "month.txt" }}-d090617912da8e70aa336aa5b4d804b1b535402e
var_6: &components_repo_unit_tests_cache_key_fallback v1-angular-components-{{ checksum "month.txt" }}
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
@@ -441,6 +441,9 @@ jobs:
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
# Check the bundle sizes.
- run: yarn --cwd aio payload-size aio-local
# Run tests with RxJS v7.
- run: yarn --cwd aio add rxjs@7.1.0
- run: yarn --cwd aio test --progress=false --watch=false
test_aio_tools:
executor: default-executor
@@ -469,6 +472,10 @@ jobs:
# 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 --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
# Run tests with RxJS v7.
# (Exclude some examples that are not yet compatible with v7.)
- run: yarn --cwd aio/tools/examples/shared add rxjs@7.1.0 && yarn --cwd aio boilerplate:add
- run: yarn --cwd aio example-e2e --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --exclude=practical-observable-usage --exclude=upgrade-module --exclude=upgrade-phonecat
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
aio_preview:
@@ -671,7 +678,7 @@ jobs:
background: true
# add module umd tsc compile option so the test can work
# properly in the legacy browsers
- run: yarn tsc -p packages --module UMD
- run: yarn tsc -p packages/tsconfig-legacy-saucelabs.json --module UMD
- run: yarn tsc -p modules --module UMD
- run: yarn bazel build //packages/zone.js:npm_package
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
@@ -734,10 +741,6 @@ jobs:
# variable. It needs to be hardcoded here, because env variables interpolation is
# not supported.
- '/tmp/angular-components-repo'
- run:
# TODO(devversion): remove once https://github.com/angular/components/pull/23056 is available.
name: Replace RBE container instance name
command: sed -i "s#default_instance#primary_instance#g" ${COMPONENTS_REPO_TMP_DIR}/.bazelrc
- run:
# Updates the `angular/components` `package.json` file to refer to the release output
# inside the `packages-dist` directory.
+1 -1
View File
@@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
setPublicVar COMPONENTS_REPO_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
setPublicVar COMPONENTS_REPO_COMMIT "7cc42f5d835b7971e9ff73e220b801cf7834d515"
setPublicVar COMPONENTS_REPO_COMMIT "d090617912da8e70aa336aa5b4d804b1b535402e"
####################################################################################################
-66
View File
@@ -1,66 +0,0 @@
---
name: "Bug Report"
about: Report a bug in the Angular Framework
---
<!--
Oh hi there!
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
-->
# Bug Report
### Affected Package
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
<!-- edit: --> The issue is caused by package @angular/....
### Is this a regression?
<!-- Did this behavior use to work in the previous version? -->
<!-- edit: --> Yes, the previous version in which this bug was not present was: ....
### Description
<!-- edit: --> A clear and concise description of the problem...
## Minimal Reproduction
<!--
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
-->
<!-- edit: --> https://stackblitz.com/...
<!--
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
Issues that don't have enough info and can't be reproduced will be closed.
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#submit-issue
-->
## Exception or Error
<pre><code>
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
</code></pre>
## Your Environment
**Angular Version:**
<pre><code>
<!-- run `ng version` and paste output below -->
</code></pre>
**Anything else relevant?**
<!-- Is this a browser specific issue? If so, please specify the browser and version. -->
<!-- Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->
+84
View File
@@ -0,0 +1,84 @@
name: Bug Report
description: Report a bug in the Angular Framework
body:
- type: dropdown
id: affected-packages
attributes:
label: Which @angular/* package(s) are the source of the bug?
options:
- animations
- bazel
- common
- compiler-cli
- compiler
- elements
- forms
- language-service
- localize
- platform-browser-dynamic
- platform-browser
- platform-server
- router
- service-worker
- upgrade
- Don't known / other
multiple: true
validations:
required: true
- type: dropdown
id: is-regression
attributes:
label: Is this a regression?
options:
- 'Yes'
- 'No'
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
validations:
required: true
- type: input
id: reproduction
attributes:
label: Please provide a link to a minimal reproduction of the bug
- type: textarea
id: exception-or-error
attributes:
label: Please provide the exception or error you saw
render: true
- type: textarea
id: environment
attributes:
label: Please provide the environment you discovered this bug in
render: true
placeholder: |
Angular CLI: 12.0.5
Node: 14.17.0
Package Manager: yarn 1.22.10
OS: linux x64
Angular: 12.0.5
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1200.5
@angular-devkit/build-angular 12.0.5
@angular-devkit/core 12.0.5
rxjs 6.6.7
typescript 4.2.4
- type: textarea
id: other
attributes:
label: Anything else?
@@ -1,31 +0,0 @@
---
name: "Feature Request"
about: Suggest a feature for Angular Framework
---
<!--
Oh hi there!
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
-->
# Feature Request
### Relevant Package
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
<!-- edit: --> This feature request is for @angular/....
### Description
<!-- edit: --> A clear and concise description of the problem or missing capability...
### Describe the solution you'd like
<!-- edit: --> If you have a solution in mind, please describe it.
### Describe alternatives you've considered
<!-- edit: --> Have you considered any alternative solutions or workarounds?
@@ -0,0 +1,46 @@
name: 'Feature Request'
description: Suggest a feature for Angular Framework
body:
- type: dropdown
id: affected-packages
attributes:
label: Which @angular/* package(s) are relevant/releated to the feature request?
options:
- animations
- bazel
- common
- compiler-cli
- compiler
- elements
- forms
- language-service
- localize
- platform-browser-dynamic
- platform-browser
- platform-server
- router
- service-worker
- upgrade
multiple: true
- type: textarea
id: description
attributes:
label: Description
validations:
required: true
- type: textarea
id: proposed-solution
attributes:
label: Proposed solution
validations:
required: true
- type: textarea
id: alternatives-considered
attributes:
label: Alternatives considered
validations:
required: true
-48
View File
@@ -1,48 +0,0 @@
---
name: "Docs or angular.io Bug Report"
about: Report an issue in Angular's documentation or angular.io application
---
<!--
Oh hi there!
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
-->
# Docs or angular.io Bug Report
### Description
<!-- edit: --> A clear and concise description of the problem...
## Minimal Reproduction
### What's the affected URL?**
<!-- edit: --> https://angular.io/...
### Reproduction Steps**
<!-- If applicable please list the steps to take to reproduce the issue -->
### Expected vs Actual Behavior**
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
## Screenshot
<!-- Often a screenshot can help to capture the issue better than a long description. -->
<!-- upload a screenshot:-->
## Exception or Error
<pre><code>
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
</code></pre>
## Your Environment
### Browser info
<!-- Is this a browser specific issue? If so, please specify the device, browser, and version. -->
### Anything else relevant?
<!-- Please provide additional info if necessary. -->
+42
View File
@@ -0,0 +1,42 @@
name: 'Docs or angular.io Bug Report'
description: Report an issue in Angular's documentation or angular.io application
body:
- type: textarea
id: description
attributes:
label: Description
validations:
required: true
- type: input
id: affected-url
attributes:
label: What is the affected URL?
- type: textarea
id: reproduction-steps
attributes:
label: Please provide the steps to reproduce the issue
- type: textarea
id: expected-vs-actual-behavior
attributes:
label: Please provide the expected behavior vs the actual behavior you encountered
- type: textarea
id: screenshot
attributes:
label: Please provide a screenshot if possible
- type: textarea
id: exception-or-error
attributes:
label: Please provide the exception or error you saw
render: true
- type: textarea
id: browser-info
attributes:
label: Is this a browser specific issue? If so, please specify the device, browser, and version.
render: true
+1 -1
View File
@@ -10,6 +10,6 @@ jobs:
if: github.repository == 'angular/angular'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/feature-request@8467fd69f068914f8f25e10b1a80c183ee886de4
- uses: angular/dev-infra/github-actions/feature-request@f83903fe1ac848407ef81465f66588e5accb6537
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
-1
View File
@@ -1 +0,0 @@
_
+2 -1
View File
@@ -15,5 +15,6 @@ export const caretaker: CaretakerConfig = {
name: 'Initial Triage Queue',
query: `is:open no:milestone`,
}
]
],
caretakerGroup: 'angular-caretaker',
};
+4 -1
View File
@@ -25,6 +25,9 @@ export const merge: DevInfraMergeConfig['merge'] = async api => {
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
},
targetLabelExemptScopes: ['dev-infra', 'docs-infra']
// `dev-infra` and `docs-infra` are not affecting the public NPM packages. Similarly,
// the `bazel` package is not considered part of the public API so that features
// can land in patch branches.
targetLabelExemptScopes: ['dev-infra', 'docs-infra', 'bazel']
};
};
+3 -3
View File
@@ -36,18 +36,18 @@ filegroup(
srcs = [
# We also declare the unminified AngularJS files since these can be used for
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
"@npm//:node_modules/angular/angular.js",
"@npm//:node_modules/angular/angular.min.js",
"@npm//:node_modules/angular-1.5/angular.js",
"@npm//:node_modules/angular-1.5/angular.min.js",
"@npm//:node_modules/angular-1.6/angular.js",
"@npm//:node_modules/angular-1.6/angular.min.js",
"@npm//:node_modules/angular-1.7/angular.js",
"@npm//:node_modules/angular-1.7/angular.min.js",
"@npm//:node_modules/angular-mocks/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.5/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.7/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.8/angular-mocks.js",
"@npm//:node_modules/angular-1.8/angular.js",
"@npm//:node_modules/angular-1.8/angular.min.js",
],
)
+74
View File
@@ -1,3 +1,77 @@
<a name="12.1.3"></a>
# 12.1.3 (2021-07-21)
### animations
| Commit | Description |
| -- | -- |
| [3cddc3d6bc](https://github.com/angular/angular/commit/3cddc3d6bc1045b76980ba3e866350d58deb0718) | fix(animations): normalize final styles in buildStyles ([#42763](https://github.com/angular/angular/pull/42763)) |
### compiler-cli
| Commit | Description |
| -- | -- |
| [d207ea06d1](https://github.com/angular/angular/commit/d207ea06d1bb554e822bab2eadcf12ef50117bd4) | fix(compiler-cli): use correct module import for types behind a `forwardRef` ([#42887](https://github.com/angular/angular/pull/42887)) |
| [e6d520f3d9](https://github.com/angular/angular/commit/e6d520f3d9104c63129b94fbf5fe54b392715fc5) | perf(compiler-cli): optimize cycle detection using a persistent cache ([#41271](https://github.com/angular/angular/pull/41271)) |
### core
| Commit | Description |
| -- | -- |
| [a6db152c78](https://github.com/angular/angular/commit/a6db152c78bc82ef39e529ab5ea55f810b17fa2e) | fix(core): use correct injector when resolving DI tokens from within a directive provider factory ([#42886](https://github.com/angular/angular/pull/42886)) |
## Special Thanks:
Alan Agius, David Shevitz, George Kalpakas, Joey Perrott, JoostK, Krzysztof Kotowicz, Minko Gechev, Paul Gschwendtner and dario-piotrowicz
<a name="12.1.2"></a>
# 12.1.2 (2021-07-14)
### bazel
| Commit | Description |
| -- | -- |
| [4a8ab4f149](https://github.com/angular/angular/commit/4a8ab4f1499a560bb4373b088785e43f26384e1c) | fix(bazel): enable dts bundling for Ivy packages ([#42728](https://github.com/angular/angular/pull/42728)) |
### common
| Commit | Description |
| -- | -- |
| [d654c7933a](https://github.com/angular/angular/commit/d654c7933a732c23dc1e68b17766457d2d11a4d8) | fix(common): re-sort output of `KeyValuePipe` when `compareFn` changes ([#42821](https://github.com/angular/angular/pull/42821)) |
### compiler
| Commit | Description |
| -- | -- |
| [2566cbb48c](https://github.com/angular/angular/commit/2566cbb48cddd23c4b29d01ad557bc71ac716700) | fix(compiler): add mappings for all HTML entities ([#42818](https://github.com/angular/angular/pull/42818)) |
| [65330f03a9](https://github.com/angular/angular/commit/65330f03a92f2743719d0e0d4cedcaadbb8c5b21) | fix(compiler): incorrect context object being referenced from listener instructions inside embedded views ([#42755](https://github.com/angular/angular/pull/42755)) |
### compiler-cli
| Commit | Description |
| -- | -- |
| [17d3de25da](https://github.com/angular/angular/commit/17d3de25daf339612c267001f0c2237533d7c789) | fix(compiler-cli): properly emit literal types when recreating type parameters in a different file ([#42761](https://github.com/angular/angular/pull/42761)) |
| [0a17e98ae2](https://github.com/angular/angular/commit/0a17e98ae2813338f03e3e01bb7cfa6024f4632b) | fix(compiler-cli): inline type checking instructions no longer prevent incremental reuse ([#42759](https://github.com/angular/angular/pull/42759)) |
| [45116097c1](https://github.com/angular/angular/commit/45116097c1dafd902014e0f680e0d50023467883) | fix(compiler-cli): support reflecting namespace declarations ([#42728](https://github.com/angular/angular/pull/42728)) |
| [df5cc1fbbf](https://github.com/angular/angular/commit/df5cc1fbbf1b1f02f1f45603552a2530bb59688d) | fix(compiler-cli): return directives for an element on a microsyntax template ([#42640](https://github.com/angular/angular/pull/42640)) |
### core
| Commit | Description |
| -- | -- |
| [63013546e1](https://github.com/angular/angular/commit/63013546e130d823db26ad96e1d4cb346e633a03) | fix(core): associate the NgModule scope for an overridden component ([#42817](https://github.com/angular/angular/pull/42817)) |
| [9ebd41e39c](https://github.com/angular/angular/commit/9ebd41e39c597ef6df2de2fb63d6458337e2757d) | fix(core): allow proper type inference when `ngFor` is used with a `trackBy` function ([#42692](https://github.com/angular/angular/pull/42692)) |
| [41c6877c01](https://github.com/angular/angular/commit/41c6877c013ba84ba5e46309b2310c097ad9e354) | fix(core): error in TestBed if module is reset mid-compilation in ViewEngine ([#42669](https://github.com/angular/angular/pull/42669)) |
### language-service
| Commit | Description |
| -- | -- |
| [97c18f4527](https://github.com/angular/angular/commit/97c18f4527187206db8b0f5730b80d2220027f9f) | fix(language-service): Do not override TS LS methods not supported by VE NgLS ([#42727](https://github.com/angular/angular/pull/42727)) |
### service-worker
| Commit | Description |
| -- | -- |
| [d87917542a](https://github.com/angular/angular/commit/d87917542a00ed6f58c7b95e3eba6aeddc5eee01) | fix(service-worker): correctly handle unrecoverable state when a client no longer exists ([#42736](https://github.com/angular/angular/pull/42736)) |
| [f2523a8fef](https://github.com/angular/angular/commit/f2523a8fef549fab6ec480ecfc966c9d938a5423) | fix(service-worker): avoid storing redundant metadata for hashed assets ([#42606](https://github.com/angular/angular/pull/42606)) |
## Special Thanks:
Alan Agius, Andrew Kushnir, Andrew Scott, Arthur Ming, Bastian, Borislav Ivanov, David Gilson, David Shevitz, Gabriele Franchitto, George Kalpakas, Joey Perrott, JoostK, Kristiyan Kostadinov, Mark Goho, Meir Blumenfeld, Paul Gschwendtner, Pete Bacon Darwin, Ryan Andersen, Theoklitos Bampouris, behrooz bozorg chami, dario-piotrowicz, ivanwonder and mgechev
<a name="12.1.1"></a>
# 12.1.1 (2021-06-30)
### compiler-cli
| Commit | Description |
| -- | -- |
| f6b828e292 | fix(compiler-cli): add support for partially evaluating types (#41661) |
### platform-browser
| Commit | Description |
| -- | -- |
| d19ddd1a87 | fix(platform-browser): in `Meta.addTag()` do not add duplicate meta tags (#42703) |
## Special Thanks:
Alan Agius, Dario Piotrowicz, George Kalpakas, George Looshch, Lars Gyrup Brink Nielsen, Paul Gschwendtner, Pete Bacon Darwin, Zach Arend, codebriefcase, dario-piotrowicz, marvinbeckert, mgechev and pavlenko
<a name="12.1.0"></a>
# 12.1.0 (2021-06-24)
### compiler
+2 -17
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 = "0fa2d443571c9e02fcb7363a74ae591bdcce2dd76af8677a95965edf329d778a",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.6.0/rules_nodejs-3.6.0.tar.gz"],
sha256 = "5c40083120eadec50a3497084f99bc75a85400ea727e82e0b2f422720573130f",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/4.0.0-beta.0/rules_nodejs-4.0.0-beta.0.tar.gz"],
)
# Check the rules_nodejs version and download npm dependencies
@@ -34,11 +34,6 @@ yarn_install(
yarn_lock = "//:yarn.lock",
)
# Load angular dependencies
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
rules_angular_dev_dependencies()
# Load protractor dependencies
load("@npm//@bazel/protractor:package.bzl", "npm_bazel_protractor_dependencies")
@@ -52,13 +47,3 @@ web_test_repositories()
load("//dev-infra/bazel/browsers:browser_repositories.bzl", "browser_repositories")
browser_repositories()
# Setup the rules_sass toolchain
load("@io_bazel_rules_sass//:defs.bzl", "sass_repositories")
sass_repositories()
# Setup the skydoc toolchain
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
skydoc_repositories()
@@ -50,5 +50,5 @@ export class PopupComponent {
private _message = '';
@Output()
closed = new EventEmitter();
closed = new EventEmitter<void>();
}
@@ -1,9 +1,9 @@
// #docplaster
// #docregion import-http
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// #docregion props
import { Product } from './products';
// #enddocregion import-http
// #enddocregion props, import-http
@Injectable({
providedIn: 'root'
@@ -79,8 +79,7 @@ export class ConfigService {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
`Backend returned code ${error.status}, body was: `, error.error);
}
// Return an observable with a user-facing error message.
return throwError(
@@ -14,7 +14,7 @@ import { NoopInterceptor } from './noop-interceptor';
// #enddocregion interceptor-providers
import { TrimNameInterceptor } from './trim-name-interceptor';
import { UploadInterceptor } from './upload-interceptor';
import { RetryInterceptor } from './retry-interceptor';
// #docregion interceptor-providers
/** Http interceptor providers in outside-in order */
@@ -39,7 +39,7 @@ export class RetryInterceptor implements HttpInterceptor {
tap(null,
() => {
// An error has occurred, so increment this request's ERROR_COUNT.
req.set(ERROR_COUNT, req.get(ERROR_COUNT) + 1);
req.context.set(ERROR_COUNT, req.context.get(ERROR_COUNT) + 1);
}),
// #docregion reading-context
// Retry the request a configurable number of times.
+1 -1
View File
@@ -1,7 +1,7 @@
<div class="center-layout-wide">
<div class="nf-container l-flex-wrap flex-center">
<img src="assets/images/support/angular-404.svg" width="300" height="300"/>
<div class="nf-response l-flex-wrap">
<div class="nf-response l-flex-wrap center">
<h1 class="no-anchor no-toc">Page Not Found</h1>
<p>We're sorry. The page you are looking for cannot be found.</p>
</div>
+1 -2
View File
@@ -173,7 +173,7 @@ Define metadata objects with the following limited syntax:
<td><code>`pie is ${multiplier} times better than cake`</code></td>
<tr>
<td>Literal string</td>
<td><code>pi</code></td>
<td><code>'pi'</code></td>
</tr>
<tr>
<td>Literal number</td>
@@ -558,7 +558,6 @@ In [Angular Ivy](guide/ivy), the template type checker has been completely rewri
As a result, templates that previously compiled under View Engine can fail type checking under Ivy. This can happen because Ivy's stricter checking catches genuine errors, or because application code is not typed correctly, or because the application uses libraries in which typings are inaccurate or not specific enough.
This stricter type checking is not enabled by default in version 9, but can be enabled by setting the `strictTemplates` configuration option.
We do expect to make strict type checking the default in the future.
For more information about type-checking options, and about improvements to template type checking in version 9 and above, see [Template type checking](guide/template-typecheck).
+1 -18
View File
@@ -111,20 +111,6 @@ Project-specific [TypeScript](https://www.typescriptlang.org/) configuration fil
| `tsconfig.spec.json` | [TypeScript](https://www.typescriptlang.org/) configuration for the application tests. See [TypeScript Configuration](guide/typescript-configuration). |
| `tslint.json` | Application-specific [TSLint](https://palantir.github.io/tslint/) configuration. |
### End-to-end test files
An `e2e/` folder at the top level contains source files for a set of end-to-end tests that correspond to the root-level application, along with test-specific configuration files.
For a multi-project workspace, application-specific end-to-end tests are in the project root, under `projects/project-name/e2e/`.
<code-example language="none">
e2e/
src/ (end-to-end tests for my-app)
app.e2e-spec.ts
app.po.ts
protractor.conf.js (test-tool config)
tsconfig.json (TypeScript config inherits from workspace)
</code-example>
{@a multiple-projects}
@@ -160,9 +146,6 @@ my-workspace/
projects/ (generated applications and libraries)
my-first-app/ --(an explicitly generated application)
... --(application-specific config)
e2e/ ----(corresponding e2e tests)
src/ ----(e2e tests source)
... ----(e2e-specific config)
src/ --(source and support files for application)
my-lib/ --(a generated library)
... --(library-specific config)
@@ -173,7 +156,7 @@ my-workspace/
When you generate a library using the CLI (with a command such as `ng generate library my-lib`), the generated files go into the `projects/` folder of the workspace. For more information about creating your own libraries, see [Creating Libraries](guide/creating-libraries).
Libraries (unlike applications and their associated e2e projects) have their own `package.json` configuration file.
Libraries unlike applications have their own `package.json` configuration file.
Under the `projects/` folder, the `my-lib` folder contains your library code.
+14 -5
View File
@@ -1,10 +1,12 @@
# Angular Roadmap
<p class="roadmap-last-updated">Last updated: 2021-05-19</p>
Angular receives a large number of feature requests, both from inside Google and from the broader open-source community. At the same time, our list of projects contains plenty of maintenance tasks, code refactorings, and potential performance improvements. We bring together representatives from developer relations, product management, and engineering to prioritize this list. As new projects come into the queue, we regularly position them based on relative priority to other projects. As work gets done, projects will move up in the queue.
The projects below are not associated with a particular Angular version. We'll release them on completion, and they will be part of a specific version based on our release schedule, following semantic versioning. For example, features are released in the next minor after they are complete, or the next major if they include breaking changes.
## In Progress
## In progress
### Improve test times and debugging with automatic test environment tear down
@@ -80,10 +82,16 @@ A long-standing feature request is to add the ability to add directives to host
A common problem with web applications is their slow initial load time. A way to improve it is to apply more granular code-splitting on a component level. To encourage this practice, we’ll be working on more ergonomic code-splitting APIs.
<details class="roadmap-done-details" open="true">
<summary class="roadmap-done-summary">
<h2>Done</h2>
<details class="completed-details" open="true">
<summary>
<h2>Completed</h2>
<span class="actions">
<span class="action-expand">Show all</span>
<span class="action-collapse">Hide all</span>
<i class="material-icons expand">expand_more</i>
</span>
</summary>
<div class="details-content">
### Accelerated debugging and performance profiling with Angular DevTools
@@ -157,10 +165,11 @@ _Completed Q4 2020_
With the deprecation of TSLint we will be moving to ESLint. As part of the process, we will work on ensuring backward compatibility with our current recommended TSLint configuration, implement a migration strategy for existing Angular applications and introduce new tooling to the Angular CLI toolchain.
### Operation Bye Bye Backlog (aka Operation Byelog)
### Operation Bye Bye Backlog (aka Operation Byelog)
_Completed Q4 2020_
We are actively investing up to 50% of our engineering capacity on triaging issues and PRs until we have a clear understanding of broader community needs. After that, we'll commit up to 20% of our engineering capacity to keep up with new submissions promptly.
</div>
</details>
+1 -1
View File
@@ -2528,7 +2528,7 @@ Add the `NavigationExtras` object to the `router.navigate()` method that navigat
<code-example path="router/src/app/auth/auth.guard.4.ts" header="src/app/auth/auth.guard.ts (v3)"></code-example>
You can also preserve query parameters and fragments across navigations without having to provide them again when navigating.
In the `LoginComponent`, you'll add an *object* as the second argument in the `router.navigateUrl()` function and provide the `queryParamsHandling` and `preserveFragment` to pass along the current query parameters and fragment to the next route.
In the `LoginComponent`, you'll add an *object* as the second argument in the `router.navigate()` function and provide the `queryParamsHandling` and `preserveFragment` to pass along the current query parameters and fragment to the next route.
<code-example path="router/src/app/auth/login/login.component.ts" header="src/app/auth/login/login.component.ts (preserve)" region="preserve"></code-example>
+6 -1
View File
@@ -34,9 +34,14 @@ Before creating a route, you should be familiar with the following:
<p>Add more routing features to the Tour of Heroes tutorial.</p>
<p class="card-footer">Routing Tour of Heroes</p>
</a>
<a href="guide/routing-with-urlmatcher" class="docs-card" title="Creating custom route matches tutorial">
<section>Creating custom route matches tutorial</section>
<p>A tutorial that covers how to use custom matching strategy patterns with Angular routing.</p>
<p class="card-footer">Custom route matches tutorial</p>
</a>
<a href="guide/router-reference" class="docs-card" title="Router reference">
<section>Router reference</section>
<p>Describes some core router API concepts.</p>
<p class="card-footer">Router reference</p>
</a>
</div>
</div>
+56 -1
View File
@@ -59,6 +59,8 @@ To systematically block XSS bugs, Angular treats all values as untrusted by defa
Unlike values to be used for rendering, Angular templates are considered trusted by default, and should be treated as executable code. Never generate templates by concatenating user input and template syntax. Doing this would enable attackers to [inject arbitrary code](https://en.wikipedia.org/wiki/Code_injection) into your application. To prevent these vulnerabilities, always use the default [AOT template compiler](/guide/security#offline-template-compiler) in production deployments.
An additional layer of protection can be provided through the use of Content security policy and Trusted Types. These web platform features operate at the DOM level which is the most effective place to prevent XSS issues because they can't be bypassed using other, lower-level APIs. For this reason, we strongly encourage developers to take advantage of these features by configuring the [content security policy](#content-security-policy) for their application and enabling [trusted types enforcement](#trusted-types).
### Sanitization and security contexts
_Sanitization_ is the inspection of an untrusted value, turning it into a value that's safe to insert into
@@ -100,7 +102,7 @@ Angular recognizes the value as unsafe and automatically sanitizes it, which rem
### Direct use of the DOM APIs and explicit sanitization calls
Built-in browser DOM APIs don't automatically protect you from security vulnerabilities.
Unless you enforce Trusted Types, the built-in browser DOM APIs don't automatically protect you from security vulnerabilities.
For example, `document`, the node available through `ElementRef`, and many third-party APIs
contain unsafe methods. In the same way, if you interact with other libraries that manipulate
the DOM, you likely won't have the same automatic sanitization as with Angular interpolations.
@@ -169,6 +171,59 @@ technique to prevent XSS. To enable CSP, configure your web server to return an
[Web Fundamentals guide](https://developers.google.com/web/fundamentals/security/csp) on the
Google Developers website.
{@a trusted-types}
### Enforcing Trusted Types
We recommend the use of [Trusted Types](https://w3c.github.io/webappsec-trusted-types/dist/spec/) as a way to help secure your applications from cross-site scripting attacks. Trusted Types is a [web platform](https://en.wikipedia.org/wiki/Web_platform)
feature that can help you prevent cross-site scripting attacks by enforcing
safer coding practices. Trusted Types can also help simplify the auditing of application code.
<div class="callout is-helpful">
Trusted Types might not yet be available in all browsers your application targets. In the case your Trusted-Types-enabled application runs in a browser that doesn't support Trusted Types, the functionality of the application will be preserved, and your application will be guarded against XSS by way of Angular's DomSanitizer. See [caniuse.com/trusted-types](https://caniuse.com/trusted-types) for the current browser support.
</div>
To enforce Trusted Types for your application, you must configure your application's web server to emit HTTP headers with one of the following Angular policies:
* `angular` - This policy is used in security-reviewed code that is internal to Angular, and is required for Angular to function when Trusted Types are enforced. Any inline template values or content sanitized by Angular is treated as safe by this policy.
* `angular#unsafe-bypass` - This policy is used for applications that use any of the methods in Angular's [DomSanitizer](api/platform-browser/DomSanitizer) that bypass security, such as `bypassSecurityTrustHtml`. Any application that uses these methods must enable this policy.
* `angular#unsafe-jit` - This policy is used by the [JIT compiler](api/core/Compiler). You must enable this policy if your application interacts directly with the JIT compiler or is running in JIT mode using the [platform browser dynamic](api/platform-browser-dynamic/platformBrowserDynamic).
You should configure the HTTP headers for Trusted Types in the following locations:
* Production serving infrastructure
* Angular CLI (`ng serve`), using the `headers` property in the `angular.json` file, for local development and end-to-end testing
* Karma (`ng test`), using the `customHeaders` property in the `karma.config.js` file, for unit testing
The following is an example of a header specifically configured for Trusted Types and Angular:
<code-example language="html">
Content-Security-Policy: trusted-types angular; require-trusted-types-for 'script';
</code-example>
The following is an example of a header specifically configured for Trusted Types and Angular applications that use any of the methods in Angular's [DomSanitizer](api/platform-browser/DomSanitizer) that bypasses security.
<code-example language="html">
Content-Security-Policy: trusted-types angular angular#unsafe-bypass; require-trusted-types-for 'script';
</code-example>
The following is an example of a header specifically configured for Trusted Types and Angular applications using JIT:
<code-example language="html">
Content-Security-Policy: trusted-types angular angular#unsafe-jit; require-trusted-types-for 'script';
</code-example>
<div class="callout is-helpful">
<header>Community contributions</header>
To learn more about troubleshooting Trusted Type configurations, the following resource might be helpful:
[Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types](https://web.dev/trusted-types/#how-to-use-trusted-types)
</div>
{@a offline-template-compiler}
### Use the AOT template compiler
+1 -1
View File
@@ -344,6 +344,6 @@ After you've set up your application for testing, you may find the following tes
* [Basics of testing components](guide/testing-components-basics)&mdash;discover the basics of testing Angular components.
* [Component testing scenarios](guide/testing-components-scenarios)&mdash;read about the various kinds of component testing scenarios and use cases.
* [Testing attribute directives](guide/testing-attribute-directives)&mdash;learn about how to test your attribute directives.
* [Testing pipes](guide/testing-pipes)&mdash;find out how to test attribute directives.
* [Testing pipes](guide/testing-pipes)&mdash;find out how to test pipes.
* [Debugging tests](guide/test-debugging)&mdash;uncover common testing bugs.
* [Testing utility APIs](guide/testing-utility-apis)&mdash;get familiar with Angular testing features.
+1 -1
View File
@@ -140,7 +140,7 @@ See [Build target](#build-target) below for more information.
* The `architect/test` section overrides build-option defaults for test builds and supplies additional test-running defaults for the `ng test` command.
* The `architect/lint` section configures defaults for options of the `ng lint` command, which performs code analysis on project source files. The default linting tool for Angular is [TSLint](https://palantir.github.io/tslint/).
* The `architect/lint` section configures defaults for options of the `ng lint` command, which performs code analysis on project source files.
* The `architect/extract-i18n` section configures defaults for options of the `ng extract-i18n` command, which extracts marked message strings from source code and outputs translation files.
+10 -10
View File
@@ -55,13 +55,19 @@
"Podcasts": {
"order": 3,
"resources": {
"sdfjkdkfj": {
"adventures-in-angular": {
"desc": "Adventures in Angular is a weekly podcast dedicated to the Angular platform and related technologies, tools, languages, and practices.",
"logo": "",
"title": "Adventures in Angular",
"url": "https://devchat.tv/adv-in-angular/"
},
"sdlkfjsldfkj": {
"angular-show": {
"desc": "ng-conf's official all-Angular podcast.",
"logo": "",
"title": "The Angular Show",
"url": "https://www.spreaker.com/show/angular-show"
},
"angular-air": {
"desc": "Weekly video podcast hosted by Jeff Whelpley with all the latest and greatest happenings in the wild world of Angular.",
"logo": "",
"title": "AngularAir",
@@ -73,10 +79,10 @@
"title": "Angular Rocks",
"url": "https://angularrocks.com"
},
"sdlkfjsldfkz": {
"happy-angular": {
"desc": "A weekly German podcast for Angular on the go",
"logo": "",
"title": "Happy Angular Podcast",
"title": "Happy Angular",
"url": "https://happy-angular.de/"
},
"ngruair": {
@@ -84,12 +90,6 @@
"logo": "",
"title": "NgRuAir",
"url": "https://github.com/ngRuAir/ngruair"
},
"the-deep-dive": {
"desc": "The advanced web development podcast about Angular, RxJS, TypeScript and other technologies. English, audio only.",
"logo": "https://i.imgur.com/mmE5Feq.jpg",
"title": "The Deep Dive",
"url": "https://thedeepdive.simplecast.com"
}
}
}
-5
View File
@@ -202,11 +202,6 @@
"title": "Template reference variables",
"tooltip": "Introductory guide to referring to DOM elements within a template."
},
{
"url": "guide/inputs-outputs",
"title": "Inputs and Outputs",
"tooltip": "Introductory guide to sharing data between parent and child directives or components."
},
{
"url": "guide/svg-in-templates",
"title": "SVG as templates",
@@ -1,3 +1,36 @@
Angular's `<ng-template>` element defines a template that doesn't render anything by default.
Angular's `<ng-template>` element defines a template that is not rendered by default.
With `<ng-template>`, you can render the content manually for full control over how the content displays.
With `<ng-template>`, you can define template content that is only being rendered by Angular when you, whether directly or indirectly, specifically instruct it to do so, allowing you to have full control over how and when the content is displayed.
@usageNotes
### Structural Directives
One of the main uses for `<ng-template>` is to hold template content that will be used by [Structural directives](/guide/structural-directives). Those directives can add and remove copies of the template content based on their own logic.
When using the [structural directive shorthand](/guide/structural-directives#structural-directive-shorthand), Angular creates an `<ng-template>` element behind the scenes.
### TemplateRef
`<ng-template>` elements are represented as instances of the `TemplateRef` class.
To add copies of the template to the DOM, pass this object to the `ViewContainerRef` method `createEmbeddedView()`.
### Template Variables
`<ng-template>` elements can be referenced in templates using [standard template variables](/guide/template-reference-variables#how-angular-assigns-values-to-template-variables).
_This is how `<ng-template>` elements are used as `ngIf` else clauses._
Such template variables can be used in conjunction with `ngTemplateOutlet` directives to render the content defined inside `<ng-template>` tags.
### Querying
A [Query](/api/core/Query) (such as `ViewChild`) can find the `TemplateRef` associated to an `<ng-template>` element so that it can be used programmatically; for instance, to pass it to the `ViewContainerRef` method `createEmbeddedView()`.
### Context
Inside the `<ng-template>` tags you can reference variables present in the surrounding outer template.
Additionally, a context object can be associated with `<ng-template>` elements.
Such an object contains variables that can be accessed from within the template contents via template (`let` and `as`) declarations.
+7 -7
View File
@@ -219,6 +219,13 @@ The Phone XL price is over $700, so the **Notify Me** button appears on that pro
To make the **Notify Me** button work, the child component needs to notify and pass the data to the parent component.
The `ProductAlertsComponent` needs to emit an event when the user clicks **Notify Me** and the `ProductListComponent` needs to respond to the event.
<div class="alert is-helpful">
In new components, the Angular Generator includes an empty `constructor()`, the `OnInit` interface, and the `ngOnInit()` method.
Since these steps don't use them, the following code examples omit them for brevity.
</div>
1. In `product-alerts.component.ts`, import `Output` and `EventEmitter` from `@angular/core`.
<code-example header="src/app/product-alerts/product-alerts.component.ts" path="getting-started/src/app/product-alerts/product-alerts.component.ts" region="imports"></code-example>
@@ -228,13 +235,6 @@ The `ProductAlertsComponent` needs to emit an event when the user clicks **Notif
<code-example path="getting-started/src/app/product-alerts/product-alerts.component.ts" header="src/app/product-alerts/product-alerts.component.ts" region="input-output"></code-example>
<div class="alert is-helpful">
In new components, the Angular Generator includes an empty `constructor()`, the `OnInit` interface, and the `ngOnInit()` method.
Since these steps don't use them, the following code example omits them for brevity.
</div>
1. In `product-alerts.component.html`, update the **Notify Me** button with an event binding to call the `notify.emit()` method.
<code-example header="src/app/product-alerts/product-alerts.component.html" path="getting-started/src/app/product-alerts/product-alerts.component.html"></code-example>
+1
View File
@@ -30,6 +30,7 @@ This section walks you through adding a **Buy** button and setting up a cart ser
<code-example header="src/app/cart.service.ts" path="getting-started/src/app/cart.service.1.ts"></code-example>
1. Import the `Product` interface from `./products.js`.
1. In the `CartService` class, define an `items` property to store the array of the current products in the cart.
<code-example path="getting-started/src/app/cart.service.ts" header="src/app/cart.service.ts" region="props"></code-example>
+1 -1
View File
@@ -22,7 +22,7 @@ To set up your development environment, follow the instructions in [Local Enviro
## Create a new workspace and an initial application
You develop applications in the context of an Angular [workspace](guide/glossary#workspace). A workspace contains the files for one or more [projects](guide/glossary#project). A project is the set of files that comprise an app, a library, or end-to-end (e2e) tests. For this tutorial, you will create a new workspace.
You develop applications in the context of an Angular [workspace](guide/glossary#workspace). A workspace contains the files for one or more [projects](guide/glossary#project). A project is the set of files that comprise an application or a library. For this tutorial, you will create a new workspace.
To create a new workspace and an initial application project:
+15 -15
View File
@@ -86,27 +86,27 @@
},
"private": true,
"dependencies": {
"@angular/animations": "12.0.5",
"@angular/cdk": "12.0.5",
"@angular/common": "12.0.5",
"@angular/compiler": "12.0.5",
"@angular/core": "12.0.5",
"@angular/elements": "12.0.5",
"@angular/forms": "12.0.5",
"@angular/material": "12.0.5",
"@angular/platform-browser": "12.0.5",
"@angular/platform-browser-dynamic": "12.0.5",
"@angular/router": "12.0.5",
"@angular/service-worker": "12.0.5",
"@angular/animations": "12.1.1",
"@angular/cdk": "12.1.1",
"@angular/common": "12.1.1",
"@angular/compiler": "12.1.1",
"@angular/core": "12.1.1",
"@angular/elements": "12.1.1",
"@angular/forms": "12.1.1",
"@angular/material": "12.1.1",
"@angular/platform-browser": "12.1.1",
"@angular/platform-browser-dynamic": "12.1.1",
"@angular/router": "12.1.1",
"@angular/service-worker": "12.1.1",
"@webcomponents/custom-elements": "1.4.3",
"rxjs": "^6.6.7",
"tslib": "^2.2.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "12.0.4",
"@angular/cli": "12.0.4",
"@angular/compiler-cli": "12.0.5",
"@angular-devkit/build-angular": "12.1.1",
"@angular/cli": "12.1.1",
"@angular/compiler-cli": "12.1.1",
"@swc/cli": "^0.1.36",
"@swc/core": "^1.2.51",
"@types/jasmine": "~3.7.0",
+1 -1
View File
@@ -28,7 +28,7 @@
<div class="content">
<div class="nf-container l-flex-wrap flex-center">
<img src="assets/images/support/angular-404.svg" width="300" height="300" />
<div class="nf-response l-flex-wrap">
<div class="nf-response l-flex-wrap center">
<h1 class="no-toc" id="page-not-found">Resource Not Found</h1>
<p>We're sorry. The resource you are looking for cannot be found.</p>
</div>
+5 -5
View File
@@ -46,7 +46,7 @@
<mat-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
<mat-sidenav [ngClass]="{'collapsed': !dockSideNav}" #sidenav class="sidenav" [mode]="mode" [opened]="isOpened" (openedChange)="updateHostClasses()">
<aio-nav-menu *ngIf="!showTopMenu" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="false"></aio-nav-menu>
<aio-nav-menu *ngIf="!showTopMenu" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow" [isWide]="dockSideNav"></aio-nav-menu>
<aio-nav-menu [nodes]="sideNavNodes" [currentNode]="currentNodes?.SideNav" [isWide]="dockSideNav"></aio-nav-menu>
<div class="doc-version">
@@ -61,11 +61,11 @@
<aio-dt *ngIf="dtOn" [(doc)]="currentDocument"></aio-dt>
</main>
</mat-sidenav-container>
<div *ngIf="hasFloatingToc" class="toc-container no-print" [style.max-height.px]="tocMaxHeight" (wheel)="restrainScrolling($event)">
<aio-lazy-ce selector="aio-toc"></aio-lazy-ce>
</div>
<div *ngIf="hasFloatingToc" class="toc-container no-print" [style.max-height.px]="tocMaxHeight" (wheel)="restrainScrolling($event)">
<aio-lazy-ce selector="aio-toc"></aio-lazy-ce>
</div>
</mat-sidenav-container>
<footer class="no-print">
<aio-footer [nodes]="footerNodes" [versionInfo]="versionInfo"></aio-footer>
+2 -2
View File
@@ -14,7 +14,7 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
const sideNavView = 'SideNav';
export const showTopMenuWidth = 1048;
export const showTopMenuWidth = 1150;
export const dockSideNavWidth = 992;
export const showFloatingTocWidth = 800;
@@ -79,7 +79,7 @@ export class AppComponent implements OnInit {
private currentUrl: string;
get isOpened() { return this.dockSideNav && this.isSideNavDoc; }
get mode() { return this.dockSideNav && (this.isSideNavDoc || this.showTopMenu) ? 'side' : 'over'; }
get mode() { return this.isOpened ? 'side' : 'over'; }
// Search related properties
showSearchResults = false;
@@ -30,7 +30,7 @@ export class ApiService implements OnDestroy {
private apiBase = DOC_CONTENT_URL_PREFIX + 'api/';
private apiListJsonDefault = 'api-list.json';
private firstTime = true;
private onDestroy = new Subject();
private onDestroy = new Subject<void>();
private sectionsSubject = new ReplaySubject<ApiSection[]>(1);
private _sections = this.sectionsSubject.pipe(takeUntil(this.onDestroy));
@@ -8,7 +8,9 @@ import { SearchService } from 'app/search/search.service';
@Component({
selector: 'aio-file-not-found-search',
template:
`<p>Let's see if any of these search results help...</p>
`<div class="alert is-helpful">
<p>Let's see if any of these search results help...</p>
</div>
<aio-search-results class="embedded" [searchResults]="searchResults | async"></aio-search-results>`
})
export class FileNotFoundSearchComponent implements OnInit {
@@ -19,7 +19,7 @@ export class TocComponent implements OnInit, AfterViewInit, OnDestroy {
isCollapsed = true;
isEmbedded = false;
@ViewChildren('tocItem') private items: QueryList<ElementRef>;
private onDestroy = new Subject();
private onDestroy = new Subject<void>();
primaryMax = 4;
tocList: TocItem[];
+10 -7
View File
@@ -70,13 +70,16 @@ describe('DocumentService', () => {
it('should encode the request path to be case-insensitive', () => {
const { docService, locationService } = getServices('initial/Doc');
docService.currentDocument.subscribe();
httpMock.expectOne(CONTENT_URL_PREFIX + 'initial/d_oc.json').flush({});
locationService.go('NEW/Doc');
httpMock.expectOne(CONTENT_URL_PREFIX + 'n_e_w_/d_oc.json').flush({});
locationService.go('doc_with_underscores');
httpMock.expectOne(CONTENT_URL_PREFIX + 'doc__with__underscores.json').flush({});
locationService.go('DOC_WITH_UNDERSCORES');
httpMock.expectOne(CONTENT_URL_PREFIX + 'd_o_c___w_i_t_h___u_n_d_e_r_s_c_o_r_e_s_.json').flush({});
expect(() => {
httpMock.expectOne(CONTENT_URL_PREFIX + 'initial/d_oc.json').flush({});
locationService.go('NEW/Doc');
httpMock.expectOne(CONTENT_URL_PREFIX + 'n_e_w_/d_oc.json').flush({});
locationService.go('doc_with_underscores');
httpMock.expectOne(CONTENT_URL_PREFIX + 'doc__with__underscores.json').flush({});
locationService.go('DOC_WITH_UNDERSCORES');
httpMock.expectOne(CONTENT_URL_PREFIX + 'd_o_c___w_i_t_h___u_n_d_e_r_s_c_o_r_e_s_.json').flush({});
}).not.toThrow();
});
it('should emit the not-found document if the document is not found on the server', () => {
+3 -2
View File
@@ -18,10 +18,11 @@ export const DOC_CONTENT_URL_PREFIX = CONTENT_URL_PREFIX + 'docs/';
const FETCHING_ERROR_CONTENTS = (path: string) => `
<div class="nf-container l-flex-wrap flex-center">
<div class="nf-icon material-icons">error_outline</div>
<div class="nf-response l-flex-wrap">
<h1 class="no-toc">Request for document failed.</h1>
<div class="nf-response l-flex-wrap center">
<h1 class="no-toc">Request for document failed</h1>
<p>
We are unable to retrieve the "${path}" page at this time.
<br/>
Please check your connection and try again later.
</p>
</div>
@@ -260,10 +260,13 @@ export class DocViewerComponent implements OnDestroy {
* (See https://github.com/angular/angular/issues/28114.)
*/
async function printSwDebugInfo(): Promise<void> {
console.log(`\nServiceWorker: ${navigator.serviceWorker?.controller?.state ?? 'N/A'}`);
const sep = '\n----------';
const swState = navigator.serviceWorker?.controller?.state ?? 'N/A';
console.log(`\nServiceWorker: ${swState}`);
if (typeof caches === 'undefined') {
console.log('\nCaches: N/A');
console.log(`${sep}\nCaches: N/A`);
} else {
const allCacheNames = await caches.keys();
const swCacheNames = allCacheNames.filter(name => name.startsWith('ngsw:/:'));
@@ -273,11 +276,28 @@ async function printSwDebugInfo(): Promise<void> {
await findCachesAndPrintEntries(swCacheNames, 'assets:app-shell:meta', true);
}
if (swState === 'activated') {
console.log(sep);
await fetchAndPrintSwInternalDebugInfo();
}
console.warn(
'\nIf you see this error, please report an issue at ' +
`${sep}\nIf you see this error, please report an issue at ` +
'https://github.com/angular/angular/issues/new?template=3-docs-bug.md including the above logs.');
// Internal helpers
async function fetchAndPrintSwInternalDebugInfo() {
try {
const res = await fetch('/ngsw/state');
if (!res.ok) {
throw new Error(`Response ${res.status} ${res.statusText}`);
}
console.log(await res.text());
} catch (err) {
console.log(`Failed to retrieve debug info from '/ngsw/state': ${err.message || err}`);
}
}
async function findCachesAndPrintEntries(
swCacheNames: string[], nameSuffix: string, includeValues: boolean,
ignoredKeys: string[] = []): Promise<void> {
@@ -23,7 +23,7 @@ export class NotificationComponent implements OnInit {
@Input() dismissOnContentClick: boolean;
@Input() notificationId: string;
@Input() expirationDate: string;
@Output() dismissed = new EventEmitter();
@Output() dismissed = new EventEmitter<void>();
@HostBinding('@hideAnimation')
showNotification: 'show'|'hide';
@@ -56,10 +56,40 @@ describe('ReportingErrorHandler service', () => {
expect(onerrorSpy).toHaveBeenCalledWith(error.message, undefined, undefined, undefined, error);
});
it('should send a non-error object to window.onerror', () => {
const error = {reason: 'this is an error message'};
handler.handleError(error);
expect(onerrorSpy).toHaveBeenCalledWith(JSON.stringify(error));
});
it('should send a non-error object with circular references to window.onerror', () => {
const error = {
reason: 'this is an error message',
get self() { return this; },
toString() { return `{reason: ${this.reason}}`; },
};
handler.handleError(error);
expect(onerrorSpy).toHaveBeenCalledWith('{reason: this is an error message}');
});
it('should send an error string to window.onerror', () => {
const error = 'this is an error message';
handler.handleError(error);
expect(onerrorSpy).toHaveBeenCalledWith(error);
});
it('should send a non-object, non-string error stringified to window.onerror', () => {
handler.handleError(404);
handler.handleError(false);
handler.handleError(null);
handler.handleError(undefined);
expect(onerrorSpy.calls.allArgs()).toEqual([
['404'],
['false'],
['null'],
['undefined'],
]);
});
});
});
+12 -6
View File
@@ -17,8 +17,7 @@ export class ReportingErrorHandler extends ErrorHandler {
* Send error info to Google Analytics, in addition to the default handling.
* @param error Information about the error.
*/
handleError(error: string | Error) {
handleError(error: any) {
try {
super.handleError(error);
} catch (e) {
@@ -27,12 +26,19 @@ export class ReportingErrorHandler extends ErrorHandler {
this.reportError(error);
}
private reportError(error: string | Error) {
private reportError(error: unknown) {
if (this.window.onerror) {
if (typeof error === 'string') {
this.window.onerror(error);
} else {
if (error instanceof Error) {
this.window.onerror(error.message, undefined, undefined, undefined, error);
} else {
if (typeof error === 'object') {
try {
error = JSON.stringify(error);
} catch {
// Ignore the error and just let it be stringified.
}
}
this.window.onerror(`${error}`);
}
}
}
+1 -1
View File
@@ -118,7 +118,7 @@ export class ScrollSpiedElementGroup {
@Injectable()
export class ScrollSpyService {
private spiedElementGroups: ScrollSpiedElementGroup[] = [];
private onStopListening = new Subject();
private onStopListening = new Subject<void>();
private resizeEvents = fromEvent(window, 'resize').pipe(auditTime(300), takeUntil(this.onStopListening));
private scrollEvents = fromEvent(window, 'scroll').pipe(auditTime(10), takeUntil(this.onStopListening));
private lastContentHeight: number;
+1 -1
View File
@@ -69,7 +69,7 @@
function formatError(msg, url, line, col, e) {
var stack;
msg = msg.replace(/^Error: /, '');
if (e) {
if (e && e.stack) {
stack = e.stack
// strip the leading "Error: " from the stack trace
.replace(/^Error: /, '')
@@ -9,12 +9,13 @@
mat-sidenav-container.sidenav-container {
min-height: 100%;
height: auto !important;
max-width: 100%;
margin: 0;
transform: none;
&.has-floating-toc {
max-width: 82%;
.mat-sidenav-content {
margin-right: 18vw;
}
}
.sidenav-content {
@@ -1,7 +1,7 @@
@use '../../mixins';
// VARIABLES
$showTopMenuWidth: 1048px;
$showTopMenuWidth: 1150px;
$hideTopMenuWidth: $showTopMenuWidth - 1;
$hamburgerShownMargin: 0 8px 0 0;
$hamburgerHiddenMargin: 0 16px 0 -64px;
@@ -132,7 +132,10 @@ mat-toolbar.app-toolbar {
.nav-link-inner {
border-radius: 4px;
font-size: 1.3rem;
font-size: clamp(10px, 1.6rem, 20px);
padding: 8px 16px;
padding: 8px clamp(5px, 0.7vw, 16px);
}
&:focus {
@@ -183,7 +186,7 @@ mat-toolbar.app-toolbar {
}
}
@media (max-width: 480px) {
@media (max-width: 515px) {
width: 150px;
}
}
@@ -200,11 +203,7 @@ mat-toolbar.app-toolbar {
.toolbar-external-icons-container {
a {
@media screen and (max-width: 480px) {
margin: 0;
&:not(:first-child) {
margin-left: -8px;
}
margin: 0 -8px 0 0;
}
@media screen and (max-width: 420px) {
-254
View File
@@ -1,254 +0,0 @@
@use 'sass:color';
@use '../constants';
@use '../mixins';
code-example,
code-tabs {
clear: both;
display: block;
code {
overflow: auto;
}
ol {
list-style: decimal;
}
.mat-card {
padding: 0;
border-radius: 5px;
}
}
code-example {
&:not(.no-box) {
background-color: rgba($backgroundgray, 0.2);
border: 0.5px solid $lightgray;
border-radius: 5px;
color: $darkgray;
margin: 16px auto;
}
&.no-box {
pre.prettyprint {
margin: 0;
}
code {
background-color: transparent;
}
}
code {
overflow: auto;
}
// TERMINAL / SHELL TEXT STYLES
&[language=sh], &[language=bash] {
background-color: $darkgray;
}
header {
background-color: $accentblue;
border-radius: 5px 5px 0 0;
color: $offwhite;
@include mixins.font-size(16);
padding: 8px 16px;
}
}
code-tabs {
margin: 16px 0;
.code-tab-group {
.mat-tab-label {
&:hover {
background: rgba(black, 0.04);
}
}
.mat-tab-body {
overflow-y: hidden;
.mat-tab-body-content {
height: auto;
transform: none;
.fadeIn {
animation: opacity 2s ease-in;
}
}
}
}
}
code-example.avoid header,
code-example.avoidFile header {
border: 2px solid $anti-pattern;
background: $anti-pattern;
}
code-example.avoid,
code-example.avoidFile,
code-tabs.avoid mat-tab-body,
code-tabs.avoidFile mat-tab-body {
border: 0.5px solid $anti-pattern;
}
aio-code {
pre.prettyprint {
position: relative;
display: flex;
min-height: 32px;
margin: 16px 24px;
white-space: pre-wrap;
align-items: center;
code {
a {
color: inherit;
}
span {
@include mixins.line-height(24);
}
ol.linenums {
margin: 0;
color: color.adjust($mediumgray, $lightness: 25%);
li {
margin: 0;
font-family: $code-font;
font-size: 90%;
@include mixins.line-height(24);
&::marker {
color: color.adjust($mediumgray, $lightness: 25%);
}
}
}
.code-missing {
color: $darkred;
}
}
.copy-button {
position: absolute;
top: -7px;
right: -19px;
padding: 0;
overflow: visible; // This is required for the button to be displayed correctly in IE11.
color: $blue-grey-200;
background-color: transparent;
border: none;
cursor: pointer;
&:hover {
color: $mediumgray;
}
}
&.lang-sh, &.lang-bash {
.copy-button {
color: $mediumgray;
&:hover {
color: $lightgray;
}
}
}
}
}
.sidenav-content {
code {
a {
color: $darkblue;
font-size: inherit;
font-weight: inherit;
}
}
:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(pre) {
> code {
background-color: rgba($lightgray, 0.3);
border-radius: 4px;
color: $deepgray;
padding: 0 4px;
}
&:not(a) > code {
padding: 4px;
}
}
.page-guide-cheatsheet & {
td:first-of-type,
th {
code {
background-color: inherit;
padding: 0;
white-space: pre-wrap;
}
}
}
.code-anchor {
cursor: pointer;
text-decoration: none;
font-size: inherit;
&:hover {
text-decoration: underline;
}
}
}
/* PRETTY PRINTING STYLES for prettify.js. */
/* The following class|color styles are derived from https://github.com/google/code-prettify/blob/master/src/prettify.css*/
/* SPAN elements with the classes below are added by prettyprint. */
.pln { color: #000 } /* plain text */
@media screen {
.str { color: #800 } /* string content */
.kwd { color: #00f } /* a keyword */
.com { color: #060 } /* a comment */
.typ { color: red } /* a type name */
.lit { color: #08c } /* a literal value */
/* punctuation, lisp open bracket, lisp close bracket */
.pun, .opn, .clo { color: #660 }
.tag { color: #008 } /* a markup tag name */
.atn { color: #606 } /* a markup attribute name */
.atv { color: #800 } /* a markup attribute value */
.dec, .var { color: #606 } /* a declaration; a variable name */
.fun { color: red } /* a function name */
}
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str { color: #060 }
.kwd { color: #006; font-weight: bold }
.com { color: #600; font-style: italic }
.typ { color: #404; font-weight: bold }
.lit { color: #044 }
.pun, .opn, .clo { color: #440 }
.tag { color: #006; font-weight: bold }
.atn { color: #404 }
.atv { color: #060 }
}
/* SHELL / TERMINAL CODE BLOCKS */
code-example {
&[language=sh], &[language=bash] {
.pnk, .blk, .pln, .otl, .kwd, .typ, .tag, .str, .atv, .atn, .com, .lit, .pun, .dec {
color: $codegreen;
}
}
}
@@ -10,53 +10,23 @@
details.overloads {
box-shadow: none;
.icon-action-header {
display: flex;
flex-direction: row;
align-items: center;
> summary {
justify-content: space-between;
a {
display: flex;
}
}
.detail-contents {
padding: 0;
border-radius: 2px;
box-shadow: none;
> *:not(hr) {
margin: 16px 24px;
}
}
summary {
height: inherit;
padding: 0;
h4 {
margin: 0;
clear: left;
}
.actions {
display: flex;
@include mixins.font-size(14);
}
.show-all {
display: initial;
}
.collapse-all {
display: none;
}
}
&[open] > summary {
.show-all {
display: none;
}
.collapse-all {
display: initial;
> .details-content {
padding: 0;
border-radius: 2px;
box-shadow: none;
> *:not(hr) {
margin: 16px 24px;
}
}
}
@@ -1,7 +1,7 @@
.cli-name {
font-weight: bold;
.kwd { color: initial } /* override code format */
.kwd { color: inherit; } /* override code format */
}
.cli-option-syntax {
@@ -13,7 +13,6 @@
}
// TERMINAL / SHELL TEXT STYLES
&.code-shell,
&[language="sh"],
&[language="bash"] {
background-color: constants.$darkgray;
@@ -96,7 +95,7 @@
:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(pre) {
> code {
background-color: if($is-dark-theme, constants.$darkgray, rgba(constants.$lightgray, 0.5));
background-color: if($is-dark-theme, constants.$darkgray, rgba(constants.$lightgray, 0.3));
color: if($is-dark-theme, constants.$white, constants.$darkgray);
}
}
@@ -200,7 +199,6 @@
/* SHELL / TERMINAL CODE BLOCKS */
code-example {
&.code-shell,
&[language="sh"],
&[language="bash"] {
.pnk,
@@ -1,3 +1,4 @@
@use 'sass:math';
@use '~@angular/cdk' as cdk;
@use '~@angular/material' as mat;
@@ -12,13 +13,13 @@ aio-cookies-popup {
position: fixed;
margin: 24px;
max-width: 430px;
padding: $inner-spacing $inner-spacing $inner-spacing / 2;
padding: $inner-spacing $inner-spacing math.div($inner-spacing, 2);
z-index: cdk.$overlay-container-z-index + 1;
.actions {
display: flex;
justify-content: flex-end;
margin: $inner-spacing $inner-spacing / -2 0 0;
margin: $inner-spacing math.div($inner-spacing, -2) 0 0;
.mat-button {
text-transform: uppercase;
@@ -3,9 +3,5 @@
@mixin theme($theme) {
details {
box-shadow: 0 1px 4px 0 rgba(constants.$black, 0.37);
> summary {
color: constants.$black;
}
}
}
+50 -13
View File
@@ -14,6 +14,19 @@
* </div>
* </details>
* ```
*
* Optionally, you can use an `.actions` container inside `<summary>` to show expand/collapse
* actions and/or a rotating icon:
* ```html
* <summary>
* <span>Some title</span>
* <span class="actions">
* <span class="action-expand">Show more</span>
* <span class="action-collapse">Show less</span>
* <i class="material-icons expand">expand_more</i>
* </span>
* </summary>
* ```
*/
details {
@@ -21,33 +34,57 @@ details {
cursor: pointer;
@include mixins.font-size(16);
position: relative;
padding: 16px 24px;
height: 16px;
display: block; // Remove the built in details marker in FF
padding: 16px;
height: inherit;
display: flex; // Remove the built in details marker in FF
align-items: center;
overflow: hidden;
&::-webkit-details-marker {
display: none; // Remove the built in details marker in webkit
}
// Rotate the icon
i.material-icons.expand {
@include mixins.rotate(0deg);
@at-root #{selector.replace(&, 'details', 'details[open]')} {
@include mixins.rotate(180deg);
}
}
> h2 {
margin: 0;
padding: 0;
border: none;
display: inline;
}
.actions {
align-items: center;
display: flex;
@include mixins.font-size(14);
// Show/hide expand and collapse actions.
.action-expand {
display: initial;
@at-root #{selector.replace(&, 'details', 'details[open]')} {
display: none;
}
}
.action-collapse {
display: none;
@at-root #{selector.replace(&, 'details', 'details[open]')} {
display: initial;
}
}
// Rotate the expand/collapse icon.
.material-icons.expand {
@include mixins.rotate(0deg);
@at-root #{selector.replace(&, 'details', 'details[open]')} {
@include mixins.rotate(180deg);
}
}
}
}
.detail-contents {
.details-content {
padding: 16px 24px;
}
}
@@ -1,11 +1,12 @@
@use 'sass:color';
@use 'sass:map';
@use '../../constants';
@mixin theme($theme) {
$is-dark-theme: map.get($theme, is-dark);
.roadmap-done-summary::marker {
color: if($is-dark-theme, constants.$offwhite, color.adjust(constants.$darkgray, $lightness: 10%));
.page-guide-roadmap {
.completed-details {
border-top: 1px solid if($is-dark-theme, constants.$mediumgray, constants.$lightgray);
}
}
}
+18 -11
View File
@@ -1,13 +1,20 @@
.roadmap-done-details {
padding: 0 20px 20px;
margin: 0 -20px;
}
.page-guide-roadmap {
.completed-details {
box-shadow: none;
margin-top: 4rem;
padding: 4rem 0 2rem;
.roadmap-done-summary {
margin: 0 -20px;
font-size: 3.2rem;
height: 40px;
padding-bottom: 0;
display: list-item;
user-select: none;
> summary {
justify-content: space-between;
padding: 0;
}
> .details-content {
padding: 0;
}
}
.roadmap-last-updated {
font-style: italic;
}
}
+9 -8
View File
@@ -1,3 +1,4 @@
@use 'sass:math';
@use '../../mixins';
$tocItemLineHeight: 24;
@@ -9,15 +10,15 @@ $tocMarkerSize: 6;
border-radius: 50%;
content: "";
height: #{$tocMarkerSize}px;
left: -#{($tocMarkerSize - $tocMarkerRailSize) / 2}px;
left: -#{math.div($tocMarkerSize - $tocMarkerRailSize, 2)}px;
position: absolute;
top: calc(#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2}px - #{$tocMarkerSize / 2}px);
top: calc(#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2 / 10}rem - #{$tocMarkerSize / 2}px);
top: calc(#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2)}px - #{math.div($tocMarkerSize, 2)}px);
top: calc(#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2 * 10)}rem - #{math.div($tocMarkerSize, 2)}px);
width: #{$tocMarkerSize}px;
}
.toc-container {
width: 18%;
width: 18vw;
position: fixed;
top: 76px;
right: 0;
@@ -158,13 +159,13 @@ aio-toc {
}
&:first-child:before {
top: calc(#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2}px - #{$tocMarkerSize / 2}px);
top: calc(#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2 / 10}rem - #{$tocMarkerSize / 2}px);
top: calc(#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2)}px - #{math.div($tocMarkerSize, 2)}px);
top: calc(#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2 * 10)}rem - #{math.div($tocMarkerSize, 2)}px);
}
&:last-child:before {
bottom: calc(100% - (#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2}px + #{$tocMarkerSize / 2}px));
bottom: calc(100% - (#{$tocItemTopPadding}px + #{$tocItemLineHeight / 2 / 10}rem + #{$tocMarkerSize / 2}px));
bottom: calc(100% - (#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2)}px + #{math.div($tocMarkerSize, 2)}px));
bottom: calc(100% - (#{$tocItemTopPadding}px + #{math.div($tocItemLineHeight, 2 * 10)}rem + #{math.div($tocMarkerSize, 2)}px));
}
&:not(.active):hover {
+4 -3
View File
@@ -1,21 +1,22 @@
@use 'sass:list';
@use 'sass:math';
@use 'sass:selector';
@use './constants';
// REM Font Adjustments
@mixin font-size($sizeValue) {
font-size: ($sizeValue) + px;
font-size: ($sizeValue / 10) + rem;
font-size: math.div($sizeValue, 10) + rem;
}
@mixin letter-spacing($spacingValue) {
letter-spacing: ($spacingValue) + px;
letter-spacing: ($spacingValue / 10) + rem;
letter-spacing: math.div($spacingValue, 10) + rem;
}
@mixin line-height($heightValue) {
line-height: ($heightValue) + px;
line-height: ($heightValue / 10) + rem;
line-height: math.div($heightValue, 10) + rem;
}
// PLACEHOLDER
+3 -1
View File
@@ -5,7 +5,9 @@ describe('site App', () => {
let page: SitePage;
beforeEach(async () => {
await SitePage.setWindowWidth(1050); // Make the window wide enough to show the SideNav side-by-side.
// Make the window wide enough to show the SideNav side-by-side
// (bigger than the app component's showTopMenuWidth).
await SitePage.setWindowWidth(1200);
page = new SitePage();
});
+24 -8
View File
@@ -25,9 +25,15 @@ const IGNORED_EXAMPLES = [];
* Run Protractor End-to-End Tests for Doc Samples
*
* Flags
* --filter to filter/select _example app subdir names
* --filter to filter/select example app subdir names
* Can be used multiple times to include multiple patterns.
* e.g. --filter=foo // all example apps with 'foo' in their folder names.
*
* --exclude to exclude example app subdir names
* Can be used multiple times to exclude multiple patterns.
* NOTE: `--exclude` is always cosidered after `--filter`.
* e.g. --exclude=bar // Exclude all example apps with 'bar' in their folder names.
*
* --setup to run yarn install, copy boilerplate and update webdriver
* e.g. --setup
*
@@ -60,7 +66,7 @@ function runE2e() {
return Promise.resolve()
.then(
() => findAndRunE2eTests(
argv.filter, outputFile, argv.shard,
argv.filter, argv.exclude, outputFile, argv.shard,
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
.then((status) => {
reportStatus(status, outputFile);
@@ -76,7 +82,9 @@ function runE2e() {
// Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps
// that they should run under. Then run each app/spec collection sequentially.
function findAndRunE2eTests(filter, outputFile, shard, cliSpecsConcurrency, maxAttempts) {
function findAndRunE2eTests(
includeFilter, excludeFilter, outputFile, shard, cliSpecsConcurrency, maxAttempts) {
const filter = {include: includeFilter, exclude: excludeFilter};
const shardParts = shard ? shard.split('/') : [0, 1];
const shardModulo = parseInt(shardParts[0], 10);
const shardDivider = parseInt(shardParts[1], 10);
@@ -84,7 +92,8 @@ function findAndRunE2eTests(filter, outputFile, shard, cliSpecsConcurrency, maxA
// create an output file with header.
const startTime = new Date().getTime();
let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`;
header += ` Filter: ${filter ? filter : 'All tests'}\n\n`;
header += ` Include: ${filter.include || 'All tests'}\n`;
header += ` Exclude: ${filter.exclude || 'No tests'}\n\n`;
fs.writeFileSync(outputFile, header);
const status = {passed: [], failed: []};
@@ -378,16 +387,23 @@ function getE2eSpecs(basePath, filter) {
// Find all e2e specs in a given example folder.
function getE2eSpecsFor(basePath, specFile, filter) {
// Only get spec file at the example root.
// The formatter doesn't understand nested template string expressions (honestly, neither do I).
// clang-format off
const e2eSpecGlob = `${filter ? `*${filter}*` : '*'}/${specFile}`;
// clang-format on
const e2eSpecGlob = [
`${filter.include ? filterToGlob(filter.include) : '*'}/${specFile}`,
`!${filter.exclude ? filterToGlob(filter.exclude) : ''}/${specFile}`,
];
return globby(e2eSpecGlob, {cwd: basePath, nodir: true})
.then(
paths => paths.filter(file => !IGNORED_EXAMPLES.some(ignored => file.startsWith(ignored)))
.map(file => path.join(basePath, file)));
}
function filterToGlob(filter) {
// `filter` can be either a string (if there is one occurrence of the corresponding option) or an
// array (if there are two or more occurrences of the corresponding option). In other words, if
// `filter` is an array, it will have more than one element.
return Array.isArray(filter) ? `*{${filter.join(',')}}*` : `*${filter}*`;
}
// Load configuration for an example. Used for SystemJS
function loadExampleConfig(exampleFolder) {
// Default config.
@@ -2,7 +2,7 @@
<section class="description">
<h2>Description</h2>
{$ doc.description | trimBlankLines | marked $}
{% if doc.usageNotes %}<p>Further information available in the <a href="#usage-notes">Usage Notes</a>...</p>{%
{% if doc.usageNotes %}<p>Further information is available in the <a href="#usage-notes">Usage Notes...</a></p>{%
endif %}
</section>
{% endif %}
@@ -130,16 +130,14 @@
<td>
<details class="overloads">
<summary>
<div class="icon-action-header">
<h4 class="no-anchor">{$ method.overloads.length $} overloads...</h4>
<span class="actions">
<span class="show-all">Show All</span>
<span class="collapse-all">Hide All</span>
<i class="material-icons expand">expand_more</i>
</span>
</div>
<h4 class="no-anchor">{$ method.overloads.length $} overloads...</h4>
<span class="actions">
<span class="action-expand">Show All</span>
<span class="action-collapse">Hide All</span>
<i class="material-icons expand">expand_more</i>
</span>
</summary>
<div class="detail-contents">
<div class="details-content">
{% if method.isAbstract %}
{$ renderOverloadInfo(method, cssClass + '-overload', method) $}
<hr class="hr-margin fullwidth">
+498 -592
View File
File diff suppressed because it is too large Load Diff
+17 -4
View File
@@ -1,13 +1,16 @@
# BEGIN-INTERNAL
load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//dev-infra:index.bzl", "ng_dev_rolled_up_generated_file")
load("//dev-infra:defaults.bzl", "ng_dev_rolled_up_generated_file", "ts_library")
# END-INTERNAL
exports_files(["tsconfig.json"])
# BEGIN-INTERNAL
ts_library(
name = "cli",
srcs = [
"cli.ts",
],
module_name = "@angular/dev-infra-private",
deps = [
"//dev-infra/caretaker",
"//dev-infra/commit-message",
@@ -42,20 +45,28 @@ genrule(
pkg_npm(
name = "npm_package",
srcs = [
# Main bazel entry-point for the shared `dev-infra` package.
"index.bzl",
"BUILD.bazel",
# Some tools within `dev-infra` which are shipped as Bazel rules might
# rely on a tsconfig file. We bring the config into the NPM package.
"tsconfig.json",
"//dev-infra/bazel:files",
"//dev-infra/benchmark:files",
],
substitutions = {
# angular/angular should not consume it's own packages, so we use
# substitutions to replace these in the published version of dev-infra.
"@angular//dev-infra/": "@npm//@angular/dev-infra-private/",
"//dev-infra/": "@npm//@angular/dev-infra-private/",
"//dev-infra:": "@npm//@angular/dev-infra-private:",
# Substitutions needed for `//dev-infra/benchmark`:
"//packages/benchpress": "@npm//@angular/benchpress",
"//packages/bazel": "@npm//@angular/bazel",
"//packages/zone.js/bundles:zone.umd.js": "@npm//zone.js",
"//packages/core": "@npm//@angular/core",
"//packages/platform-browser": "@npm//@angular/platform-browser",
# This substitution is particularly verbose because we need to make sure
# that only things available via Angular Bazel are imported from
# tools/defaults.bzl.
@@ -68,6 +79,7 @@ pkg_npm(
"//dev-infra/benchmark/driver-utilities",
"//dev-infra/commit-message",
"//dev-infra/ts-circular-dependencies",
"//dev-infra/tslint-rules",
],
)
@@ -101,3 +113,4 @@ ng_dev_rolled_up_generated_file(
"//dev-infra/release/build",
],
)
# END-INTERNAL
+2
View File
@@ -5,6 +5,8 @@ filegroup(
srcs = [
"BUILD.bazel",
"expand_template.bzl",
"extract_js_module_output.bzl",
"//dev-infra/bazel/api-golden:files",
"//dev-infra/bazel/browsers:files",
"//dev-infra/bazel/remote-execution:files",
],
+35
View File
@@ -0,0 +1,35 @@
load("@npm//@bazel/typescript:index.bzl", "ts_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"index.ts",
"index_npm_packages.ts",
])
ts_library(
name = "api-golden",
srcs = [
"find_entry_points.ts",
"index.ts",
"index_npm_packages.ts",
"test_api_report.ts",
],
# A tsconfig needs to be specified as otherwise `ts_library` will look for the config
# in `//:package.json` and this breaks when the BUILD file is copied to `@npm//`.
tsconfig = "//dev-infra:tsconfig.json",
deps = [
"@npm//@bazel/runfiles",
"@npm//@microsoft/api-extractor",
"@npm//@types/node",
"@npm//chalk",
"@npm//tslib",
"@npm//typescript",
],
)
# Expose the sources in the dev-infra NPM package.
filegroup(
name = "files",
srcs = glob(["*"]),
)
@@ -0,0 +1,62 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {lstatSync, readdirSync, readFileSync} from 'fs';
import {dirname, join} from 'path';
/** Interface describing a resolved NPM package entry point. */
export interface PackageEntryPoint {
typesEntryPointPath: string;
packageJsonPath: string;
}
/** Interface describing contents of a `package.json`. */
interface PackageJson {
types?: string;
typings?: string;
}
/** Finds all entry points within a given NPM package directory. */
export function findEntryPointsWithinNpmPackage(dirPath: string): PackageEntryPoint[] {
const entryPoints: PackageEntryPoint[] = [];
for (const packageJsonFilePath of findPackageJsonFilesInDirectory(dirPath)) {
const packageJson = JSON.parse(readFileSync(packageJsonFilePath, 'utf8')) as PackageJson;
const typesFile = packageJson.types || packageJson.typings;
if (typesFile) {
entryPoints.push({
packageJsonPath: packageJsonFilePath,
typesEntryPointPath: join(dirname(packageJsonFilePath), typesFile),
});
}
}
return entryPoints;
}
/** Determine if the provided path is a directory. */
function isDirectory(dirPath: string) {
try {
return lstatSync(dirPath).isDirectory();
} catch {
return false;
}
}
/** Finds all `package.json` files within a directory. */
function* findPackageJsonFilesInDirectory(directoryPath: string): IterableIterator<string> {
for (const fileName of readdirSync(directoryPath)) {
const fullPath = join(directoryPath, fileName);
if (isDirectory(fullPath)) {
yield* findPackageJsonFilesInDirectory(fullPath);
} else if (fileName === 'package.json') {
yield fullPath;
}
}
}
+127
View File
@@ -0,0 +1,127 @@
load("//dev-infra/bazel:extract_js_module_output.bzl", "extract_js_module_output")
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary", "nodejs_test")
nodejs_test_args = [
# Needed so that node doesn't walk back to the source directory.
# From there, the relative imports would point to .ts files.
"--node_options=--preserve-symlinks",
# TODO(josephperrott): update dependency usages to no longer need bazel patch module resolver
# See: https://github.com/bazelbuild/rules_nodejs/wiki#--bazel_patch_module_resolver-now-defaults-to-false-2324
"--bazel_patch_module_resolver",
]
default_strip_export_pattern = "^ɵ(?!ɵdefineInjectable|ɵinject|ɵInjectableDef)"
"""Escapes a Regular expression so that it can be passed as process argument."""
def _escape_regex_for_arg(value):
return "\"%s\"" % value
"""
Extracts type names from a list of NPM type targets.
For example: Consider the `@npm//@types/node` target. This function extracts `node`
from the label. This is needed so that the Node types can be wired up within a
TypeScript program using the `types` tsconfig option.
"""
def extract_type_names_from_labels(type_targets):
type_names = []
for type_target in type_targets:
type_package = Label(type_target).package
if (type_package.startswith("@types/")):
type_names.append(type_package[len("@types/"):])
else:
fail("Expected type target to match the following format: " +
"`@<npm_workspace>//@types/<name>`, but got: %s" % type_target)
return type_names
"""
Builds an API report for the specified entry-point and compares it against the
specified golden
"""
def api_golden_test(
name,
golden,
entry_point,
data = [],
strip_export_pattern = default_strip_export_pattern,
types = [],
**kwargs):
quoted_export_pattern = _escape_regex_for_arg(strip_export_pattern)
kwargs["tags"] = kwargs.get("tags", []) + ["api_guard"]
# For API golden tests not running against a NPM package, we extract all transitive
# declarations of the specified `data` targets. This is necessary because API extractor
# needs to resolve other targets that have been linked by the Bazel NodeJS rules. The
# linker by default only provides access to JavaScript sources, but the API extractor is
# specifically concerned with type definitions that we can extract manually here.
extract_js_module_output(
name = "%s_data_typings" % name,
deps = data,
provider = "JSModuleInfo",
include_declarations = True,
include_default_files = False,
)
test_data = ["//dev-infra/bazel/api-golden", "//:package.json", ":%s_data_typings" % name] + \
data + types
nodejs_test(
name = name,
data = test_data,
entry_point = "//dev-infra/bazel/api-golden:index.ts",
templated_args = nodejs_test_args + [golden, entry_point, "false", quoted_export_pattern] +
extract_type_names_from_labels(types),
**kwargs
)
nodejs_binary(
name = name + ".accept",
testonly = True,
data = test_data,
entry_point = "//dev-infra/bazel/api-golden:index.ts",
templated_args = nodejs_test_args + [golden, entry_point, "true", quoted_export_pattern] +
extract_type_names_from_labels(types),
**kwargs
)
"""
Builds an API report for all entrypoints within the given NPM package and compares it
against goldens within the specified directory.
"""
def api_golden_test_npm_package(
name,
golden_dir,
npm_package,
data = [],
strip_export_pattern = default_strip_export_pattern,
types = [],
**kwargs):
quoted_export_pattern = _escape_regex_for_arg(strip_export_pattern)
kwargs["tags"] = kwargs.get("tags", []) + ["api_guard"]
nodejs_test(
name = name,
data = ["//dev-infra/bazel/api-golden"] + data + types,
entry_point = "//dev-infra/bazel/api-golden:index_npm_packages.ts",
templated_args = nodejs_test_args + [golden_dir, npm_package, "false", quoted_export_pattern] +
extract_type_names_from_labels(types),
**kwargs
)
nodejs_binary(
name = name + ".accept",
testonly = True,
data = ["//dev-infra/bazel/api-golden"] + data + types,
entry_point = "//dev-infra/bazel/api-golden:index_npm_packages.ts",
templated_args = nodejs_test_args + [golden_dir, npm_package, "true", quoted_export_pattern] +
extract_type_names_from_labels(types),
**kwargs
)
+47
View File
@@ -0,0 +1,47 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {runfiles} from '@bazel/runfiles';
import * as chalk from 'chalk';
import {testApiGolden} from './test_api_report';
/**
* Entry point for the `api_golden_test` Bazel rule. This function builds an API report for
* the specified entry point file and compares it against the specified golden file.
*/
async function main(
goldenFilePath: string, entryPointFilePath: string, approveGolden: boolean,
stripExportPattern: RegExp, typeNames: string[]) {
const {succeeded, apiReportChanged} = await testApiGolden(
goldenFilePath, entryPointFilePath, approveGolden, stripExportPattern, typeNames);
if (!succeeded && apiReportChanged) {
console.error(chalk.red(`The API signature has changed and the golden file is outdated.`));
console.info(chalk.yellow(
`Golden can be updated by running: yarn bazel run ${process.env.TEST_TARGET}.accept`));
}
// Bazel expects `3` as exit code for failing tests.
process.exitCode = succeeded ? 0 : 3;
}
if (require.main === module) {
const args = process.argv.slice(2);
const goldenFilePath = runfiles.resolve(args[0]);
const entryPointFilePath = runfiles.resolve(args[1]);
const approveGolden = args[2] === 'true';
const stripExportPattern = new RegExp(args[3]);
const typeNames = args.slice(4);
main(goldenFilePath, entryPointFilePath, approveGolden, stripExportPattern, typeNames)
.catch(e => {
console.error(e);
process.exit(1);
});
}
@@ -0,0 +1,74 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {runfiles} from '@bazel/runfiles';
import * as chalk from 'chalk';
import {join, relative} from 'path';
import {findEntryPointsWithinNpmPackage} from './find_entry_points';
import {testApiGolden} from './test_api_report';
/**
* Entry point for the `api_golden_test_npm_package` Bazel rule. This function determines
* all types within the specified NPM package and builds API reports that will be compared
* against golden files within the given golden directory.
*/
async function main(
goldenDir: string, npmPackageDir: string, approveGolden: boolean, stripExportPattern: RegExp,
typeNames: string[]) {
const entryPoints = findEntryPointsWithinNpmPackage(npmPackageDir);
const outdatedGoldens: string[] = [];
let allTestsSucceeding = true;
for (const {packageJsonPath, typesEntryPointPath} of entryPoints) {
const pkgRelativeName = relative(npmPackageDir, typesEntryPointPath);
// API extractor generates API reports as markdown files. For each types
// entry-point we maintain a separate golden file. These golden files are
// based on the name of the entry-point `.d.ts` file in the NPM package,
// but with the proper `.md` file extension.
// See: https://api-extractor.com/pages/overview/demo_api_report/.
const goldenName = pkgRelativeName.replace(/\.d\.ts$/, '.md');
const goldenFilePath = join(goldenDir, goldenName);
const {succeeded, apiReportChanged} = await testApiGolden(
goldenFilePath, typesEntryPointPath, approveGolden, stripExportPattern, typeNames,
packageJsonPath);
// Keep track of outdated goldens.
if (!succeeded && apiReportChanged) {
outdatedGoldens.push(goldenName);
}
allTestsSucceeding = allTestsSucceeding && succeeded;
}
if (outdatedGoldens.length) {
console.error(chalk.red(`The following goldens are outdated:`));
outdatedGoldens.forEach(name => console.info(`- ${name}`));
console.info();
console.info(chalk.yellow(
`The goldens can be updated by running: yarn bazel run ${process.env.TEST_TARGET}.accept`));
}
// Bazel expects `3` as exit code for failing tests.
process.exitCode = allTestsSucceeding ? 0 : 3;
}
if (require.main === module) {
const args = process.argv.slice(2);
const goldenDir = runfiles.resolve(args[0]);
const npmPackageDir = runfiles.resolve(args[1]);
const approveGolden = args[2] === 'true';
const stripExportPattern = new RegExp(args[3]);
const typeNames = args.slice(4);
main(goldenDir, npmPackageDir, approveGolden, stripExportPattern, typeNames).catch(e => {
console.error(e);
process.exit(1);
});
}
@@ -0,0 +1,142 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {runfiles} from '@bazel/runfiles';
import {ConsoleMessageId, Extractor, ExtractorConfig, ExtractorLogLevel, ExtractorMessage, ExtractorMessageId, ExtractorResult, IConfigFile} from '@microsoft/api-extractor';
import {AstModule} from '@microsoft/api-extractor/lib/analyzer/AstModule';
import {ExportAnalyzer} from '@microsoft/api-extractor/lib/analyzer/ExportAnalyzer';
import {basename, dirname} from 'path';
/**
* Original definition of the `ExportAnalyzer#fetchAstModuleExportInfo` method.
* We store the original function since we monkey-patch it later to account for
* specified strip export patterns.
* */
const _origFetchAstModuleExportInfo = ExportAnalyzer.prototype.fetchAstModuleExportInfo;
/**
* Builds an API report for the given entry-point file and compares
* it against a golden file.
*
* @param goldenFilePath Path to an API report file that is used as golden
* @param indexFilePath Entry point file that is analyzed to build the API report.
* @param approveGolden Whether the golden file should be updated.
* @param stripExportPattern Regular Expression that can be used to filter out exports
* from the API report.
* @param typeNames Name of types which should be included for analysis of the entry-point.
* Types are expected to exist within the default `node_modules/@types/` folder.
* @param packageJsonPath Optional path to a `package.json` file that contains the entry
* point. Note that the `package.json` is currently only used by `api-extractor` to determine
* the package name displayed within the API golden.
*/
export async function testApiGolden(
goldenFilePath: string, indexFilePath: string, approveGolden: boolean,
stripExportPattern: RegExp, typeNames: string[] = [],
packageJsonPath = resolveWorkspacePackageJsonPath()): Promise<ExtractorResult> {
// If no `TEST_TMPDIR` is defined, then this script runs using `bazel run`. We use
// the runfile directory as temporary directory for API extractor.
const tempDir = process.env.TEST_TMPDIR ?? process.cwd();
const configObject: IConfigFile = {
compiler: {
overrideTsconfig:
// We disable automatic `@types` resolution as this throws-off API reports
// when the API test is run outside sandbox. Instead we expect a list of
// hard-coded types that should be included. This works in non-sandbox too.
{files: [indexFilePath], compilerOptions: {types: typeNames, lib: ['esnext', 'dom']}}
},
projectFolder: dirname(packageJsonPath),
mainEntryPointFilePath: indexFilePath,
dtsRollup: {enabled: false},
docModel: {enabled: false},
apiReport: {
enabled: true,
reportFolder: dirname(goldenFilePath),
reportTempFolder: tempDir,
reportFileName: basename(goldenFilePath),
},
tsdocMetadata: {enabled: false},
newlineKind: 'lf',
messages: {
extractorMessageReporting: {
// If an export does not have a release tag (like `@public`), API extractor maps
// considers it still as `Public`. We hide the message for now given the Angular
// repositories do not follow the TSDoc standard. https://tsdoc.org/.
// TODO: Make this an error once TSDoc standard is followed in all projects.
[ExtractorMessageId.MissingReleaseTag]: {logLevel: ExtractorLogLevel.None},
},
},
};
// We read the specified `package.json` manually and build a package name that is
// compatible with the API extractor. This is a workaround for a bug in api-extractor.
// TODO remove once https://github.com/microsoft/rushstack/issues/2774 is resolved.
const packageJson = require(packageJsonPath);
const packageNameSegments = packageJson.name.split('/');
const packageName = packageNameSegments.length === 1 ?
packageNameSegments[0] :
`${packageNameSegments[0]}/${packageNameSegments.slice(1).join('_')}`;
const extractorConfig = ExtractorConfig.prepare({
configObject,
// TODO: Remove workaround once https://github.com/microsoft/rushstack/issues/2774 is fixed.
packageJson: {name: packageName},
packageJsonFullPath: packageJsonPath,
configObjectFullPath: undefined,
});
// This patches the `ExportAnalyzer` of `api-extractor` so that we can filter out
// exports that match a specified pattern. Ideally this would not be needed as the
// TSDoc JSDoc annotations could be used to filter out exports from the API report,
// but there are cases in Angular where exports cannot be `@internal` but at the same
// time are denoted as unstable. Such exports are allowed to change frequently and should
// not be captured in the API report (as this would be unnecessarily inconvenient).
ExportAnalyzer.prototype.fetchAstModuleExportInfo = function(module: AstModule) {
const info = _origFetchAstModuleExportInfo.apply(this, [module]);
info.exportedLocalEntities.forEach((entity, exportName) => {
if (stripExportPattern.test(exportName)) {
info.exportedLocalEntities.delete(exportName);
}
});
return info;
};
return Extractor.invoke(extractorConfig, {
// If the golden should be approved, then `localBuild: true` instructs
// API extractor to update the file.
localBuild: approveGolden,
// Process messages from the API extractor (and modify log levels if needed).
messageCallback: msg => processExtractorMessage(msg, approveGolden),
});
}
/**
* Process an API extractor message. Microsoft's API extractor allows developers to
* handle messages before API extractor prints them. This allows us to adjust log level
* for certain messages, or to fully prevent messages from being printed out.
* */
async function processExtractorMessage(message: ExtractorMessage, isApprove: boolean) {
// If the golden does not match, we hide the error as API extractor prints
// a warning asking the user to manually copy the new API report. We print
// a custom warning below asking the developer to run the `.accept` Bazel target.
// TODO: Simplify once https://github.com/microsoft/rushstack/issues/2773 is resolved.
if (message.messageId === ConsoleMessageId.ApiReportNotCopied) {
// Mark the message as handled so that API-extractor does not print it. We print
// a message manually after extraction.
message.handled = true;
message.logLevel = isApprove ? ExtractorLogLevel.None : ExtractorLogLevel.Error;
}
}
/** Resolves the `package.json` of the workspace executing this action. */
function resolveWorkspacePackageJsonPath(): string {
const workspaceName = process.env.BAZEL_WORKSPACE!;
return runfiles.resolve(`${workspaceName}/package.json`);
}
@@ -0,0 +1,80 @@
"""Implementation of the `browser_archive` rule."""
def _browser_archive_impl(ctx):
ctx.report_progress("Downloading browser archive from: %s" % ctx.attr.url)
ctx.download_and_extract(
url = ctx.attr.url,
sha256 = ctx.attr.sha256,
)
# The browser archive has been downloaded and extracted. We now generate a repository
# `BUILD.bazel` file that exposes the archive files, together with the specified
# named files using the `browser_configure` rule.
ctx.file("BUILD.bazel", content = """
load("@angular//dev-infra/bazel/browsers:browser_configure.bzl", "browser_configure")
licenses(%s)
browser_configure(
name = "metadata",
files = glob(["**/*"]),
named_files = %s,
visibility = ["//visibility:public"],
)
""" % (str(ctx.attr.licenses), str(ctx.attr.named_files)))
"""
Rule that can be used to download and unpack a browser archive in a dedicated Bazel
repository. Additionally, files within the archive can be denoted with an unique name
so that web tests can access browser files in a platform-agnostic way, regardless of
which `browser_archive` repository is added as dependency.
As an example for the concept of denoting archive files with an unique name, consider a case
where a a web test decides conditionally based on the current exec platform which
`browser_archive` repository is used (e.g. mac, windows or linux). The archives are different
for each platform. The test usually would need to determine the current platform, and know how
each archive is structured in order to access the browser binary within the repository. By
defining named files though, the web test could just pull a named file called `BINARY` that
always resolves to the browser binary in a platform-agnostic way.
Note #1: This rule exists as an alternative to the `platform_http_file` concept
from `rules_webtesting` because the `platform_http_file` rule does not extract the archive
directly, but relies on later build actions to perform the unpacking. This results in less
efficient caching because build actions are invalidated more frequently (e.g. `bazel clean).
We also noticed that the extraction within RBE containers is rather unstable, and extracting
the archives as part of a Bazel repository mitigates this (as extractions happens on the host).
Note #2: Additionally `rules_webtesting` defines a single repository for all platforms,
where only an archive for the current host platform is pulled. This breaks cross-compilation
because the wrong platform archive would be used for web tests that run in the exec platform.
"""
browser_archive = repository_rule(
implementation = _browser_archive_impl,
attrs = {
"url": attr.string(
doc = "Browser archive to download and extract.",
mandatory = True,
),
"sha256": attr.string(
doc = "SHA256 checksum for the archive.",
mandatory = True,
),
"licenses": attr.string_list(
mandatory = True,
allow_empty = False,
doc = """
Licenses that apply to the archive. Will be passed to a `licenses` invocation
within the repository. https://docs.bazel.build/versions/0.24.0/be/functions.html#licenses.
""",
),
"named_files": attr.string_dict(
doc = """
Dictionary that maps files to unique identifiers. This is useful
if browser archives are different on different platforms and the web
tests would not want to care about archive-specific paths. e.g. targets
expect a `CHROMIUM` key to point to the Chromium browser binary.
""",
mandatory = True,
),
},
)
@@ -0,0 +1,69 @@
load("@io_bazel_rules_webtesting//web/internal:metadata.bzl", "metadata")
load("@io_bazel_rules_webtesting//web/internal:provider.bzl", "WebTestInfo")
"""Converts the specified label to a manifest path"""
def _label_to_manifest_path(label):
if label.package != "":
return "%s/%s" % (label.workspace_name, label.package)
return label.workspace_name
"""Implementation of the `browser_configure` rule."""
def _browser_configure_impl(ctx):
named_files = {}
base_dir = _label_to_manifest_path(ctx.label)
# Update the named files to manifest paths that can be resolved
# with Bazel runfile resolution in web tests.
for n, p in ctx.attr.named_files.items():
named_files[n] = base_dir + "/" + p
# Create a web test metadata file that will be provided as part of
# the `WebTestInfo` provider.
metadata.create_file(
ctx = ctx,
output = ctx.outputs.web_test_metadata,
web_test_files = [
metadata.web_test_files(ctx = ctx, named_files = named_files),
],
)
return [
DefaultInfo(runfiles = ctx.runfiles(files = ctx.files.files)),
WebTestInfo(metadata = ctx.outputs.web_test_metadata),
]
"""
Rule that is used in combination with the `browser_archive` rule. It captures a set
of files which are needed for dealing with a browser. Additionally, specific files
for the browser can be denoted with an unique name so that web tests can access browser
files in a platform-agnostic way, regardless of which browser repository is selected.
The specified browser files are exposed as runfiles of the target defined through this
rule. The unique names with their associated files are captured within a metadata file
that is exposed through a `WebTestInfo` provider. Web tests will be able to deal with
this metadata file to resolve browser files in a platform-agnostic way.
More details on this can be found in the `browser_archive` rule.
"""
browser_configure = rule(
attrs = {
"files": attr.label_list(
mandatory = True,
allow_files = True,
doc = "List of files which are needed for the browser.",
),
"named_files": attr.string_dict(
doc = """
Dictionary that maps files to unique identifiers. This is useful
if browser archives are different on different platforms and the web
tests would not want to care about archive-specific paths. e.g. targets
expect a `CHROMIUM` key to point to the Chromium browser binary.
""",
mandatory = True,
),
},
outputs = {"web_test_metadata": "%{name}.gen.json"},
implementation = _browser_configure_impl,
)
@@ -1,17 +1,3 @@
# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Pinned browser versions.
This function is here to make browser repositories work with cross-platform RBE.
+15 -63
View File
@@ -1,74 +1,26 @@
load("@io_bazel_rules_webtesting//web:web.bzl", "browser", "web_test_archive")
load("@io_bazel_rules_webtesting//web:web.bzl", "browser")
# Copyright Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#
package(default_visibility = ["//visibility:public"])
# Override of chromium web_test_archive so that the archive is selected based on platform
web_test_archive(
name = "chromium_archive",
testonly = True,
archive = select({
"@io_bazel_rules_webtesting//common/conditions:linux": "@org_chromium_chromium_amd64//file",
"@io_bazel_rules_webtesting//common/conditions:mac": "@org_chromium_chromium_macos//file",
"@io_bazel_rules_webtesting//common/conditions:windows": "@org_chromium_chromium_windows//file",
}),
extract = "build",
named_files = select({
"@io_bazel_rules_webtesting//common/conditions:linux": {"CHROMIUM": "chrome-linux/chrome"},
"@io_bazel_rules_webtesting//common/conditions:mac": {"CHROMIUM": "chrome-mac/Chromium.app/Contents/MacOS/chromium"},
"@io_bazel_rules_webtesting//common/conditions:windows": {"CHROMIUM": "chrome-win/chrome.exe"},
}),
visibility = ["//dev-infra/bazel/browsers:__subpackages__"],
)
# Override of chromedriver web_test_archive so that the archive is selected based on platform
web_test_archive(
name = "chromedriver_archive",
testonly = True,
archive = select({
"@io_bazel_rules_webtesting//common/conditions:linux": "@org_chromium_chromedriver_amd64//file",
"@io_bazel_rules_webtesting//common/conditions:mac": "@org_chromium_chromedriver_macos//file",
"@io_bazel_rules_webtesting//common/conditions:windows": "@org_chromium_chromedriver_windows//file",
}),
extract = "build",
named_files = select({
"@io_bazel_rules_webtesting//common/conditions:linux": {
"CHROMEDRIVER": "chromedriver_linux64/chromedriver",
},
"@io_bazel_rules_webtesting//common/conditions:mac": {
"CHROMEDRIVER": "chromedriver_mac64/chromedriver",
},
"@io_bazel_rules_webtesting//common/conditions:windows": {
"CHROMEDRIVER": "chromedriver_win32/chromedriver.exe",
},
}),
visibility = ["//dev-infra/bazel/browsers:__subpackages__"],
)
browser(
name = "chromium",
metadata = "chromium.json",
visibility = ["//visibility:public"],
deps = [
":chromedriver_archive",
":chromium_archive",
"@io_bazel_rules_webtesting//go/wsl",
],
] + select({
"@io_bazel_rules_webtesting//common/conditions:linux": [
"@org_chromium_chromedriver_amd64//:metadata",
"@org_chromium_chromium_amd64//:metadata",
],
"@io_bazel_rules_webtesting//common/conditions:mac": [
"@org_chromium_chromedriver_macos//:metadata",
"@org_chromium_chromium_macos//:metadata",
],
"@io_bazel_rules_webtesting//common/conditions:windows": [
"@org_chromium_chromedriver_windows//:metadata",
"@org_chromium_chromium_windows//:metadata",
],
}),
)
# Make source files available for distribution via pkg_npm
+31 -13
View File
@@ -1,4 +1,4 @@
load("//dev-infra/bazel/browsers:platform_http_file.bzl", "platform_http_file")
load("//dev-infra/bazel/browsers:browser_archive_repo.bzl", "browser_archive")
"""
Defines repositories for Chromium that can be used inside Karma unit tests
@@ -9,50 +9,68 @@ def define_chromium_repositories():
# To update to a newer version of Chromium see instructions in
# https://github.com/angular/angular/blob/master/dev-infra/bazel/browsers/README.md.
platform_http_file(
browser_archive(
name = "org_chromium_chromium_amd64",
licenses = ["notice"], # BSD 3-clause (maybe more?)
sha256 = "36759ed6d151645d00a3a015200334edc70188b422eec51bcaa5790c8e906e27",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/812847/chrome-linux.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/812847/chrome-linux.zip",
named_files = {
"CHROMIUM": "chrome-linux/chrome",
},
)
platform_http_file(
browser_archive(
name = "org_chromium_chromium_macos",
licenses = ["notice"], # BSD 3-clause (maybe more?)
sha256 = "e10533c84ef57232975d6bde9cd28fd0354371e9556dda85e01178e6dcd56b93",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/812851/chrome-mac.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/812851/chrome-mac.zip",
named_files = {
"CHROMIUM": "chrome-mac/Chromium.app/Contents/MacOS/chromium",
},
)
platform_http_file(
browser_archive(
name = "org_chromium_chromium_windows",
licenses = ["notice"], # BSD 3-clause (maybe more?)
sha256 = "40d0dec1892d729db2f7d8f27feff762b070a02f04d4e14f4e37b97d6b7c3c8f",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/812822/chrome-win.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/812822/chrome-win.zip",
named_files = {
"CHROMIUM": "chrome-win/chrome.exe",
},
)
platform_http_file(
browser_archive(
name = "org_chromium_chromedriver_amd64",
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
sha256 = "d859f8ecb21e26d3ddaf3f229da695bc86512f4e6c9fe32533af7a8b36783ec5",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/812847/chromedriver_linux64.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/812847/chromedriver_linux64.zip",
named_files = {
"CHROMEDRIVER": "chromedriver_linux64/chromedriver",
},
)
platform_http_file(
browser_archive(
name = "org_chromium_chromedriver_macos",
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
sha256 = "aa7a99fa23287725d7108cc07baa94e6f0ef4171ff7b134018387a939a67d93d",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/812851/chromedriver_mac64.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/812851/chromedriver_mac64.zip",
named_files = {
"CHROMEDRIVER": "chromedriver_mac64/chromedriver",
},
)
platform_http_file(
browser_archive(
name = "org_chromium_chromedriver_windows",
licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT
sha256 = "826f2bd0c50b823e7642860ed08cacf69d3756002a71ac30cdd77c68f31d2d24",
# 87.0.4280
urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/812822/chromedriver_win32.zip"],
url = "https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/812822/chromedriver_win32.zip",
named_files = {
"CHROMEDRIVER": "chromedriver_win32/chromedriver.exe",
},
)
+12 -53
View File
@@ -1,52 +1,7 @@
load("@io_bazel_rules_webtesting//web:web.bzl", "browser", "web_test_archive")
load("@io_bazel_rules_webtesting//web:web.bzl", "browser")
# Copyright Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#
package(default_visibility = ["//visibility:public"])
# Override of firefox web_test_archive so that the archive is selected based on platform.
web_test_archive(
name = "firefox_archive",
testonly = True,
archive = select({
"@io_bazel_rules_webtesting//common/conditions:linux": "@org_mozilla_firefox_amd64//file",
"@io_bazel_rules_webtesting//common/conditions:mac": "@org_mozilla_firefox_macos//file",
}),
extract = "build",
named_files = select({
"@io_bazel_rules_webtesting//common/conditions:linux": {"FIREFOX": "firefox/firefox"},
"@io_bazel_rules_webtesting//common/conditions:mac": {"FIREFOX": "Firefox.app/Contents/MacOS/firefox"},
}),
visibility = ["//dev-infra/bazel/browsers:__subpackages__"],
)
# Override of geckodriver web_test_archive so that the archive is selected based on platform.
web_test_archive(
name = "geckodriver_archive",
testonly = True,
archive = select({
"@io_bazel_rules_webtesting//common/conditions:linux": "@org_mozilla_geckodriver_amd64//file",
"@io_bazel_rules_webtesting//common/conditions:mac": "@org_mozilla_geckodriver_macos//file",
}),
extract = "build",
named_files = {"GECKODRIVER": "geckodriver"},
visibility = ["//dev-infra/bazel/browsers:__subpackages__"],
)
browser(
name = "firefox",
disabled = select({
@@ -56,14 +11,18 @@ browser(
"//conditions:default": None,
}),
metadata = "firefox.json",
visibility = ["//visibility:public"],
deps = select({
"@io_bazel_rules_webtesting//common/conditions:windows": [],
"//conditions:default": [
"@io_bazel_rules_webtesting//go/wsl",
":firefox_archive",
":geckodriver_archive",
deps = [
"@io_bazel_rules_webtesting//go/wsl",
] + select({
"@io_bazel_rules_webtesting//common/conditions:linux": [
"@org_mozilla_firefox_amd64//:metadata",
"@org_mozilla_geckodriver_amd64//:metadata",
],
"@io_bazel_rules_webtesting//common/conditions:mac": [
"@org_mozilla_firefox_macos//:metadata",
"@org_mozilla_geckodriver_macos//:metadata",
],
"@io_bazel_rules_webtesting//common/conditions:windows": [],
}),
)
+21 -9
View File
@@ -1,4 +1,4 @@
load("//dev-infra/bazel/browsers:platform_http_file.bzl", "platform_http_file")
load("//dev-infra/bazel/browsers:browser_archive_repo.bzl", "browser_archive")
"""
Defines repositories for Firefox that can be used inside Karma unit tests
@@ -9,34 +9,46 @@ def define_firefox_repositories():
# Instructions on updating the Firefox version can be found in the `README.md` file
# next to this file.
platform_http_file(
browser_archive(
name = "org_mozilla_firefox_amd64",
licenses = ["reciprocal"], # MPL 2.0
sha256 = "601e5a9a12ce680ecd82177c7887dae008d8f33690da43be1a690b76563cd992",
# Firefox v84.0
urls = ["https://ftp.mozilla.org/pub/firefox/releases/84.0/linux-x86_64/en-US/firefox-84.0.tar.bz2"],
url = "https://ftp.mozilla.org/pub/firefox/releases/84.0/linux-x86_64/en-US/firefox-84.0.tar.bz2",
named_files = {
"FIREFOX": "firefox/firefox",
},
)
platform_http_file(
browser_archive(
name = "org_mozilla_firefox_macos",
licenses = ["reciprocal"], # MPL 2.0
sha256 = "4c7bca050eb228f4f6f93a9895af0a87473e03c67401d1d2f1ba907faf87fefd",
# Firefox v84.0
urls = ["https://ftp.mozilla.org/pub/firefox/releases/84.0/mac/en-US/Firefox%2084.0.dmg"],
url = "https://ftp.mozilla.org/pub/firefox/releases/84.0/mac/en-US/Firefox%2084.0.dmg",
named_files = {
"FIREFOX": "Firefox.app/Contents/MacOS/firefox",
},
)
platform_http_file(
browser_archive(
name = "org_mozilla_geckodriver_amd64",
licenses = ["reciprocal"], # MPL 2.0
sha256 = "61bfc547a623d7305256611a81ecd24e6bf9dac555529ed6baeafcf8160900da",
# Geckodriver v0.28.0
urls = ["https://github.com/mozilla/geckodriver/releases/download/v0.28.0/geckodriver-v0.28.0-linux64.tar.gz"],
url = "https://github.com/mozilla/geckodriver/releases/download/v0.28.0/geckodriver-v0.28.0-linux64.tar.gz",
named_files = {
"GECKODRIVER": "geckodriver",
},
)
platform_http_file(
browser_archive(
name = "org_mozilla_geckodriver_macos",
licenses = ["reciprocal"], # MPL 2.0
sha256 = "c288ff6db39adfd5eea0e25b4c3e71bfd9fb383eccf521cdd65f67ea78eb1761",
# Geckodriver v0.28.0
urls = ["https://github.com/mozilla/geckodriver/releases/download/v0.28.0/geckodriver-v0.28.0-macos.tar.gz"],
url = "https://github.com/mozilla/geckodriver/releases/download/v0.28.0/geckodriver-v0.28.0-macos.tar.gz",
named_files = {
"GECKODRIVER": "geckodriver",
},
)
@@ -1,24 +0,0 @@
load(
"@io_bazel_rules_webtesting//web/internal:platform_http_file.bzl",
_platform_http_file = "platform_http_file",
)
def platform_http_file(name, licenses, sha256, urls):
"""Platform specific browser repository.
This works around a deficiency in io_bazel_rules_webtesting platform_http_file in that
it selects the platform when the repository rule is executed. This limits browsers
tests to run on the local user platform only. For cross-platform RBE we want a repository
to be defined per platform so the correct one can be selected.
"""
_platform_http_file(
name = name,
amd64_sha256 = sha256,
amd64_urls = urls,
licenses = licenses,
macos_sha256 = sha256,
macos_urls = urls,
windows_sha256 = sha256,
windows_urls = urls,
)
@@ -0,0 +1,78 @@
load("@build_bazel_rules_nodejs//:providers.bzl", "DeclarationInfo", "JSEcmaScriptModuleInfo", "JSModuleInfo", "JSNamedModuleInfo")
"""Converts a provider name to its actually Starlark provider instance."""
def _name_to_js_module_provider(name):
if name == "JSModuleInfo":
return JSModuleInfo
elif name == "JSNamedModuleInfo":
return JSNamedModuleInfo
elif name == "JSEcmaScriptModuleInfo":
return JSEcmaScriptModuleInfo
fail("Unexpected JavaScript module provider.")
"""Implementation of the extract_js_module_output rule."""
def _extract_js_module_output_impl(ctx):
js_module_provider = _name_to_js_module_provider(ctx.attr.provider)
depsets = []
for dep in ctx.attr.deps:
# Include JavaScript sources (including transitive outputs) based on the
# configured JavaScript module provider.
if js_module_provider in dep:
depsets.append(dep[js_module_provider].sources)
# Based on whether declarations should be collected, extract direct
# and transitive declaration files using the `DeclarationInfo` provider.
if ctx.attr.include_declarations and DeclarationInfo in dep:
depsets.append(dep[DeclarationInfo].transitive_declarations)
# Based on whether default files should be collected, extract direct
# files which are exposed using the `DefaultInfo` provider. Also include
# data runfiles which are needed for the current target.
# https://docs.bazel.build/versions/main/skylark/lib/DefaultInfo.html#data_runfiles
if ctx.attr.include_default_files and DefaultInfo in dep:
depsets.append(dep[DefaultInfo].files)
depsets.append(dep[DefaultInfo].data_runfiles.files)
sources = depset(transitive = depsets)
return [DefaultInfo(files = sources)]
"""
Rule that collects declared JavaScript module output files from a list of dependencies
based on a configurable JavaScript module provider. The extracted outputs are exposed
within the `DefaultInfo` provider. Targets defined using this rule can be used as input
for rules that require JavaScript sources, or if there are multiple JavaScript output
variants defined for a target while for example only the `JSModule` outputs are of interest.
As an example: This rule is helpful in combination with `ts_library` and `ng_module` as
those rule expose multiple output flavors (which are distinguishable by the JavaScript module
providers as imported from `providers.bzl`). i.e. these rules expose flavors for named AMD
modules and ECMAScript module output. For reference:
https://github.com/bazelbuild/rules_nodejs/blob/stable/packages/typescript/internal/build_defs.bzl#L334-L337
"""
extract_js_module_output = rule(
implementation = _extract_js_module_output_impl,
attrs = {
"deps": attr.label_list(
allow_files = True,
),
"provider": attr.string(
doc = "JavaScript module info provider that is used for collecting sources from the dependencies.",
mandatory = True,
values = ["JSModuleInfo", "JSNamedModuleInfo", "JSEcmaScriptModuleInfo"],
),
"include_declarations": attr.bool(
mandatory = True,
doc = "Whether declaration files should be collected from the dependencies.",
),
"include_default_files": attr.bool(
mandatory = True,
doc = """
Whether files from the `DefaultInfo` provider should be collected. Includes
data runfiles needed for the default outputs from dependencies.
""",
),
},
)
@@ -1,11 +1,10 @@
package(default_visibility = ["//visibility:public"])
load("//dev-infra:defaults.bzl", "ts_library")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "driver-utilities",
srcs = glob(["*.ts"]),
module_name = "@angular/dev-infra-private/benchmark/driver-utilities",
tsconfig = "//dev-infra/benchmark/component_benchmark:tsconfig-e2e.json",
deps = [
"//packages/benchpress",
@@ -71,6 +71,10 @@ def ng_rollup_bundle(
silent = True,
format = format,
sourcemap = "true",
# TODO(devversion): consider removing when View Engine is removed. View Engine
# uses Bazel manifest path imports in generated factory files.
# e.g. `import "<workspace_root>/<..>/some_file";`
link_workspace_root = True,
**kwargs
)
@@ -49,6 +49,7 @@ const plugins = [
// https://github.com/angular/angular-cli/blob/1a1ceb609b9a87c4021cce3a6f0fc6d167cd09d2/packages/ngtools/webpack/src/angular_compiler_plugin.ts#L918-L920
mainFields: ivyEnabled ? ['module_ivy_ngcc', 'main_ivy_ngcc', 'module', 'main'] :
['module', 'main'],
preferBuiltins: true,
}),
commonjs({ignoreGlobal: true}),
sourcemaps(),
@@ -62,6 +63,7 @@ if (useBuildOptimizer) {
module.exports = {
plugins,
onwarn: customWarningHandler,
external: [TMPL_external],
output: {
globals: {TMPL_globals},
@@ -69,6 +71,18 @@ module.exports = {
}
};
/** Custom warning handler for Rollup. */
function customWarningHandler(warning, defaultHandler) {
// If rollup is unable to resolve an import, we want to throw an error
// instead of silently treating the import as external dependency.
// https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
if (warning.code === 'UNRESOLVED_IMPORT') {
throw Error(`Unresolved import: ${warning.message}`);
}
defaultHandler(warning);
}
/** Extracts the top-level bundle banner if specified. */
function extractBannerIfConfigured() {
if (!bannerFile) {
+15 -1
View File
@@ -64,8 +64,12 @@ var GithubClient = /** @class */ (function () {
this.repos = this._octokit.repos;
this.issues = this._octokit.issues;
this.git = this._octokit.git;
this.paginate = this._octokit.paginate;
this.rateLimit = this._octokit.rateLimit;
this.teams = this._octokit.teams;
// Note: These are properties from `Octokit` that are brought in by optional plugins.
// TypeScript requires us to provide an explicit type for these.
this.rest = this._octokit.rest;
this.paginate = this._octokit.paginate;
}
return GithubClient;
}());
@@ -258,6 +262,16 @@ var GitClient = /** @class */ (function () {
}
return new semver.SemVer(latestTag, semVerOptions);
};
/** Retrieves the git tag matching the provided SemVer, if it exists. */
GitClient.prototype.getMatchingTagForSemver = function (semver$1) {
var semVerOptions = { loose: true };
var tags = this.runGraceful(['tag', '--sort=-committerdate', '--merged']).stdout.split('\n');
var matchingTag = tags.find(function (tag) { var _a; return ((_a = semver.parse(tag, semVerOptions)) === null || _a === void 0 ? void 0 : _a.compare(semver$1)) === 0; });
if (matchingTag === undefined) {
throw new Error("Unable to find a tag for the version: \"" + semver$1.format() + "\"");
}
return matchingTag;
};
/** Retrieve a list of all files in the repository changed since the provided shaOrRef. */
GitClient.prototype.allChangesFilesSince = function (shaOrRef) {
if (shaOrRef === void 0) { shaOrRef = 'HEAD'; }
+3 -4
View File
@@ -1,5 +1,4 @@
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//tools:defaults.bzl", "jasmine_node_test")
load("//dev-infra:defaults.bzl", "jasmine_node_test", "ts_library")
ts_library(
name = "caretaker",
@@ -7,14 +6,15 @@ ts_library(
["**/*.ts"],
exclude = ["**/*.spec.ts"],
),
module_name = "@angular/dev-infra-private/caretaker",
visibility = ["//dev-infra:__subpackages__"],
deps = [
"//dev-infra/release/versioning",
"//dev-infra/utils",
"@npm//@types/inquirer",
"@npm//@types/node",
"@npm//@types/node-fetch",
"@npm//@types/yargs",
"@npm//inquirer",
"@npm//multimatch",
"@npm//node-fetch",
"@npm//typed-graphqlify",
@@ -41,7 +41,6 @@ ts_library(
jasmine_node_test(
name = "test",
bootstrap = ["//tools/testing:node_no_angular_es5"],
deps = [
":test_lib",
],
+2 -2
View File
@@ -13,10 +13,10 @@ const exampleData = 'this is example data' as const;
/** A simple usage of the BaseModule to illustrate the workings built into the abstract class. */
class ConcreteBaseModule extends BaseModule<typeof exampleData> {
async retrieveData() {
override async retrieveData() {
return exampleData;
}
async printToTerminal() {}
override async printToTerminal() {}
}
describe('BaseModule', () => {
+2 -2
View File
@@ -25,7 +25,7 @@ type CiData = {
}[];
export class CiModule extends BaseModule<CiData> {
async retrieveData() {
override async retrieveData() {
const gitRepoWithApi = {api: this.git.github, ...this.git.remoteConfig};
const releaseTrains = await fetchActiveReleaseTrains(gitRepoWithApi);
@@ -52,7 +52,7 @@ export class CiModule extends BaseModule<CiData> {
return await Promise.all(ciResultPromises);
}
async printToTerminal() {
override async printToTerminal() {
const data = await this.data;
const minLabelLength = Math.max(...data.map(result => result.label.length));
info.group(bold(`CI`));
+2 -2
View File
@@ -23,7 +23,7 @@ export interface G3StatsData {
}
export class G3Module extends BaseModule<G3StatsData|void> {
async retrieveData() {
override async retrieveData() {
const toCopyToG3 = this.getG3FileIncludeAndExcludeLists();
const latestSha = this.getLatestShas();
@@ -35,7 +35,7 @@ export class G3Module extends BaseModule<G3StatsData|void> {
latestSha.g3, latestSha.master, toCopyToG3.include, toCopyToG3.exclude);
}
async printToTerminal() {
override async printToTerminal() {
const stats = await this.data;
if (!stats) {
return;
+2 -2
View File
@@ -45,7 +45,7 @@ type GithubQueryResult = {
const MAX_RETURNED_ISSUES = 20;
export class GithubQueriesModule extends BaseModule<GithubQueryResults|void> {
async retrieveData() {
override async retrieveData() {
// Non-null assertion is used here as the check for undefined immediately follows to confirm the
// assertion. Typescript's type filtering does not seem to work as needed to understand
// whether githubQueries is undefined or not.
@@ -95,7 +95,7 @@ export class GithubQueriesModule extends BaseModule<GithubQueryResults|void> {
return graphqlQuery;
}
async printToTerminal() {
override async printToTerminal() {
const queryResults = await this.data;
if (!queryResults) {
return;
+2 -2
View File
@@ -45,11 +45,11 @@ export const services: ServiceConfig[] = [
];
export class ServicesModule extends BaseModule<StatusCheckResult[]> {
async retrieveData() {
override async retrieveData() {
return Promise.all(services.map(service => this.getStatusFromStandardApi(service)));
}
async printToTerminal() {
override async printToTerminal() {
const statuses = await this.data;
const serviceNameMinLength = Math.max(...statuses.map(service => service.name.length));
info.group(bold('Service Statuses'));
+2 -1
View File
@@ -8,9 +8,10 @@
import {Argv} from 'yargs';
import {CheckModule} from './check/cli';
import {HandoffModule} from './handoff/cli';
/** Build the parser for the caretaker commands. */
export function buildCaretakerParser(yargs: Argv) {
return yargs.command(CheckModule);
return yargs.command(CheckModule).command(HandoffModule);
}
+6
View File
@@ -9,7 +9,13 @@
import {assertNoErrors, getConfig, NgDevConfig} from '../utils/config';
export interface CaretakerConfig {
/** Github queries showing a snapshot of pulls/issues caretakers need to monitor. */
githubQueries?: {name: string; query: string;}[];
/**
* The Github group used to track current caretakers. A second group is assumed to exist with the
* name "<group-name>-roster" containing a list of all users eligible for the caretaker group.
* */
caretakerGroup?: string;
}
/** Retrieve and validate the config as `CaretakerConfig`. */
+36
View File
@@ -0,0 +1,36 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Argv, CommandModule} from 'yargs';
import {addGithubTokenOption} from '../../utils/git/github-yargs';
import {updateCaretakerTeamViaPrompt} from './update-github-team';
export interface CaretakerHandoffOptions {
githubToken: string;
}
/** Builds the command. */
function builder(yargs: Argv) {
return addGithubTokenOption(yargs);
}
/** Handles the command. */
async function handler() {
await updateCaretakerTeamViaPrompt();
}
/** yargs command module for assisting in handing off caretaker. */
export const HandoffModule: CommandModule<{}, CaretakerHandoffOptions> = {
handler,
builder,
command: 'handoff',
describe: 'Run a handoff assistant to aide in moving to the next caretaker',
};
@@ -0,0 +1,132 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {prompt} from 'inquirer';
import {debug, green, info, red, yellow} from '../../utils/console';
import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client';
import {getCaretakerConfig} from '../config';
/** Update the Github caretaker group, using a prompt to obtain the new caretaker group members. */
export async function updateCaretakerTeamViaPrompt() {
/** Caretaker specific configuration. */
const caretakerConfig = getCaretakerConfig().caretaker;
if (caretakerConfig.caretakerGroup === undefined) {
throw Error('`caretakerGroup` is not defined in the `caretaker` config');
}
/** The list of current members in the group. */
const current = await getGroupMembers(caretakerConfig.caretakerGroup);
/** The list of members able to be added to the group as defined by a separate roster group. */
const roster = await getGroupMembers(`${caretakerConfig.caretakerGroup}-roster`);
const {
/** The list of users selected to be members of the caretaker group. */
selected,
/** Whether the user positively confirmed the selected made. */
confirm
} =
await prompt([
{
type: 'checkbox',
choices: roster,
message: 'Select 2 caretakers for the upcoming rotation:',
default: current,
name: 'selected',
prefix: '',
validate: (selected: string[]) => {
if (selected.length !== 2) {
return 'Please select exactly 2 caretakers for the upcoming rotation.';
}
return true;
},
},
{
type: 'confirm',
default: true,
prefix: '',
message: 'Are you sure?',
name: 'confirm',
}
]);
if (confirm === false) {
info(yellow(' ⚠ Skipping caretaker group update.'));
return;
}
if (JSON.stringify(selected) === JSON.stringify(current)) {
info(green(' √ Caretaker group already up to date.'));
return;
}
try {
await setCaretakerGroup(caretakerConfig.caretakerGroup, selected);
} catch {
info(red(' ✘ Failed to update caretaker group.'));
return;
}
info(green(' √ Successfully updated caretaker group'));
}
/** Retrieve the current list of members for the provided group. */
async function getGroupMembers(group: string) {
/** The authenticated GitClient instance. */
const git = AuthenticatedGitClient.get();
return (await git.github.teams.listMembersInOrg({
org: git.remoteConfig.owner,
team_slug: group,
}))
.data.filter(_ => !!_)
.map(member => member!.login);
}
async function setCaretakerGroup(group: string, members: string[]) {
/** The authenticated GitClient instance. */
const git = AuthenticatedGitClient.get();
/** The full name of the group <org>/<group name>. */
const fullSlug = `${git.remoteConfig.owner}/${group}`;
/** The list of current members of the group. */
const current = await getGroupMembers(group);
/** The list of users to be removed from the group. */
const removed = current.filter(login => !members.includes(login));
/** Add a user to the group. */
const add = async (username: string) => {
debug(`Adding ${username} to ${fullSlug}.`);
await git.github.teams.addOrUpdateMembershipForUserInOrg({
org: git.remoteConfig.owner,
team_slug: group,
username,
role: 'maintainer',
});
};
/** Remove a user from the group. */
const remove = async (username: string) => {
debug(`Removing ${username} from ${fullSlug}.`);
await git.github.teams.removeMembershipForUserInOrg({
org: git.remoteConfig.owner,
team_slug: group,
username,
});
};
debug.group(`Caretaker Group: ${fullSlug}`);
debug(`Current Membership: ${current.join(', ')}`);
debug(`New Membership: ${members.join(', ')}`);
debug(`Removed: ${removed.join(', ')}`);
debug.groupEnd();
// Add members before removing to prevent the account performing the action from removing their
// permissions to change the group membership early.
await Promise.all(members.map(add));
await Promise.all(removed.map(remove));
debug(`Successfuly updated ${fullSlug}`);
}

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