Compare commits

...

64 Commits
8.2.2 ... 7.1.2

Author SHA1 Message Date
11d2a8cc81 release: cut the v7.1.2 release 2018-12-06 15:08:57 -08:00
ad106abece build: introduce remote bazel caching (#27358)
This PR introduces:

1. Google Cloud Store bucket which contains build artifacts
2. Documentation on how to enable remote caching in development

Each team member should download a service key. More convenient ways of authentication would be more obscure and prevent us from doing identity tracking of the produced artifacts.

PR Close #27358
2018-12-06 11:25:03 -08:00
84f2928c8c fix(compiler-cli): ngtsc shim files not being generated on case-insensitive platforms (#27466)
Common insensitive platforms are `win32/win64` (see:
[here](3e4c5c95ab/src/compiler/sys.ts (L681-L682)))

Currently when running `bazel build packages/core --define=compile=aot`, the `compiler-cli` will throw because it cannot find the `index.ngfactory.ts` file in the compiler host. This is because the shim host wrapper is not properly generating the requested `ngfactory` file.

This happens because we call `getCanonicalFileName` that returns a path that is different to the actual program filenames that are used to construct a map of generated files. Since the generators always use the paths which are not "canonical" and pases them internally like that, we can just stop manually calling `getCanonicalFileName`.

PR Close #27466
2018-12-06 09:24:53 -08:00
610472bf3b Revert "fix(router): change processing url tree children condition (#26243)" (#27516)
This reverts commit ccc77ca441.

Breaks Pantheon see cl/224256517.

PR Close #27516
2018-12-06 09:17:21 -08:00
7bed896f11 Revert "fix(router): process empty path segment when preceding a named outlet (#26243)" (#27516)
This reverts commit 20cef5078d.

Breaks Pantheon see cl/224256517.

PR Close #27516
2018-12-06 09:17:21 -08:00
d7c72fced7 build: remove obsolete gulp build task (#27386)
PR Close #27386
2018-12-05 20:55:33 -08:00
3ca5de7efd ci: don't run node unit tests on travis (#27386)
we run all these tests on CircleCI with bazel.

PR Close #27386
2018-12-05 20:55:33 -08:00
485e2a147a test(benchpress): make most of the tests run under bazel (#27386)
PR Close #27386
2018-12-05 20:55:33 -08:00
b24f1984f3 ci: remove validate-commit-message tests from travis (#27386)
we alredy run them via bazel.

I also removed a bunch of obsolete files that bazel doesn't need.

PR Close #27386
2018-12-05 20:55:33 -08:00
f8846ef14e docs: remove obsolete packages/examples/web_workers/ts/.gitkeep (#27386)
PR Close #27386
2018-12-05 20:55:33 -08:00
9a93259b64 test: correct bazel visibility for @angular/private/testing (#27386)
we don't want anyone else to depened on this stuff.

PR Close #27386
2018-12-05 20:55:33 -08:00
194f1f084f test(service-worker): run the remaining service-worker tests under bazel (#27386)
PR Close #27386
2018-12-05 20:55:33 -08:00
fba9fa2302 test(common): run @angular/common/http/testing tests under bazel (#27386)
PR Close #27386
2018-12-05 20:55:32 -08:00
820e2027e0 ci: don't run router tests on travis (#27386)
we already run them on circle under bazel

PR Close #27386
2018-12-05 20:55:32 -08:00
0508143128 build: add kara to more approval lists (#27493)
PR Close #27493
2018-12-05 14:41:50 -08:00
a97fbfd823 refactor(docs-infra): remove unused custom element (#27250)
PR Close #27250
2018-12-05 13:26:28 -08:00
e552cadc90 fix(docs-infra): do not use an Angular element in hard-coded FETCH_ERROR document (#27250)
The `FETCH_ERROR` document is used when we are unable to retrieve a
document (except for 404 errors), which includes when there is no
internet connection. Using the `<current-location>` element in the
document's template to show the path of the page we failed to retrieve
assumes that the element's bundle is available (e.g. cached by the SW)
or can be fetched from the server.

When none of these conditions is met, the `DocViewer` is unable to
prepare the document and fails, never showing the `FETCH_ERROR` page to
the user.

Furthermore, the path we are looking to retrieve via
`<current-location>` is essentially the document ID, which we already
have. Thus, loading and instantiating a whole component just for that is
overkill.

This commit addresses both issues by getting rid of the
`<current-location>` component and directly embedding the document ID
into the `FETCH_ERROR` content.

PR Close #27250
2018-12-05 13:26:28 -08:00
35ab809326 fix(docs-infra): fix sidenav positioning when notification is shown (#27250)
_Before:_
![sidenav-scrollbar-before](https://user-images.githubusercontent.com/8604205/49089078-62519d00-f263-11e8-8369-f39e73dcc239.png)

_After:_
![sidenav-scrollbar-after](https://user-images.githubusercontent.com/8604205/49089077-62519d00-f263-11e8-8a94-0c34044c4ba1.png)

PR Close #27250
2018-12-05 13:26:28 -08:00
919ef66a7c build(docs-infra): remove dependency on FontAwesome (#27250)
We were only using two FontAwesome icons (`link` and `twitter`). The
twitter icon is already available as an SVG (used in the topbar) and a
similar link icon is available via 'Material Icons', which we are
already brining in.

This commit removes the dependency on FontAwesome and uses the available
icons instead.

_Before:_
![contributor-info-before](https://user-images.githubusercontent.com/8604205/49089076-61b90680-f263-11e8-8c5f-c52d332e6e64.png)

_After:_
![contributor-info-after](https://user-images.githubusercontent.com/8604205/49089075-61b90680-f263-11e8-9785-b8df15aaacd3.png)

PR Close #27250
2018-12-05 13:26:28 -08:00
a37c65827a fix(docs-infra): correctly cache footer image by the SW (#27250)
When using relative paths for CSS resources (such as background images),
`@angular/cli` will move them to the root `dist/` directory (and update
the paths in CSS accordingly). This results in the SW being unable to
cache the resource, because it is not where it expects it to be.

This commit fixes this issue for the footer background image, by using
an absolute path for the URL. (It also removes an unused style that
would have been affected by the same issue.)

PR Close #27250
2018-12-05 13:26:28 -08:00
1371cf6d33 fix(docs-infra): ensure material icons are cached for offline access (#27250)
In order for 'Material Icons' to work offline, their `.woff2` file needs
to have been cached by the SW. This file is not requested by the
browser, until an element needs to use the icon font.

In order to speed up the initial page load and avoid FOUC, we use
inlined SVGs for all icons in the app shell. As a result, the `.woff2`
file may not be requested, when a user visits angular.io. If they go
offline before visiting a page that does actually use 'Material Icons',
then such icons will not work correctly (e.g. the `error_outline` icon
used in the error page for failed requests due to network
unanvailability).

This commit fixes this, by adding a non-visible element that needs the
'Material Icons' font on the main component. Thids ensures that the
`.woff2` file will always be loaded, even if the page does not use any
material icons.

(Note: The element is inserted lazily to avoid affecting the initial
rendering.)

PR Close #27250
2018-12-05 13:26:28 -08:00
e9655720f8 fix(docs-infra): remove hard-coded color from inlined SVG icons (#27250)
This allows the icons to inherit the color of their HTMLElement parent.

PR Close #27250
2018-12-05 13:26:28 -08:00
8512e34521 fix(docs-infra): inline SVG icons used in page load sensitive UI (#27250)
These icons are part of the app shell and used on every load (on both
desktop and mobile). Inlining them ensures they are rendered asap.

PR Close #27250
2018-12-05 13:26:28 -08:00
21c9cfff5a fix(docs-infra): always fetch Roboto font (#27250)
Previously, we did not load the Roboto font, instead relying on the user
to have it available on their system and falling back to different fonts
otherwise. This resulted in the page being styled slightly differently
for those people that didn't have the font installed locally.

PR Close #27250
2018-12-05 13:26:28 -08:00
e902f5ee6a fix(docs-infra): do not create an anchor for the file-not-found header (#27250)
PR Close #27250
2018-12-05 13:26:28 -08:00
013a241b94 refactor(docs-infra): move minified lunr script to the generated directory (#27250)
PR Close #27250
2018-12-05 13:26:27 -08:00
0d0bc1f725 build: error when files specified in payload size limits are missing (#27250)
PR Close #27250
2018-12-05 13:26:27 -08:00
a655d288ca ci: test ts-api-guardian on windows (#27205)
PR Close #27205
2018-12-05 12:49:55 -08:00
e55088a364 build: to fsevents@2.0.1 (#27469)
the old version was failing to compile on MacOS Mojave 10.14.1.

PR Close #27469
2018-12-05 10:48:20 -08:00
2e41631026 build(bazel): replace yarn_install(name = "npm") with @npm local_reporsitory() to speed up build (#27469)
PR Close #27469
2018-12-05 10:48:20 -08:00
2bc85fb77e fix(router): process empty path segment when preceding a named outlet (#26243)
PR Close #10726

PR Close #26243
2018-12-05 10:39:30 -08:00
8167bfc87c fix(router): change processing url tree children condition (#26243)
stop adding next path of pathless activated route to the url

PR Close #26224

PR Close #26243
2018-12-05 10:39:30 -08:00
711ef2ded4 build: update to newest ibazel (#27441)
this supports the --define flag which we use for Ivy development

PR Close #27441
2018-12-04 20:00:06 -08:00
5c57920dbb fix(docs-infra): log the successful creation of previews (#27436)
This can help with debugging issues, e.g. with the communication between
the preview server and CI, as it gives a better idea of exactly when was
the preview made available and how long it took.

PR Close #27436
2018-12-04 19:59:25 -08:00
9b4d95974a fix(bazel): do not throw if ts compile action does not create esm5 outputs (#27401)
In some applications, developers define a `ts_library` that just consists of `d.ts` files (e.g. to type `module.id`; see: https://github.com/angular/material2/blob/master/src/module-typings.d.ts), and expect the `esm5.bzl` file to not throw an error like:

```
  target.typescript.replay_params.outputs
struct' object has no attribute 'outputs'
```

The "replay_parameters" property will exist in that case, but is set to "None" because there is no action that should be replayed in favor of producing ES5 outputs. See: https://github.com/bazelbuild/rules_typescript/pull/326. Notice that this right now breaks similarly because an empty `struct()` is returned that does not have a property called `outputs`. [#326](https://github.com/bazelbuild/rules_typescript/pull/326) fixes that by being explicit that there is no _action_ at all.

PR Close #27401
2018-12-04 19:58:36 -08:00
8087b6b611 fix(compiler-cli): flatModuleIndex files not generated on windows with multiple input files (#27200)
* Currently when building a `ng_module` with Bazel and having the flat module id option set, the flat module files are not being generated because `@angular/compiler-cli` does not properly determine the entry-point file.

Note that this logic is not necessarily specific to Bazel and the same problem can happen without Bazel if multiple TypeScript input files are specified while the `flatModuleIndex` option has been enabled.

PR Close #27200
2018-12-04 14:01:25 -08:00
1ca292392b fix(bazel): ng_package cannot be run multiple times without clean (#27200)
Currently when building the `ng_package` multiple times, the old `ng_package` output will be copied over to the new `ng_package` content. Resulting in packages like `src/cdk/npm_package/npm_package/npm_package/AND_MORE`.

This happens because currently all TypeScript definition files are resolved from within the `binDir`. This is just wrong because it could then take up the `d.ts` files from the previous `ng_package` output. All typescript definitions that belong to the target package, should be resolved through Bazel and copied based on that computation.

Also fixes that `esm` files aren't written to the `ng_package` on Windows. This is because we try to flatten paths using the `path.delimiter` while the path is always using Posix delimiters (causing the paths to be incorrect)

PR Close #27200
2018-12-04 14:01:25 -08:00
079c4b3482 fix(bazel): do not throw error when writing tsickle externs (#27200)
* Currently when building the ES5 and ES2015 output, `ngc_wrapped` will fail because it tries to write the `fs.openSync` the tsickle output file at the same time. This causes a runtime exception in Windows and can be fixed by just writing the externs for ES5 mode to the proper ES5 "output root".

PR Close #27200
2018-12-04 14:01:25 -08:00
e476c38dee fix(bazel): ng_package not generating UMD bundles on windows (#27200)
* Fixes that `ng_package` does not work generate UMD bundles on Windows because the `esm5/` files are not written to the output directory. This is because `rootDirs` and `rootDir` are posix paths and cause invalid relative paths when mixed with Windows backslash paths.

PR Close #27200
2018-12-04 14:01:25 -08:00
8799ea7ea0 ci(docs-infra): manually trigger the preview server webhook (#27458)
With this change, we no longer depend on CircleCI to trigger the webhook
(which it sometimes does with considerable delay or not at all).

This has the added benefit that other jobs will not unnecessarily
trigger webhooks and spam the preview server logs. It is only the
`aio_preview` job's webhook that we care about.

Related to #27352.

PR Close #27458
2018-12-04 13:59:54 -08:00
03787924da docs: fix typo in toh-pt6.md (#27403)
PR Close #27403
2018-12-03 08:24:19 -08:00
1022db1c8c test(common): add PercentPipe round and trim tests (#27365)
Add tests to cover the percent's decimal to be rounded and trimmed.
PR Close #27365
2018-12-03 08:22:25 -08:00
560cb99f55 docs(common): update PercentPipe default maxFractionDigits value (#27365)
Change the docs to reflect the actual default value

Fixes #27079
PR Close #27365
2018-12-03 08:22:25 -08:00
5acfdee3ca build: only stamp version info when releasing (#27362)
Also build releases into a dedicated output_base so you can't
accidentally publish with outdated version stamp.

Bump the version of rules_nodejs so we don't need to create the
symlink_prefixes for the .publish command to work.

PR Close #27362
2018-11-30 16:08:23 -08:00
fc2c23ef4b fix(bazel): ng_package should correctly map to source maps in secondary entry-points (#27313)
This fixes the issue with broken source maps for @angular/common/http/testing.

Fixes #25510

PR Close #27313
2018-11-30 13:40:01 -08:00
1ddc34cbc5 build(bazel): update handling of rules_nodejs transitive deps (#27264)
BREAKING CHANGES:

Bazel users: rules_angular_dependencies() will no longer install transitive dependencies of build_bazel_rules_nodejs and build_bazel_rules_typescript. User WORKSPACE files will now need to install rules_nodejs and rules_typescript transitive deps directly:

```
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
rules_typescript_dependencies()

load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
rules_nodejs_dependencies()
```

PR Close #27264
2018-11-30 13:35:52 -08:00
184d63d91d docs: fix dynamic-component-loader example for Adblock Plus + EasyList (#27212)
Reported issue in #18138 is due to EasyList being selected in ABP. This commit fixes both the image at the bottom of the Dynamic Component Loader example, and the Stackblitz demo.

Fixes #18138

PR Close #27212
2018-11-30 13:35:38 -08:00
236ac060b0 fix(platform-server): add @angular/http to the list of peerDependencies (#27307)
Fixes #26154

PR Close #27307
2018-11-30 10:02:44 -08:00
2cce8d4ebc docs: fix typo (#27294)
PR Close #27294
2018-11-29 22:15:28 -08:00
a149c3a8db docs(forms): update API reference for common APIs and template-driven directives (#27033)
PR Close #27033
2018-11-29 21:33:08 -08:00
013c0ae2e1 style: change style css syntax (#27253)
PR Close #27253
2018-11-29 21:26:53 -08:00
c8aebaeb76 build: Replace iteration over depsets with an explicit .to_list() call. (#27336)
PR Close #27336
2018-11-29 21:22:39 -08:00
56254b53bd build: add kara to approvers for packages needing ivy TestBed updates (#27337)
PR Close #27337
2018-11-29 21:22:24 -08:00
5d0e1147df docs: move Minko to Angular (#27339)
Joined the team at Google about a month ago 

PR Close #27339
2018-11-29 21:21:54 -08:00
a0f239fc71 docs: move past events on events page (#27342)
Moves events that have already happened to the list of past events.

PR Close #27342
2018-11-29 21:21:24 -08:00
88032eb302 docs: Minor: insert missing space (#27213)
PR Close #27213
2018-11-28 11:41:21 -08:00
827e223edb docs: replace ChromeNoSandbox by ChromeHeadlessCI (#27304)
the custom launcher name should be named ChromeHeadlessCI instead of ChromeNoSandbox.
PR Close #27304
2018-11-28 11:40:03 -08:00
14d75d6971 docs: add instructions to diagnose slow Bazel builds (#27324)
PR Close #27324
2018-11-28 11:39:38 -08:00
8282e15c2b release: cut the v7.1.1 release 2018-11-28 10:09:48 -08:00
bdf5f3e499 fix(core): export a value for InjectFlags (#27279)
A recent commit (probably 2c7386c) has changed the import graph of the
DI types in core, and somehow results in the ngc compiler deciding to
re-export core DI types from application factories which tangentially
use inject(). This is not really surprising; ngc's import graph can be
very unstable.

However, this results in a re-export of InjectFlags surviving JS
compilation. InjectFlags was a const enum, akin to an interface in TS,
with no runtime repesentation. This causes a warning to be emitted by
Webpack when it sees the re-export of InjectFlags.

This commit avoids the issue by removing 'const' from the declaration
of InjectFlags, causing it to have a runtime value. This is a temporary
fix. The real fix will be for ngc to no longer write exports of const
enums.

Testing strategy: manually verified. Due to the problem only manifesting
when recompiling after a change and then running Webpack, there is no
existing framework via which this could be easily tested with an
integration test. Additionally, the potential for this issue is gone in
Ivy, so this solution is only temporarily needed.

Fixes #27251.

PR Close #27279
2018-11-27 13:40:39 -08:00
a71038b5fa build(docs-infra): upgrade npm-run-all to latest version for security (#27274)
Earlier versions may transitively depend on a malicious version of
`flatmap-stream` (see dominictarr/event-stream#116).

The `aio-builds-setup/` had an older version of `event-stream` (3.3.4),
which did not depend on `flatmap-stream`, but upgraded it anyway.

PR Close #27274
2018-11-27 13:38:36 -08:00
d735160a11 fix(docs-infra): don't call setSearch when not clicking in the searchBox and no searchResults (#26590)
Fix to call locationService.setSearch less often to avoid unnecessary
downloading of favicons

Fixes #26544

PR Close #26590
2018-11-27 13:38:28 -08:00
498c4c32b1 docs: add forms terms to glossary (#27075)
PR Close #27075
2018-11-27 13:38:20 -08:00
b9c7da6503 build: fix source-map warnings for ts-api-guardian (#27098)
* Fixes that running `ts-api-guardian` targets always causes source map warnings to appear.

PR Close #27098
2018-11-27 13:38:13 -08:00
131 changed files with 1676 additions and 4352 deletions

View File

@ -1,3 +1,11 @@
# Load any settings specific to the current user
try-import .bazelrc.user
################################
# Settings for Angular team members only
################################
# To enable this feature check the "Remote caching" section in docs/BAZEL.md.
build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-team-cache
###############################
# Typescript / Angular / Sass #
###############################
@ -30,10 +38,12 @@ test --nolegacy_external_runfiles
###############################
# Release support #
# Turn on these settings with #
# --config=release #
###############################
# Releases should always be stamped with version control info
build --workspace_status_command=./tools/bazel_stamp_vars.sh
build:release --workspace_status_command=./tools/bazel_stamp_vars.sh
###############################
# Output #

42
.buildkite/Dockerfile Normal file
View File

@ -0,0 +1,42 @@
# Heavily based on https://github.com/StefanScherer/dockerfiles-windows/ images.
# Combines the node windowsservercore image with the Bazel Prerequisites (https://docs.bazel.build/versions/master/install-windows.html).
# msys install taken from https://github.com/StefanScherer/dockerfiles-windows/issues/30
# VS redist install taken from https://github.com/StefanScherer/dockerfiles-windows/blob/master/apache/Dockerfile
# The nanoserver image won't work because MSYS2 does not run in it https://github.com/Alexpux/MSYS2-packages/issues/1493
# Before building this image, you must locally build node-windows:10.13.0-windowsservercore-1803.
# Clone https://github.com/StefanScherer/dockerfiles-windows/commit/4ce7101a766b9b880ac262479dd9126b64d656cf and build using
# docker build -t node-windows:10.13.0-windowsservercore-1803 --build-arg core=microsoft/windowsservercore:1803 --build-arg target=microsoft/windowsservercore:1803 .
FROM node-windows:10.13.0-windowsservercore-1803
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# Install 7zip to extract msys2
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe
# For some reason the last letter in the destination directory is lost. So '/D=C:\\7zip0' will extract to '/D=C:\\7zip'.
RUN Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait
# Extract msys2
RUN Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait
RUN Remove-Item msys2.tar.xz
RUN Remove-Item msys2.tar
RUN Remove-Item 7z.exe
RUN Remove-Item -Recurse 7zip
# Add MSYS2 to PATH, and set BAZEL_SH
RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine)
RUN [Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
# Install Microsoft Visual C++ Redistributable for Visual Studio 2015
RUN Invoke-WebRequest -UseBasicParsing 'https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe' -OutFile vc_redist.x64.exe
RUN Start-Process 'c:\\vc_redist.x64.exe' -ArgumentList '/Install', '/Passive', '/NoRestart' -NoNewWindow -Wait
RUN Remove-Item vc_redist.x64.exe
# Add a fix for https://github.com/docker/for-win/issues/2920 as entry point to the container.
SHELL ["cmd", "/c"]
COPY "fix-msys64.cmd" "C:\\fix-msys64.cmd"
ENTRYPOINT cmd /C C:\\fix-msys64.cmd && cmd /c
CMD ["cmd.exe"]

96
.buildkite/README.md Normal file
View File

@ -0,0 +1,96 @@
# BuildKite configuration
This folder contains configuration for the [BuildKite](https://buildkite.com) based CI checks for
this repository.
BuildKite is a CI provider that provides build coordination and reports while we provide the
infrastructure.
CI runs are triggered by new PRs and will show up on the GitHub checks interface, along with the
other current CI solutions.
Currently it is only used for tests on Windows platforms.
## The build pipeline
BuildKite uses a pipeline for each repository. The `pipeline.yml` file defines pipeline
[build steps](https://buildkite.com/docs/pipelines/defining-steps) for this repository.
Run results can be seen in the GitHub checks interface and in the
[pipeline dashboard](https://buildkite.com/angular/angular).
Although most configuration is done via `pipeline.yml`, some options are only available
in the online [pipeline settings](https://buildkite.com/angular/angular/settings).
## Infrastructure
BuildKite does not provide the host machines where the builds runs, providing instead the
[BuildKite Agent](https://buildkite.com/docs/agent/v3) that should be run our own infrastructure.
### Agents
This agent polls the BuildKite API for builds, runs them, and reports back the results.
Agents are the unit of concurrency: each agent can run one build at any given time.
Adding agents allows more builds to be ran at the same time.
Individual agents can have tags, and pipeline steps can target only agents with certain tags via the
`agents` field in `pipeline.yml`.
For example: agents on Windows machines are tagged as `windows`, and the Windows specific build
steps list `windows: true` in their `agents` field.
You can see the current agent pool, along with their tags, in the
[agents list](https://buildkite.com/organizations/angular/agents).
### Our host machines
We use [Google Cloud](https://cloud.google.com/) as our cloud provider, under the
[Angular project](https://console.cloud.google.com/home/dashboard?project=internal-200822).
To access this project you need need to be logged in with a Google account that's a member of
team@angular.io.
For googlers this may be your google.com account, for others it is an angular.io account.
In this project we have a number of Windows VMs running, each of them with several agents.
The `provision-windows-buildkite.ps1` file contains instructions on how to create new host VMs that
are fully configured to run the BuildKite agents as services.
Our pipeline uses [docker-buildkite-plugin](https://github.com/buildkite-plugins/docker-buildkite-plugin)
to run build steps inside docker containers.
This way we achieve isolation and hermeticity.
The `Dockerfile` file describes a custom Docker image that includes NodeJs, Yarn, and the Bazel
pre-requisites on Windows.
To upload a new version of the docker image, follow any build instructions in `Dockerfile` and then
run `docker build -t angular/node-bazel-windows:NEW_VERSION`, followed by
`docker push angular/node-bazel-windows:NEW_VERSION`.
After being pushed it should be available online, and you can use the new version in `pipeline.yml`.
## Caretaker
BuildKite status can be found at https://www.buildkitestatus.com/.
Issues related to the BuildKite setup should be escalated to the Tools Team via the current
caretaker, followed by Alex Eagle and Filipe Silva.
Support requests should be submitted via email to support@buildkite.com and cc Igor, Misko, Alex,
Jeremy and Manu
## Rollout strategy
At the moment our BuildKite CI uses 1 host VM running 4 agents, thus being capable of 4 concurrent
builds.
The only test running is `bazel test //tools/ts-api-guardian:all`, and the PR check is not
mandatory.
In the future we should add cache support to speed up the initial `yarn` install, and also Bazel
remote caching to speed up Bazel builds.
After the current setup is verified as stable and reliable the GitHub PR check can become mandatory.
The tests ran should also be expanded to cover most, if not all, of the Bazel tests.

View File

@ -0,0 +1,6 @@
@echo off
REM Fix for https://github.com/docker/for-win/issues/2920
REM echo "Fixing msys64 folder..."
REM Touch all .dll files inside C:\msys64\
forfiles /p C:\msys64\ /s /m *.dll /c "cmd /c Copy /B @path+,, >NUL"
REM echo "Fixed msys64 folder."

10
.buildkite/pipeline.yml Normal file
View File

@ -0,0 +1,10 @@
steps:
- label: windows-test
commands:
- "yarn install --frozen-lockfile --non-interactive --network-timeout 100000"
- "yarn bazel test //tools/ts-api-guardian:all --noshow_progress"
plugins:
- docker#v2.1.0:
image: "filipesilva/node-bazel-windows:0.0.2"
agents:
windows: true

View File

@ -0,0 +1,92 @@
# PowerShell script to provision a Windows Server with BuildKite
# This script follows https://buildkite.com/docs/agent/v3/windows.
# Instructions
# VM creation:
# In Google Cloud Platform, create a Compute Engine instance.
# We recommend machine type n1-highcpu-16 (16 vCPUs, 14.4 GB memory).
# Use a windows boot disk with container support such as
# "Windows Server version 1803 Datacenter Core for Containers".
# Give it a name, then click "Create".
# VM setup:
# In the Compute Engine menu, select "VM Instances". Click on the VM name you chose before.
# Click "Set Windows Password" to choose a username and password.
# Click RDP to open a remote desktop via browser, using the username and password.
# In the Windows command prompt start an elevated powershell by inputing
# "powershell -Command "Start-Process PowerShell -Verb RunAs" followed by Enter.
# Download and execute this script from GitHub, passing the token (mandatory), tags (optional)
# and number of agents (optional) as args:
# ```
# Invoke-WebRequest -Uri https://raw.githubusercontent.com/angular/angular/master/.buildkite/provision-windows-buildkite.ps1 -OutFile provision.ps1
# .\provision.ps1 -token "MY_TOKEN" -tags "windows=true,another_tag=true" -agents 4
# ```
# The VM should restart and be fully configured.
# Creating extra VMs
# You can create an image of the current VM by following the instructions below.
# https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image
# Then create a new VM and choose "Custom images".
# Script proper.
# Get the token and tags from arguments.
param (
[Parameter(Mandatory=$true)][string]$token,
[string]$tags = ""
[Int]$agents = 1
)
# Allow HTTPS
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
# Helper to add to PATH.
# Will take current PATH so avoid running it after anything to modifies only the powershell session path.
function Add-Path ([string]$newPathItem) {
$Env:Path+= ";" + $newPathItem + ";"
[Environment]::SetEnvironmentVariable("Path",$env:Path, [System.EnvironmentVariableTarget]::Machine)
}
# Install Git for Windows
Write-Host "Installing Git for Windows."
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.19.1.windows.1/Git-2.19.1-64-bit.exe -OutFile git.exe
.\git.exe /VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh" /DIR="C:\git"
Add-Path "C:\git\bin"
Remove-Item git.exe
# Download NSSM (https://nssm.cc/) to run the BuildKite agent as a service.
Write-Host "Downloading NSSM."
Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -OutFile nssm.zip
Expand-Archive -Path nssm.zip -DestinationPath C:\nssm
Add-Path "C:\nssm\nssm-2.24-101-g897c7ad\win64"
Remove-Item nssm.zip
# Run the BuildKite agent install script
Write-Host "Installing BuildKite agent."
$env:buildkiteAgentToken = $token
$env:buildkiteAgentTags = $tags
Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/buildkite/agent/master/install.ps1'))
# Configure the BuildKite agent clone and timestamp behavior
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ngit-clone-flags=--config core.autocrlf=input --config core.eol=lf --config core.longpaths=true --config core.symlinks=true`n"
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ntimestamp-lines=true`n"
# Register the BuildKite agent service using NSSM, so that it persists through restarts and is
# restarted if the process dies.
for ($i=1; $i -le $agents; $i++)
{
$agentName = "buildkite-agent-$i"
Write-Host "Registering $agentName as a service."
nssm.exe install $agentName "C:\buildkite-agent\bin\buildkite-agent.exe" "start"
nssm.exe set $agentName AppStdout "C:\buildkite-agent\$agentName.log"
nssm.exe set $agentName AppStderr "C:\buildkite-agent\$agentName.log"
nssm.exe status $agentName
nssm.exe start $agentName
nssm.exe status $agentName
}
# Restart the machine.
Restart-Computer

View File

@ -275,6 +275,7 @@ jobs:
# The `destination` needs to be kept in synch with the value of
# `AIO_ARTIFACT_PATH` in `aio/aio-builds-setup/Dockerfile`
destination: aio/dist/aio-snapshot.tgz
- run: node ./aio/scripts/create-preview $CIRCLE_BUILD_NUM
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
test_aio_preview:
@ -461,7 +462,3 @@ workflows:
branches:
only:
- master
notify:
webhooks:
- url: https://ngbuilds.io/circle-build

View File

@ -0,0 +1,107 @@
#!/usr/bin/env node
/**
* Usage (cli):
* ```
* node create-preview <build-number> <job-name> <webhook-url>
* ```
*
* Usage (JS):
* ```js
* require('./trigger-webhook').
* triggerWebhook(buildNumber, jobName, webhookUrl).
* then(...);
* ```
*
* Triggers a notification webhook with CircleCI specific info.
*
* It can be used for notifying external servers and trigger operations based on CircleCI job status
* (e.g. triggering the creation of a preview based on previously stored build atrifacts).
*
* The body of the sent payload is of the form:
* ```json
* {
* "payload": {
* "build_num": ${buildNumber}
* "build_parameters": {
* "CIRCLE_JOB": "${jobName}"
* }
* }
* }
* ```
*
* When used from JS, it returns a promise which resolves to an object of the form:
* ```json
* {
* "statucCode": ${statusCode},
* "responseText": "${responseText}"
* }
* ```
*
* NOTE:
* - When used from the cli, the command will exit with an error code if the response's status code
* is outside the [200, 400) range.
* - When used from JS, the returned promise will be resolved, even if the response's status code is
* outside the [200, 400) range. It is up to the caller to decide how this should be handled.
*/
// Imports
const {request} = require('https');
// Exports
module.exports = {
triggerWebhook,
};
// Run
if (require.resolve === module) {
_main(process.argv.slice(2));
}
// Helpers
function _main(args) {
triggerWebhook(...args).
then(({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`))).
catch(err => {
console.error(err);
process.exit(1);
});
}
function postJson(url, data) {
return new Promise((resolve, reject) => {
const opts = {method: 'post', headers: {'Content-Type': 'application/json'}};
const onResponse = res => {
const statusCode = res.statusCode || -1;
let responseText = '';
res.
on('error', reject).
on('data', d => responseText += d).
on('end', () => resolve({statusCode, responseText}));
};
request(url, opts, onResponse).
on('error', reject).
end(JSON.stringify(data));
});
}
async function triggerWebhook(buildNumber, jobName, webhookUrl) {
if (!buildNumber || !jobName || !webhookUrl || isNaN(buildNumber)) {
throw new Error(
'Missing or invalid arguments.\n' +
'Expected: buildNumber (number), jobName (string), webhookUrl (string)');
}
const data = {
payload: {
build_num: +buildNumber,
build_parameters: {CIRCLE_JOB: jobName},
},
};
return postJson(webhookUrl, data);
}

5
.gitignore vendored
View File

@ -2,6 +2,7 @@
/dist/
/bazel-*
/integration/bazel/bazel-*
e2e_test.*
node_modules
bower_components
@ -29,3 +30,7 @@ yarn-error.log
# rollup-test output
/modules/rollup-test/dist/
# User specific bazel settings
.bazelrc.user

View File

@ -98,6 +98,7 @@ groups:
- IgorMinar #fallback
- mhevery
- vikerman #fallback
- kara
build-and-ci:
conditions:
@ -211,6 +212,7 @@ groups:
- mhevery #fallback
- IgorMinar #fallback
- jenniferfell #docs only
- kara
compiler/i18n:
conditions:
@ -223,6 +225,7 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
- kara
compiler:
conditions:
@ -234,6 +237,7 @@ groups:
- mhevery
- IgorMinar #fallback
- jenniferfell #docs only
- kara
compiler-cli/ngtools:
conditions:
@ -243,6 +247,7 @@ groups:
- hansl
- filipesilva #fallback
- IgorMinar #fallback
- kara
compiler-cli:
conditions:
@ -257,6 +262,7 @@ groups:
- alxhub
- IgorMinar #fallback
- mhevery #fallback
- kara
common:
conditions:
@ -269,6 +275,7 @@ groups:
- pkozlowski-opensource #primary
- IgorMinar #fallback
- mhevery #fallback
- kara
forms:
conditions:
@ -334,6 +341,7 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
- kara
testing:
conditions:
@ -367,6 +375,7 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
- kara
platform-browser:
conditions:
@ -376,6 +385,7 @@ groups:
- mhevery #primary
# needs secondary
- IgorMinar #fallback
- kara
platform-server:
conditions:
@ -398,6 +408,7 @@ groups:
- mhevery #primary
# needs secondary
- IgorMinar #fallback
- kara
service-worker:
conditions:
@ -431,6 +442,7 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
- jenniferfell #docs only
- kara
benchpress:
conditions:

View File

@ -1,3 +1,30 @@
<a name="7.1.2"></a>
## [7.1.2](https://github.com/angular/angular/compare/7.1.1...7.1.2) (2018-12-06)
### Bug Fixes
* **bazel:** do not throw error when writing tsickle externs ([#27200](https://github.com/angular/angular/issues/27200)) ([079c4b3](https://github.com/angular/angular/commit/079c4b3))
* **bazel:** do not throw if ts compile action does not create esm5 outputs ([#27401](https://github.com/angular/angular/issues/27401)) ([9b4d959](https://github.com/angular/angular/commit/9b4d959))
* **bazel:** ng_package cannot be run multiple times without clean ([#27200](https://github.com/angular/angular/issues/27200)) ([1ca2923](https://github.com/angular/angular/commit/1ca2923))
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([e476c38](https://github.com/angular/angular/commit/e476c38))
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([fc2c23e](https://github.com/angular/angular/commit/fc2c23e)), closes [#25510](https://github.com/angular/angular/issues/25510)
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([8087b6b](https://github.com/angular/angular/commit/8087b6b))
* **compiler-cli:** ngtsc shim files not being generated on case-insensitive platforms ([#27466](https://github.com/angular/angular/issues/27466)) ([84f2928](https://github.com/angular/angular/commit/84f2928)), closes [/github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts#L681-L682](https://github.com//github.com/Microsoft/TypeScript/blob/3e4c5c95abd515eb9713b881d27ab3a93cc00461/src/compiler/sys.ts/issues/L681-L682)
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([236ac06](https://github.com/angular/angular/commit/236ac06)), closes [#26154](https://github.com/angular/angular/issues/26154)
<a name="7.1.1"></a>
## [7.1.1](https://github.com/angular/angular/compare/7.1.0...7.1.1) (2018-11-28)
### Bug Fixes
* **core:** export a value for InjectFlags ([#27279](https://github.com/angular/angular/issues/27279)) ([bdf5f3e](https://github.com/angular/angular/commit/bdf5f3e)), closes [#27251](https://github.com/angular/angular/issues/27251)
<a name="7.1.0"></a>
# [7.1.0](https://github.com/angular/angular/compare/7.1.0-rc.0...7.1.0) (2018-11-21)

View File

@ -21,6 +21,14 @@ rules_angular_dependencies()
# These are the dependencies only for us
rules_angular_dev_dependencies()
# Install transitive deps of rules_typescript
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
rules_typescript_dependencies()
# Install transitive deps of rules_nodejs
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
rules_nodejs_dependencies()
#
# Point Bazel to WORKSPACEs that live in subdirectories
#
@ -56,10 +64,9 @@ node_repositories(
yarn_version = "1.12.1",
)
yarn_install(
local_repository(
name = "npm",
package_json = "//tools:npm/package.json",
yarn_lock = "//tools:npm/yarn.lock",
path = "tools/npm_workspace",
)
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")

3
aio/.gitignore vendored
View File

@ -44,6 +44,3 @@ protractor-results*.txt
# System Files
.DS_Store
Thumbs.db
# copied dependencies
src/assets/js/lunr*

View File

@ -41,8 +41,6 @@ Here are the most important tasks you might need to use:
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
## Developing on Windows
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
@ -50,7 +48,7 @@ These unresolved links cause the docs generation process to fail because it cann
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.

View File

@ -7,7 +7,7 @@ import {CircleCiApi} from '../common/circle-ci-api';
import {GithubApi} from '../common/github-api';
import {GithubPullRequests} from '../common/github-pull-requests';
import {GithubTeams} from '../common/github-teams';
import {assert, assertNotMissingOrEmpty, Logger} from '../common/utils';
import {assert, assertNotMissingOrEmpty, computeShortSha, Logger} from '../common/utils';
import {BuildCreator} from './build-creator';
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from './build-events';
import {BuildRetriever} from './build-retriever';
@ -144,7 +144,10 @@ export class PreviewServerFactory {
const artifactPath = await buildRetriever.downloadBuildArtifact(buildNum, pr, sha, cfg.buildArtifactPath);
const isPublic = await buildVerifier.getPrIsTrusted(pr);
await buildCreator.create(pr, sha, artifactPath, isPublic);
res.sendStatus(isPublic ? 201 : 202);
logger.log(`PR:${pr}, SHA:${computeShortSha(sha)}, Build:${buildNum} - ` +
`Successfully created ${isPublic ? 'public' : 'non-public'} preview.`);
} catch (err) {
logger.error('CircleCI webhook error', err);
respondWithError(res, err);

View File

@ -46,7 +46,7 @@
"@types/shelljs": "^0.8.0",
"@types/supertest": "^2.0.5",
"nodemon": "^1.18.3",
"npm-run-all": "^4.1.3",
"npm-run-all": "^4.1.5",
"supertest": "^3.1.0",
"tslint": "^5.11.0",
"tslint-jasmine-noSkipOrFocus": "^1.0.9",

View File

@ -129,7 +129,7 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
dependencies:
@ -384,7 +384,7 @@ chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0:
chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
@ -532,9 +532,10 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^6.0.4:
cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
@ -1630,16 +1631,17 @@ npm-packlist@^1.1.6:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-run-all@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.3.tgz#49f15b55a66bb4101664ce270cb18e7103f8f185"
npm-run-all@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
dependencies:
ansi-styles "^3.2.0"
chalk "^2.1.0"
cross-spawn "^6.0.4"
ansi-styles "^3.2.1"
chalk "^2.4.1"
cross-spawn "^6.0.5"
memorystream "^0.3.1"
minimatch "^3.0.4"
ps-tree "^1.1.0"
pidtree "^0.3.0"
read-pkg "^3.0.0"
shell-quote "^1.6.1"
string.prototype.padend "^3.0.0"
@ -1786,6 +1788,11 @@ pause-stream@0.0.11:
dependencies:
through "~2.3"
pidtree@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b"
integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==
pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"

View File

@ -9,7 +9,7 @@ import { AdComponent } from './ad.component';
selector: 'app-ad-banner',
// #docregion ad-host
template: `
<div class="ad-banner">
<div class="ad-banner-example">
<h3>Advertisements</h3>
<ng-template ad-host></ng-template>
</div>

View File

@ -18,6 +18,6 @@
color: black;
}
.ad-banner {
.ad-banner-example {
width: 400px;
}

View File

@ -7,7 +7,8 @@
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
text-align: center;
margin-bottom: 0;
}
[class*='col-'] {
padding-right: 20px;

View File

@ -17,7 +17,8 @@ button {
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer; cursor: hand;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;

View File

@ -16,7 +16,8 @@ a {
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
text-align: center;
margin-bottom: 0;
}
h4 {
position: relative;

View File

@ -18,7 +18,8 @@ button {
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer; cursor: hand;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;

View File

@ -16,7 +16,8 @@ a {
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
text-align: center;
margin-bottom: 0;
}
h4 {
position: relative;

View File

@ -3,7 +3,7 @@
border-bottom: 1px solid gray;
border-left: 1px solid gray;
border-right: 1px solid gray;
width:195px;
width: 195px;
height: 16px;
padding: 5px;
background-color: white;

View File

@ -16,7 +16,8 @@ a {
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
text-align: center;
margin-bottom: 0;
}
h4 {
position: relative;

View File

@ -18,7 +18,8 @@ button {
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer; cursor: hand;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;

View File

@ -3,7 +3,7 @@
border-bottom: 1px solid gray;
border-left: 1px solid gray;
border-right: 1px solid gray;
width:195px;
width: 195px;
height: 16px;
padding: 5px;
background-color: white;

View File

@ -3,7 +3,7 @@
<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">
<h1 class="no-toc">Page Not Found</h1>
<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>
</div>

View File

@ -192,7 +192,7 @@ Here are two sample components and the `AdComponent` interface for reference:
The final ad banner looks like this:
<figure>
<img src="generated/images/guide/dynamic-component-loader/ads.gif" alt="Ads">
<img src="generated/images/guide/dynamic-component-loader/ads-example.gif" alt="Ads">
</figure>

View File

@ -317,6 +317,30 @@ Within Angular, use [NgModules](guide/glossary#ngmodule) to make public parts av
{@a F}
{@a form-control}
## form control
A instance of `FormControl`, which is a fundamental building block for Angular forms. Together with `FormGroup` and `FormArray`, tracks the value, validation, and status of a form input element.
Read more forms in the [Introduction to forms in Angular](guide/forms-overview).
{@a form-model}
## form model
The "source of truth" for the value and validation status of a form input element at a given point in time. When using [reactive forms](guide/glossary#reactive-forms), the form model is created explicitly in the component class. When using [template-driven forms](guide/glossary#template-driven-forms), the form model is implicitly created by directives.
Learn more about reactive and template-driven forms in the [Introduction to forms in Angular](guide/forms-overview).
{@a form-validation}
## form validation
A check that runs when form values change and reports whether the given values are correct and complete, according to the defined constraints. Reactive forms apply [validator functions](guide/form-validation#adding-to-reactive-forms). Template-driven forms use [validator directives](guide/form-validation#adding-to-template-driven-forms).
To learn more, see [Form Validation](guide/form-validation).
{@a G}
@ -325,6 +349,14 @@ Within Angular, use [NgModules](guide/glossary#ngmodule) to make public parts av
{@a I}
{@a immutability}
## immutability
The ability to alter the state of a value after its creation. [Reactive forms](guide/glossary#reactive-forms) perform immutable changes in that
each change to the data model produces a new data model rather than modifying the existing one. [Template-driven forms](guide/glossary#template-driven-forms) perform mutable changes with `NgModel` and [two-way data binding](guide/glossary#data-binding) to modify the existing data model in place.
{@a injectable}
## injectable
@ -575,14 +607,15 @@ Learn more in [Dependency Injection](guide/dependency-injection).
A framework for building Angular forms through code in a component.
The alternative is a [template-driven form](guide/glossary#template-driven-forms).
When building reactive forms:
When using reactive forms:
* The "source of truth" is the component. The validation is defined using code in the component.
* Each control is explicitly created in the component class with `new FormControl()` or with `FormBuilder`.
* The "source of truth", the form model, is defined in the component class.
* Validation is set up through validation functions rather than valdation directives.
* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
* The template input elements do *not* use `ngModel`.
* The associated Angular directives are prefixed with `Form`, such as `FormGroup()`, `FormControl()`, and `FormControlName()`.
* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
Reactive forms are powerful, flexible, and a good choice for more complex data-entry form scenarios, such as dynamic generation of form controls.
The alternative is a template-driven form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
{@a router}
{@a router-module}
@ -697,16 +730,14 @@ Additional templates, represented by `TemplateRef` objects, can define alternati
A format for building Angular forms using HTML forms and input elements in the view.
The alternative format uses the [reactive forms](guide/glossary#reactive-forms) framework.
When building template-driven forms:
When using template-driven forms:
* The "source of truth" is the template. The validation is defined using attributes on the individual input elements.
* [Two-way binding](guide/glossary#data-binding) with `ngModel` keeps the component model synchronized with the user's entry into the input elements.
* Behind the scenes, Angular creates a new control for each input element, provided you have set up a `name` attribute and two-way binding for each input.
* The associated Angular directives are prefixed with `ng` such as `ngForm`, `ngModel`, and `ngModelGroup`.
Template-driven forms are convenient, quick, and simple. They are a good choice for many basic data-entry form scenarios.
Read about how to build template-driven forms in [Forms](guide/forms).
The alternative is a reactive form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
{@a template-expression}

View File

@ -190,7 +190,7 @@ which you must adjust to start Chrome without sandboxing.
We'll be using [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome#cli) in these examples.
* In the Karma configuration file, `karma.conf.js`, add a custom launcher called ChromeNoSandbox below browsers:
* In the Karma configuration file, `karma.conf.js`, add a custom launcher called ChromeHeadlessCI below browsers:
```
browsers: ['Chrome'],
customLaunchers: {
@ -684,7 +684,7 @@ and returns a [`ComponentFixture`](#component-fixture).
Do not re-configure `TestBed` after calling `createComponent`.
The `createComponent` method freezes the current `TestBed`definition,
The `createComponent` method freezes the current `TestBed` definition,
closing it to further configuration.
You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`,

View File

Before

Width:  |  Height:  |  Size: 851 KiB

After

Width:  |  Height:  |  Size: 851 KiB

View File

@ -422,8 +422,8 @@
"picture": "minko.jpg",
"twitter": "mgechev",
"website": "http://blog.mgechev.com",
"bio": "Software engineer who enjoys theoretical computer science and its practical applications. Author of the books 'Switching to Angular 2' and 'Getting Started with Angular', speaker and blogger. Working on tooling for Angular and TypeScript.",
"group": "GDE"
"bio": "Software engineer who enjoys theoretical computer science and its practical applications. Speaker, author of the book 'Switching to Angular', codelyzer, Guess.js, and the Go linter revive. Working for faster and more reliable software.",
"group": "Angular"
},
"uri": {

View File

@ -13,18 +13,6 @@
</tr>
</thead>
<tbody>
<!-- ReactiveConf -->
<tr>
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
<td>Prague, Czech Republic</td>
<td>October 29-31, 2018</td>
</tr>
<!-- AngularConnect-->
<tr>
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
<td>London, United Kingdom</td>
<td>November 5-7, 2018</td>
</tr>
</tbody>
</table>
@ -38,6 +26,18 @@
</tr>
</thead>
<tbody>
<!-- ReactiveConf -->
<tr>
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
<td>Prague, Czech Republic</td>
<td>October 29-31, 2018</td>
</tr>
<!-- AngularConnect-->
<tr>
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
<td>London, United Kingdom</td>
<td>November 5-7, 2018</td>
</tr>
<!-- AngularMix -->
<tr>
<th><a href="https://angularmix.com/" title="AngularMix">AngularMix</a></th>

View File

@ -1,7 +1,5 @@
<h1>Test Code Page</h1>
<p>Current location is <current-location></current-location></p>
<h2>&lt;code-tabs&gt;</h2>
<p>No linenums at code-tabs level</p>

View File

@ -251,7 +251,7 @@ Here is the final version of `getHeroes` with the `tap` that logs the operation.
Most web APIs support a _get by id_ request in the form `:baseURL/:id`.
Here, the _base URL_ is the `heroesURL` defined in the [Heroes and HTTP](http://localhost:4800/tutorial/toh-pt6#heroes-and-http) section (`api/heroes`) and _id_ is
Here, the _base URL_ is the `heroesURL` defined in the [Heroes and HTTP](tutorial/toh-pt6#heroes-and-http) section (`api/heroes`) and _id_ is
the number of the hero that you want to retrieve. For example, `api/heroes/11`.
Add a `HeroService.getHero()` method to make that request:

View File

@ -12,13 +12,13 @@
"/app/search/search-worker.js",
"/assets/images/favicons/favicon.ico",
"/assets/js/*.js",
"/generated/lunr.min.js",
"/*.css",
"/*.js"
],
"urls": [
"https://fonts.googleapis.com/**",
"https://fonts.gstatic.com/s/**",
"https://maxcdn.bootstrapcdn.com/**"
"https://fonts.gstatic.com/s/**"
]
}
}, {

View File

@ -7,7 +7,7 @@
"license": "MIT",
"scripts": {
"preinstall": "node ../tools/yarn/check-yarn.js",
"postinstall": "node tools/cli-patches/patch.js && uglifyjs node_modules/lunr/lunr.js -c -m -o src/assets/js/lunr.min.js --source-map",
"postinstall": "node tools/cli-patches/patch.js",
"aio-use-local": "node tools/ng-packages-installer overwrite . --debug",
"aio-use-npm": "node tools/ng-packages-installer restore .",
"aio-check-local": "node tools/ng-packages-installer check .",
@ -25,7 +25,7 @@
"e2e": "ng e2e --no-webdriver-update",
"presetup": "yarn --cwd .. install && yarn install --frozen-lockfile && yarn ~~check-env && yarn ~~clean-generated && yarn boilerplate:remove",
"setup": "yarn aio-use-npm && yarn example-use-npm",
"postsetup": "yarn boilerplate:add && yarn build-ie-polyfills && yarn extract-cli-command-docs && yarn docs",
"postsetup": "yarn ~~build-ie-polyfills && yarn ~~minify-lunr && yarn boilerplate:add && yarn extract-cli-command-docs && yarn docs",
"presetup-local": "yarn presetup",
"setup-local": "yarn aio-use-local && yarn example-use-local",
"postsetup-local": "yarn postsetup",
@ -61,13 +61,14 @@
"generate-stackblitz": "node ./tools/stackblitz-builder/generateStackblitz",
"generate-zips": "node ./tools/example-zipper/generateZips",
"build-404-page": "node scripts/build-404-page",
"build-ie-polyfills": "yarn webpack-cli src/ie-polyfills.js -o src/generated/ie-polyfills.min.js --mode production",
"update-webdriver": "webdriver-manager update --standalone false --gecko false $CHROMEDRIVER_VERSION_ARG",
"~~check-env": "node scripts/check-environment",
"~~clean-generated": "node --eval \"require('shelljs').rm('-rf', 'src/generated')\"",
"~~build": "ng build",
"post~~build": "yarn build-404-page",
"~~http-server": "http-server"
"~~build-ie-polyfills": "webpack-cli src/ie-polyfills.js -o src/generated/ie-polyfills.min.js --mode production",
"~~http-server": "http-server",
"~~minify-lunr": "uglifyjs node_modules/lunr/lunr.js -c -m -o src/generated/lunr.min.js --source-map"
},
"engines": {
"node": ">=10.9.0 <11.0.0",
@ -141,7 +142,7 @@
"lighthouse": "^3.2.1",
"lodash": "^4.17.4",
"lunr": "^2.1.0",
"npm-run-all": "^4.1.3",
"npm-run-all": "^4.1.5",
"protractor": "^5.2.0",
"rehype": "^6.0.0",
"rehype-slug": "^2.0.0",

View File

@ -2,10 +2,9 @@
"aio": {
"master": {
"uncompressed": {
"runtime": 3881,
"main": 499953,
"polyfills": 53926,
"prettify": 14917
"runtime": 3713,
"main": 500343,
"polyfills": 53926
}
}
}

View File

@ -0,0 +1,37 @@
#!/usr/bin/env node
/**
* Usage:
* node create-preview <build-number>
*
* Triggers the preview server to initiate the preview creation process for the specified CircleCI
* build number. It must be called _after_ the build artifacts have been created and stored on
* CircleCI.
*/
// Imports
const {triggerWebhook} = require('../../.circleci/trigger-webhook');
// Constants
const JOB_NAME = 'aio_preview';
const WEBHOOK_URL = 'https://ngbuilds.io/circle-build';
// Input
const buildNumber = process.argv[2];
// Run
triggerWebhook(buildNumber, JOB_NAME, WEBHOOK_URL).
then(({statusCode, responseText}) => isSuccess(statusCode) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`))).
catch(err => {
console.error(err);
process.exit(1);
});
// Helpers
function isSuccess(statusCode) {
// Getting a 409 response from the preview server means that the preview has already been created
// for the corresponding PR/SHA, so our objective has been accomplished.
return (200 <= statusCode && statusCode < 400) || (statusCode === 409);
}

View File

@ -29,10 +29,12 @@
<aio-top-menu *ngIf="isSideBySide" [nodes]="topMenuNodes"></aio-top-menu>
<aio-search-box class="search-container" #searchBox (onSearch)="doSearch($event)" (onFocus)="doSearch($event)"></aio-search-box>
<div class="toolbar-external-icons-container">
<a href="https://twitter.com/angular" title="Twitter">
<img src="assets/images/logos/twitter-icon.svg"></a>
<a href="https://github.com/angular/angular" title="GitHub">
<img src="assets/images/logos/github-icon.svg"></a>
<a href="https://twitter.com/angular" title="Twitter" aria-label="Angular on twitter">
<mat-icon svgIcon="logos:twitter"></mat-icon>
</a>
<a href="https://github.com/angular/angular" title="GitHub" aria-label="Angular on github">
<mat-icon svgIcon="logos:github"></mat-icon>
</a>
</div>
</mat-toolbar-row>
</mat-toolbar>
@ -72,3 +74,10 @@
<aio-footer [nodes]="footerNodes" [versionInfo]="versionInfo" ></aio-footer>
</footer>
<!--
Work-around to ensure that the `.woff2` file for the 'Material Icons' font will always be fetched.
This allows the SW to cache the file (even if there are no icons in the current page) and ensure
material icons on other pages are displayed correctly in offline mode.
(Note: Instantiate lazily to avoid affecting the initial rendering.)
-->
<mat-icon class="cdk-visually-hidden" *ngIf="!isStarting">&nbsp;</mat-icon>

View File

@ -742,7 +742,7 @@ describe('AppComponent', () => {
expect(component.showSearchResults).toBe(true);
});
it('should not intercept clicks om the searchBox', () => {
it('should not intercept clicks on the searchBox', () => {
component.showSearchResults = true;
fixture.detectChanges();
@ -752,6 +752,11 @@ describe('AppComponent', () => {
expect(component.showSearchResults).toBe(true);
});
it('should not call `locationService.setSearch` when searchResults are not shown', () => {
docViewer.click();
expect(locationService.setSearch).not.toHaveBeenCalled();
});
});
describe('keyup handling', () => {

View File

@ -389,7 +389,10 @@ export class AppComponent implements OnInit {
hideSearchResults() {
this.showSearchResults = false;
this.locationService.setSearch('', { ...this.locationService.search(), search: undefined });
const oldSearch = this.locationService.search();
if (oldSearch.search !== undefined) {
this.locationService.setSearch('', { ...oldSearch, search: undefined });
}
}
focusSearchBox() {

View File

@ -51,31 +51,19 @@ export const svgIconProviders = [
useValue: {
name: 'close',
svgSource:
'<svg fill="#ffffff" focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
'<svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />' +
'<path d="M0 0h24v24H0z" fill="none" />' +
'</svg>',
},
multi: true,
},
{
provide: SVG_ICONS,
useValue: {
name: 'error_outline',
svgSource:
'<svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M0 0h24v24H0V0z" fill="none" />' +
'<path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />' +
'</svg>',
},
multi: true,
},
{
provide: SVG_ICONS,
useValue: {
name: 'insert_comment',
svgSource:
'<svg fill="#ffffff" focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
'<svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z" />' +
'<path d="M0 0h24v24H0z" fill="none" />' +
'</svg>',
@ -104,6 +92,41 @@ export const svgIconProviders = [
},
multi: true,
},
// Namespace: logos
{
provide: SVG_ICONS,
useValue: {
namespace: 'logos',
name: 'github',
svgSource:
'<svg focusable="false" viewBox="0 0 51.8 50.4" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M25.9,0.2C11.8,0.2,0.3,11.7,0.3,25.8c0,11.3,7.3,20.9,17.5,24.3c1.3,0.2,1.7-0.6,1.7-1.2c0-0.6,0-2.6,0-4.8' +
'c-7.1,1.5-8.6-3-8.6-3c-1.2-3-2.8-3.7-2.8-3.7c-2.3-1.6,0.2-1.6,0.2-1.6c2.6,0.2,3.9,2.6,3.9,2.6c2.3,3.9,6,2.8,7.5,2.1' +
'c0.2-1.7,0.9-2.8,1.6-3.4c-5.7-0.6-11.7-2.8-11.7-12.7c0-2.8,1-5.1,2.6-6.9c-0.3-0.7-1.1-3.3,0.3-6.8c0,0,2.1-0.7,7,2.6' +
'c2-0.6,4.2-0.9,6.4-0.9c2.2,0,4.4,0.3,6.4,0.9c4.9-3.3,7-2.6,7-2.6c1.4,3.5,0.5,6.1,0.3,6.8c1.6,1.8,2.6,4.1,2.6,6.9' +
'c0,9.8-6,12-11.7,12.6c0.9,0.8,1.7,2.4,1.7,4.7c0,3.4,0,6.2,0,7c0,0.7,0.5,1.5,1.8,1.2c10.2-3.4,17.5-13,17.5-24.3' +
'C51.5,11.7,40.1,0.2,25.9,0.2z" />' +
'</svg>',
},
multi: true,
},
{
provide: SVG_ICONS,
useValue: {
namespace: 'logos',
name: 'twitter',
svgSource:
'<svg focusable="false" viewBox="0 0 50 59" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M50,9.3c-1.8,0.8-3.8,1.4-5.9,1.6c2.1-1.3,3.7-3.3,4.5-5.7c-2,1.2-4.2,2-6.5,2.5c-1.9-2-4.5-3.2-7.5-3.2' +
'c-5.7,0-10.3,4.6-10.3,10.3c0,0.8,0.1,1.6,0.3,2.3C16.1,16.7,8.5,12.6,3.5,6.4c-0.9,1.5-1.4,3.3-1.4,5.2c0,3.6,1.8,6.7,4.6,8.5' +
'C5,20,3.4,19.6,2,18.8c0,0,0,0.1,0,0.1c0,5,3.5,9.1,8.2,10.1c-0.9,0.2-1.8,0.4-2.7,0.4c-0.7,0-1.3-0.1-1.9-0.2' +
'c1.3,4.1,5.1,7,9.6,7.1c-3.5,2.8-7.9,4.4-12.7,4.4c-0.8,0-1.6,0-2.4-0.1c4.5,2.9,9.9,4.6,15.7,4.6c18.9,0,29.2-15.6,29.2-29.2' +
'c0-0.4,0-0.9,0-1.3C46.9,13.2,48.6,11.4,50,9.3z" />' +
'</svg>',
},
multi: true,
},
];
// tslint:enable: max-line-length

View File

@ -1,12 +1,13 @@
import { NgModule, Type } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { ContributorListComponent } from './contributor-list.component';
import { ContributorService } from './contributor.service';
import { ContributorComponent } from './contributor.component';
import { WithCustomElementComponent } from '../element-registry';
@NgModule({
imports: [ CommonModule ],
imports: [ CommonModule, MatIconModule ],
declarations: [ ContributorListComponent, ContributorComponent ],
entryComponents: [ ContributorListComponent ],
providers: [ ContributorService ]

View File

@ -13,16 +13,16 @@ import { CONTENT_URL_PREFIX } from 'app/documents/document.service';
<div class="contributor-image" [style.background-image]="'url('+pictureBase+(person.picture || noPicture)+')'">
<div class="contributor-info">
<a *ngIf="person.bio" mat-button>
<a *ngIf="person.bio" mat-button class="info-item">
View Bio
</a>
<a *ngIf="person.twitter" mat-button class="icon"
<a *ngIf="person.twitter" mat-icon-button class="info-item icon"
href="https://twitter.com/{{person.twitter}}" target="_blank" (click)="$event.stopPropagation()">
<span class="fa fa-twitter fa-2x"></span>
<mat-icon svgIcon="logos:twitter"></mat-icon>
</a>
<a *ngIf="person.website" mat-button class="icon"
<a *ngIf="person.website" mat-icon-button class="info-item icon"
href="{{person.website}}" target="_blank" (click)="$event.stopPropagation()">
<span class="fa fa-link fa-2x"></span>
<mat-icon class="link-icon">link</mat-icon>
</a>
</div>
</div>

View File

@ -1,35 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service';
import { CurrentLocationComponent } from './current-location.component';
describe('CurrentLocationComponent', () => {
let element: HTMLElement;
let fixture: ComponentFixture<CurrentLocationComponent>;
let locationService: MockLocationService;
beforeEach(() => {
locationService = new MockLocationService('initial/url');
TestBed.configureTestingModule({
declarations: [ CurrentLocationComponent ],
providers: [
{ provide: LocationService, useValue: locationService }
]
});
fixture = TestBed.createComponent(CurrentLocationComponent);
element = fixture.nativeElement;
});
it('should render the current location', () => {
fixture.detectChanges();
expect(element.textContent).toEqual('initial/url');
locationService.urlSubject.next('next/url');
fixture.detectChanges();
expect(element.textContent).toEqual('next/url');
});
});

View File

@ -1,12 +0,0 @@
/* tslint:disable component-selector */
import { Component } from '@angular/core';
import { LocationService } from 'app/shared/location.service';
/** Renders the current location path. */
@Component({
selector: 'current-location',
template: '{{ location.currentPath | async }}'
})
export class CurrentLocationComponent {
constructor(public location: LocationService) { }
}

View File

@ -1,13 +0,0 @@
import { NgModule, Type } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CurrentLocationComponent } from './current-location.component';
import { WithCustomElementComponent } from '../element-registry';
@NgModule({
imports: [ CommonModule ],
declarations: [ CurrentLocationComponent ],
entryComponents: [ CurrentLocationComponent ]
})
export class CurrentLocationModule implements WithCustomElementComponent {
customElementComponent: Type<any> = CurrentLocationComponent;
}

View File

@ -36,14 +36,6 @@ export const ELEMENT_MODULE_PATHS_AS_ROUTES = [
selector: 'code-tabs',
loadChildren: './code/code-tabs.module#CodeTabsModule'
},
{
selector: 'current-location',
loadChildren: './current-location/current-location.module#CurrentLocationModule'
},
{
selector: 'expandable-section',
loadChildren: './expandable-section/expandable-section.module#ExpandableSectionModule'
},
{
selector: 'live-example',
loadChildren: './live-example/live-example.module#LiveExampleModule'

View File

@ -1,7 +0,0 @@
<mat-expansion-panel style="background: inherit">
<mat-expansion-panel-header>
{{title}}
</mat-expansion-panel-header>
<ng-content></ng-content>
</mat-expansion-panel>

View File

@ -1,11 +0,0 @@
/* tslint:disable component-selector */
import {Component, Input} from '@angular/core';
/** Custom element wrapper for the material expansion panel with a title input. */
@Component({
selector: 'aio-expandable-section',
templateUrl: 'expandable-section.component.html',
})
export class ExpandableSectionComponent {
@Input() title;
}

View File

@ -1,13 +0,0 @@
import { NgModule, Type } from '@angular/core';
import { ExpandableSectionComponent } from './expandable-section.component';
import { WithCustomElementComponent } from '../element-registry';
import { MatExpansionModule } from '@angular/material';
@NgModule({
imports: [ MatExpansionModule ],
declarations: [ ExpandableSectionComponent, ],
entryComponents: [ ExpandableSectionComponent ]
})
export class ExpandableSectionModule implements WithCustomElementComponent {
customElementComponent: Type<any> = ExpandableSectionComponent;
}

View File

@ -113,6 +113,7 @@ describe('DocumentService', () => {
httpMock.expectOne({}).flush(null, {status: 500, statusText: 'Server Error'});
expect(latestDocument.id).toEqual(FETCHING_ERROR_ID);
expect(latestDocument.contents).toContain('We are unable to retrieve the "initial/doc" page at this time.');
expect(logger.output.error).toEqual([
[jasmine.any(Error)]
]);

View File

@ -15,13 +15,13 @@ export const FETCHING_ERROR_ID = 'fetching-error';
export const CONTENT_URL_PREFIX = 'generated/';
export const DOC_CONTENT_URL_PREFIX = CONTENT_URL_PREFIX + 'docs/';
const FETCHING_ERROR_CONTENTS = `
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>
<p>
We are unable to retrieve the "<current-location></current-location>" page at this time.
We are unable to retrieve the "${path}" page at this time.
Please check your connection and try again later.
</p>
</div>
@ -46,7 +46,7 @@ export class DocumentService {
private getDocument(url: string) {
const id = url || 'index';
this.logger.log('getting document', id);
if ( !this.cache.has(id)) {
if (!this.cache.has(id)) {
this.cache.set(id, this.fetchDocument(id));
}
return this.cache.get(id)!;
@ -93,7 +93,7 @@ export class DocumentService {
this.cache.delete(id);
return of({
id: FETCHING_ERROR_ID,
contents: FETCHING_ERROR_CONTENTS
contents: FETCHING_ERROR_CONTENTS(id),
});
}
}

View File

@ -6,7 +6,7 @@
var SEARCH_TERMS_URL = '/generated/docs/app/search-data.json';
// NOTE: This needs to be kept in sync with `ngsw-config.json`.
importScripts('/assets/js/lunr.min.js');
importScripts('/generated/lunr.min.js');
var index;
var pages /* : SearchInfo */ = {};

View File

@ -17,6 +17,27 @@ describe('CustomIconRegistry', () => {
expect(svgElement).toEqual(createSvg(svgSrc));
});
it('should support caching icons with a namespace', () => {
const mockHttp: any = {};
const mockSanitizer: any = {};
const mockDocument: any = {};
const svgSrc1 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h100" /></svg>';
const svgSrc2 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h200" /></svg>';
const svgSrc3 = '<svg xmlns="http://www.w3.org/2000/svg"><path d="h300" /></svg>';
const svgIcons: SvgIconInfo[] = [
{ name: 'test_icon', svgSource: svgSrc1 },
{ namespace: 'foo', name: 'test_icon', svgSource: svgSrc2 },
{ namespace: 'bar', name: 'test_icon', svgSource: svgSrc3 },
];
const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons);
let svgElement: SVGElement|undefined;
registry.getNamedSvgIcon('test_icon', 'foo').subscribe(el => svgElement = el);
expect(svgElement).toEqual(createSvg(svgSrc2));
});
it('should call through to the MdIconRegistry if the icon name is not in the preloaded cache', () => {
const mockHttp: any = {};
const mockSanitizer: any = {};

View File

@ -20,21 +20,26 @@ import { DomSanitizer } from '@angular/platform-browser';
*/
export const SVG_ICONS = new InjectionToken<Array<SvgIconInfo>>('SvgIcons');
export interface SvgIconInfo {
namespace?: string;
name: string;
svgSource: string;
}
interface SvgIconMap {
[iconName: string]: SVGElement;
[namespace: string]: {
[iconName: string]: SVGElement;
};
}
const DEFAULT_NS = '$$default';
/**
* A custom replacement for Angular Material's `MdIconRegistry`, which allows
* us to provide preloaded icon SVG sources.
*/
@Injectable()
export class CustomIconRegistry extends MatIconRegistry {
private preloadedSvgElements: SvgIconMap = {};
private preloadedSvgElements: SvgIconMap = {[DEFAULT_NS]: {}};
constructor(http: HttpClient, sanitizer: DomSanitizer, @Optional() @Inject(DOCUMENT) document,
@Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
@ -43,18 +48,24 @@ export class CustomIconRegistry extends MatIconRegistry {
}
getNamedSvgIcon(iconName: string, namespace?: string) {
if (this.preloadedSvgElements[iconName]) {
return of(this.preloadedSvgElements[iconName].cloneNode(true) as SVGElement);
}
return super.getNamedSvgIcon(iconName, namespace);
const nsIconMap = this.preloadedSvgElements[namespace || DEFAULT_NS];
const preloadedElement = nsIconMap && nsIconMap[iconName];
return preloadedElement
? of(preloadedElement.cloneNode(true) as SVGElement)
: super.getNamedSvgIcon(iconName, namespace);
}
private loadSvgElements(svgIcons: SvgIconInfo[]) {
const div = document.createElement('DIV');
svgIcons.forEach(icon => {
const ns = icon.namespace || DEFAULT_NS;
const nsIconMap = this.preloadedSvgElements[ns] || (this.preloadedSvgElements[ns] = {});
// SECURITY: the source for the SVG icons is provided in code by trusted developers
div.innerHTML = icon.svgSource;
this.preloadedSvgElements[icon.name] = div.querySelector('svg')!;
nsIconMap[icon.name] = div.querySelector('svg')!;
});
}
}

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 51.8 50.4" style="enable-background:new 0 0 51.8 50.4;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M25.9,0.2C11.8,0.2,0.3,11.7,0.3,25.8c0,11.3,7.3,20.9,17.5,24.3c1.3,0.2,1.7-0.6,1.7-1.2c0-0.6,0-2.6,0-4.8
c-7.1,1.5-8.6-3-8.6-3c-1.2-3-2.8-3.7-2.8-3.7c-2.3-1.6,0.2-1.6,0.2-1.6c2.6,0.2,3.9,2.6,3.9,2.6c2.3,3.9,6,2.8,7.5,2.1
c0.2-1.7,0.9-2.8,1.6-3.4c-5.7-0.6-11.7-2.8-11.7-12.7c0-2.8,1-5.1,2.6-6.9c-0.3-0.7-1.1-3.3,0.3-6.8c0,0,2.1-0.7,7,2.6
c2-0.6,4.2-0.9,6.4-0.9c2.2,0,4.4,0.3,6.4,0.9c4.9-3.3,7-2.6,7-2.6c1.4,3.5,0.5,6.1,0.3,6.8c1.6,1.8,2.6,4.1,2.6,6.9
c0,9.8-6,12-11.7,12.6c0.9,0.8,1.7,2.4,1.7,4.7c0,3.4,0,6.2,0,7c0,0.7,0.5,1.5,1.8,1.2c10.2-3.4,17.5-13,17.5-24.3
C51.5,11.7,40.1,0.2,25.9,0.2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 49.7" style="enable-background:new 0 0 50 49.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M50,9.3c-1.8,0.8-3.8,1.4-5.9,1.6c2.1-1.3,3.7-3.3,4.5-5.7c-2,1.2-4.2,2-6.5,2.5c-1.9-2-4.5-3.2-7.5-3.2
c-5.7,0-10.3,4.6-10.3,10.3c0,0.8,0.1,1.6,0.3,2.3C16.1,16.7,8.5,12.6,3.5,6.4c-0.9,1.5-1.4,3.3-1.4,5.2c0,3.6,1.8,6.7,4.6,8.5
C5,20,3.4,19.6,2,18.8c0,0,0,0.1,0,0.1c0,5,3.5,9.1,8.2,10.1c-0.9,0.2-1.8,0.4-2.7,0.4c-0.7,0-1.3-0.1-1.9-0.2
c1.3,4.1,5.1,7,9.6,7.1c-3.5,2.8-7.9,4.4-12.7,4.4c-0.8,0-1.6,0-2.4-0.1c4.5,2.9,9.9,4.6,15.7,4.6c18.9,0,29.2-15.6,29.2-29.2
c0-0.4,0-0.9,0-1.3C46.9,13.2,48.6,11.4,50,9.3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 937 B

View File

@ -21,9 +21,9 @@
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/images/favicons/favicon-144x144.png">
<!-- NOTE: These need to be kept in sync with `ngsw-config.json`. -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<!-- -->
<link rel="manifest" href="pwa-manifest.json">

View File

@ -103,8 +103,8 @@ footer::after {
left: 0;
right: 0;
background:
url('../src/assets/images/logos/angular/angular_whiteTransparent_withMargin.png') top 0 left 0 repeat,
url('../src/assets/images/logos/angular/angular_whiteTransparent_withMargin.png') top 80px left 160px repeat;
url('/assets/images/logos/angular/angular_whiteTransparent_withMargin.png') top 0 left 0 repeat,
url('/assets/images/logos/angular/angular_whiteTransparent_withMargin.png') top 80px left 160px repeat;
opacity: 0.05;
background-size: 320px auto;
}

View File

@ -67,21 +67,6 @@ a.button.mat-button {
background: $darkgray;
color: rgba($white, .87);
}
&.button-shield,
&.button-shield.mat-button {
background-color: $blue;
background: $blue url('assets/images/logos/angular/angular_whiteTransparent.svg') 24px 13px no-repeat;
color: rgba($white, .87);
padding-left: 54px;
background-size: 22px 22px;
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {
background: $blue url('assets/images/logos/angular/angular_whiteTransparent.svg') 24px 13px no-repeat;
background-size: 22px 22px;
}
}
}
.cta-bar {

View File

@ -70,7 +70,7 @@ aio-contributor {
@media (hover) { opacity: 0; }
border-radius: 50%;
[mat-button] {
.info-item {
color: $white;
font-size: 14px;
font-weight: 500;
@ -85,8 +85,14 @@ aio-contributor {
min-width: 20px;
width: 20px;
.fa-2x {
font-size: 20px;
mat-icon {
height: 20px;
width: 20px;
&.link-icon {
margin-top: -7px;
transform: rotateZ(45deg);
}
}
}
}

View File

@ -73,7 +73,7 @@ aio-notification {
}
mat-sidenav.mat-sidenav.sidenav {
top: 56px + $notificationHeight;
top: 64px + $notificationHeight;
@media (max-width: 600px) {
top: 56px + $notificationHeight;

View File

@ -624,9 +624,10 @@ ajv@6.5.3:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^4.7.0:
ajv@^4.7.0, ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
@ -726,7 +727,7 @@ ansi-styles@^3.1.0:
dependencies:
color-convert "^1.9.0"
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
dependencies:
@ -923,6 +924,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ=
assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
@ -998,18 +1004,23 @@ autoprefixer@8.4.1:
postcss "^6.0.22"
postcss-value-parser "^3.2.3"
aws-sign2@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8=
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
aws4@^1.2.1, aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
axe-core@3.0.0-beta.2:
version "3.0.0-beta.2"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.0.0-beta.2.tgz#82a13d371268034352bba2bcb263c5625b3e4a09"
@ -1196,6 +1207,22 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
body-parser@1.18.2, body-parser@^1.16.1:
version "1.18.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
integrity sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=
dependencies:
bytes "3.0.0"
content-type "~1.0.4"
debug "2.6.9"
depd "~1.1.1"
http-errors "~1.6.2"
iconv-lite "0.4.19"
on-finished "~2.3.0"
qs "6.5.1"
raw-body "2.3.2"
type-is "~1.6.15"
body-parser@1.18.3, body-parser@^1.18.3:
version "1.18.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
@ -1211,21 +1238,6 @@ body-parser@1.18.3, body-parser@^1.18.3:
raw-body "2.3.3"
type-is "~1.6.16"
body-parser@^1.16.1:
version "1.18.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
dependencies:
bytes "3.0.0"
content-type "~1.0.4"
debug "2.6.9"
depd "~1.1.1"
http-errors "~1.6.2"
iconv-lite "0.4.19"
on-finished "~2.3.0"
qs "6.5.1"
raw-body "2.3.2"
type-is "~1.6.15"
bonjour@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
@ -2301,7 +2313,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^6.0.0, cross-spawn@^6.0.4, cross-spawn@^6.0.5:
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
dependencies:
@ -2782,10 +2794,6 @@ duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
duplexer@^0.1.1, duplexer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.1.2, duplexify@^3.5.0:
version "3.5.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
@ -3202,19 +3210,6 @@ event-emitter@^0.3.5, event-emitter@~0.3.5:
d "1"
es5-ext "~0.10.14"
event-stream@~3.3.0:
version "3.3.6"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.6.tgz#cac1230890e07e73ec9cacd038f60a5b66173eef"
dependencies:
duplexer "^0.1.1"
flatmap-stream "^0.1.0"
from "^0.1.7"
map-stream "0.0.7"
pause-stream "^0.0.11"
split "^1.0.1"
stream-combiner "^0.2.2"
through "^2.3.8"
eventemitter3@1.x.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
@ -3683,10 +3678,6 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
flatmap-stream@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/flatmap-stream/-/flatmap-stream-0.1.0.tgz#ed54e01422cd29281800914fcb968d58b685d5f1"
flatmap@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4"
@ -3732,6 +3723,15 @@ forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
form-data@~2.1.1:
version "2.1.4"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
mime-types "^2.1.12"
form-data@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
@ -3769,10 +3769,6 @@ from2@^2.1.0, from2@^2.1.1:
inherits "^2.0.1"
readable-stream "^2.0.0"
from@^0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
fs-access@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
@ -4232,10 +4228,23 @@ handlebars@^4.0.1, handlebars@^4.0.3:
optionalDependencies:
uglify-js "^2.6"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio=
dependencies:
ajv "^4.9.1"
har-schema "^1.0.5"
har-validator@~5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
@ -4411,7 +4420,7 @@ hastscript@^4.0.0:
property-information "^4.0.0"
space-separated-tokens "^1.0.0"
hawk@3.1.3:
hawk@3.1.3, hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
dependencies:
@ -4577,6 +4586,15 @@ http-server@^0.9.0:
portfinder "0.4.x"
union "~0.4.3"
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=
dependencies:
assert-plus "^0.2.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@ -6095,10 +6113,6 @@ map-obj@^1.0.0, map-obj@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
map-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
map-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
@ -6289,9 +6303,10 @@ miller-rabin@^4.0.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
"mime-db@>= 1.36.0 < 2":
"mime-db@>= 1.36.0 < 2", mime-db@~1.37.0:
version "1.37.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
mime-db@~1.36.0:
version "1.36.0"
@ -6315,6 +6330,13 @@ mime-types@~2.1.19:
dependencies:
mime-db "~1.36.0"
mime-types@~2.1.7:
version "2.1.21"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==
dependencies:
mime-db "~1.37.0"
mime@1.4.1, mime@^1.2.11, mime@^1.3.4, mime@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
@ -6777,16 +6799,17 @@ npm-registry-client@8.6.0:
optionalDependencies:
npmlog "2 || ^3.1.0 || ^4.0.0"
npm-run-all@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.3.tgz#49f15b55a66bb4101664ce270cb18e7103f8f185"
npm-run-all@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
dependencies:
ansi-styles "^3.2.0"
chalk "^2.1.0"
cross-spawn "^6.0.4"
ansi-styles "^3.2.1"
chalk "^2.4.1"
cross-spawn "^6.0.5"
memorystream "^0.3.1"
minimatch "^3.0.4"
ps-tree "^1.1.0"
pidtree "^0.3.0"
read-pkg "^3.0.0"
shell-quote "^1.6.1"
string.prototype.padend "^3.0.0"
@ -6832,7 +6855,7 @@ nunjucks@^3.0.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c"
oauth-sign@~0.8.2:
oauth-sign@~0.8.1, oauth-sign@~0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
@ -7291,12 +7314,6 @@ path-type@^3.0.0:
dependencies:
pify "^3.0.0"
pause-stream@^0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
dependencies:
through "~2.3"
pbkdf2@^3.0.3:
version "3.0.14"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
@ -7307,10 +7324,20 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
pidtree@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b"
integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -7528,9 +7555,10 @@ protractor@^5.2.0:
webdriver-js-extender "^1.0.0"
webdriver-manager "^12.0.6"
proxy-addr@~2.0.4:
proxy-addr@~2.0.3, proxy-addr@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
dependencies:
forwarded "~0.1.2"
ipaddr.js "1.8.0"
@ -7539,12 +7567,6 @@ prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
ps-tree@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
dependencies:
event-stream "~3.3.0"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@ -8974,12 +8996,6 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"
split@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
dependencies:
through "2"
sprintf-js@^1.0.3:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
@ -9060,13 +9076,6 @@ stream-browserify@^2.0.1:
inherits "~2.0.1"
readable-stream "^2.0.2"
stream-combiner@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858"
dependencies:
duplexer "~0.1.1"
through "~2.3.4"
stream-each@^1.1.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd"
@ -9170,6 +9179,11 @@ stringmap@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/stringmap/-/stringmap-0.2.2.tgz#556c137b258f942b8776f5b2ef582aa069d7d1b1"
stringstream@~0.0.4:
version "0.0.6"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
stringstream@~0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@ -9446,7 +9460,7 @@ through2@^2.0.0, through2@^2.0.3:
readable-stream "^2.1.5"
xtend "~4.0.1"
through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.4:
"through@>=2.2.7 <3", through@X.X.X, through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@ -9540,6 +9554,13 @@ tough-cookie@^2.3.2, tough-cookie@~2.3.3:
dependencies:
punycode "^1.4.1"
tough-cookie@~2.3.0:
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==
dependencies:
punycode "^1.4.1"
tough-cookie@~2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"

View File

@ -168,8 +168,23 @@ Of course, non-hermeticity in an action can cause problems.
At worst, you can fetch a broken artifact from the cache, making your build non-reproducible.
For this reason, we are careful to implement our Bazel rules to depend only on their inputs.
Currently we only use remote caching on CircleCI.
We could enable it for developer builds as well, which would make initial builds much faster for developers by fetching already-built artifacts from the cache.
Currently we only use remote caching on CircleCI and we let Angular core developers enable remote caching to speed up their builds.
### Remote cache in development
To enable remote caching for your build:
1. Go to the service accounts for the ["internal" project](https://console.cloud.google.com/iam-admin/serviceaccounts?project=internal-200822)
1. Select "Angular local dev", click on "Edit", scroll to the bottom, and click "Create key"
1. When the pop-up shows, select "JSON" for "Key type" and click "Create"
1. Save the key in a secure location
1. Create a file called `.bazelrc.user` in the root directory of the workspace, and add the following content:
```
build --config=angular-team --google_credentials=[ABSOLUTE_PATH_TO_SERVICE_KEY]
```
### Remote cache for Circle CI
This feature is experimental, and developed by the CircleCI team with guidance from Angular.
Contact Alex Eagle with questions.
@ -181,6 +196,75 @@ Contact Alex Eagle with questions.
1. Bazel must be configured to connect to the proxy on a local port. This configuration lives in `.circleci/bazel.rc` and is enabled because we overwrite the system Bazel settings in /etc/bazel.bazelrc with this file.
1. Each `bazel` command in `.circleci/config.yml` picks up and uses the caching flags.
## Diagnosing slow builds
If a build seems slow you can use Bazel to diagnose where time is spent.
The first step is to generate a profile of the build using the `--profile filename_name.profile` flag.
```
yarn bazel build //packages/compiler --profile filename_name.profile
```
This will generate a `filename_name.profile` that you can then analyse using [analyze-profile](https://docs.bazel.build/versions/master/user-manual.html#analyze-profile) command.
## Using the console profile report
You can obtain a simple report directly in the console by running:
```
yarn bazel analyze-profile filename_name.profile
```
This will show the phase summary, individual phase information and critical path.
You can also list all individual tasks and the time they took using `--task_tree`.
```
yarn bazel analyze-profile filename_name.profile --task_tree ".*"
```
To show all tasks that take longer than a certain threshold, use the `--task_tree_threshold` flag.
The default behaviour is to use a 50ms threshold.
```
yarn bazel analyze-profile filename_name.profile --task_tree ".*" --task_tree_threshold 5000
```
`--task_tree` takes a regexp as argument that filters by the text shown after the time taken.
Compiling TypeScript shows as:
```
70569 ACTION_EXECUTE (10974.826 ms) Compiling TypeScript (devmode) //packages/compiler:compiler []
```
To filter all tasks by TypeScript compilations that took more than 5 seconds, use:
```
yarn bazel analyze-profile filename_name.profile --task_tree "Compiling TypeScript" --task_tree_threshold 5000
```
### Using the HTML profile report
A more comprehensive way to visualize the profile information is through the HTML report:
```
yarn bazel analyze-profile filename_name.profile --html --html_details --html_histograms
```
This will generate a `filename_name.profile.html` file that you can open in your browser.
On the upper right corner that is a small table of contents with links to three areas: Tasks, Legend and Statistics.
In the Tasks section you will find a graph of where time is spent. Legend shows what the colors in the Tasks graph mean.
Hovering over the background will show what phase that is, while hovering over bars will show more details about that specific action.
The Statistics section shows how long each phase took and how time was spent in that phase.
Usually the longest one is the execution phase, which also includes critical path information.
Also in the Statistics section are the Skylark statistic, split in User-Defined and Builtin function execution time.
You can click the "self" header twice to order the table by functions where the most time (in ms) is spent.
When diagnosing slow builds you should focus on the top time spenders across all phases and functions.
Usually there is a single item (or multiple items of the same kind) where the overwhelming majority of time is spent.
## Known issues
### Webstorm

View File

@ -29,8 +29,6 @@ following products on your development machine:
* [Java Development Kit](http://www.oracle.com/technetwork/es/java/javase/downloads/index.html) which is used
to execute the selenium standalone server for e2e testing.
* (Optional for now) [Bazel](https://bazel.build/), please follow instructions in [BAZEL.md](https://github.com/angular/angular/blob/master/docs/BAZEL.md)
## Getting the Sources
Fork and clone the Angular repository:
@ -124,7 +122,7 @@ You can automatically format your code by running:
A better way is to set up your IDE to format the changed file on each file save.
### VS Code
1. Install [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) extension for VS Code.
1. Install [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) extension for VS Code.
2. Open `settings.json` in your workspace and add these lines:
```json
"files.autoSave": "onFocusChange",

View File

@ -32,8 +32,6 @@ gulp.task('format', loadTask('format', 'format'));
gulp.task('format:untracked', loadTask('format', 'format-untracked'));
gulp.task('format:diff', loadTask('format', 'format-diff'));
gulp.task('format:changed', ['format:untracked', 'format:diff']);
gulp.task('build.sh', loadTask('build', 'all'));
gulp.task('build.sh:no-bundle', loadTask('build', 'no-bundle'));
gulp.task('lint', ['format:enforce', 'validate-commit-messages', 'tslint']);
gulp.task('tslint', ['tools:build'], loadTask('lint'));
gulp.task('validate-commit-messages', loadTask('validate-commit-message'));

View File

@ -20,6 +20,14 @@ load("@angular//packages/bazel:package.bzl", "rules_angular_dependencies")
rules_angular_dependencies()
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
rules_typescript_dependencies()
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
rules_nodejs_dependencies()
http_archive(
name = "io_bazel_rules_sass",
sha256 = "dbe9fb97d5a7833b2a733eebc78c9c1e3880f676ac8af16e58ccf2139cbcad03",

View File

@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "7.1.0",
"version": "7.1.2",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps",
@ -36,6 +36,7 @@
"@angular-devkit/architect": "^0.10.6",
"@angular-devkit/core": "^7.0.4",
"@angular-devkit/schematics": "^7.0.4",
"@bazel/karma": "0.21.0",
"@bazel/typescript": "0.21.0",
"@schematics/angular": "^7.0.4",
"@types/chokidar": "1.7.3",
@ -85,13 +86,12 @@
"zone.js": "^0.8.26"
},
"optionalDependencies": {
"fsevents": "1.1.2"
"fsevents": "2.0.1"
},
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
"devDependencies": {
"@bazel/bazel": "^0.18.1",
"@bazel/ibazel": "^0.1.1",
"@bazel/karma": "0.21.0",
"@bazel/ibazel": "~0.8.2",
"@types/angular": "^1.6.47",
"@types/base64-js": "1.2.5",
"@types/jasminewd2": "^2.0.4",
@ -145,4 +145,4 @@
"vrsource-tslint-rules": "5.1.1",
"webpack": "1.12.9"
}
}
}

View File

@ -7,8 +7,6 @@
"""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load(":rules_nodejs_package.bzl", "rules_nodejs_dependencies")
load(":rules_typescript_package.bzl", "rules_typescript_dependencies")
def rules_angular_dependencies():
"""
@ -20,13 +18,13 @@ def rules_angular_dependencies():
#
# Download Bazel toolchain dependencies as needed by build actions
#
# TODO(gmagolan): updated to next tagged rules_typescript release
# Use a SHA to get fix for needing symlink_prefix during npm publishing
# TODO(alexeagle): updated to next tagged rules_typescript release
_maybe(
http_archive,
name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.16.2.zip",
strip_prefix = "rules_nodejs-0.16.2",
url = "https://github.com/bazelbuild/rules_nodejs/archive/ee218e2a98b9f09ba07cecac8496a5918c47bc5d.zip",
strip_prefix = "rules_nodejs-ee218e2a98b9f09ba07cecac8496a5918c47bc5d",
)
_maybe(
@ -48,9 +46,6 @@ def rules_angular_dependencies():
],
)
rules_typescript_dependencies()
rules_nodejs_dependencies()
def rules_angular_dev_dependencies():
"""
Fetch dependencies needed for local development, but not needed by users.

View File

@ -1,56 +0,0 @@
# 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.
"""Dependency-related rules defining our version and dependency versions.
Fulfills similar role as the package.json file.
"""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# This file mirrored from https://raw.githubusercontent.com/bazelbuild/rules_nodejs/0.15.3/package.bzl
VERSION = "0.15.3"
def rules_nodejs_dependencies():
"""
Fetch our transitive dependencies.
If the user wants to get a different version of these, they can just fetch it
from their WORKSPACE before calling this function, or not call this function at all.
"""
_maybe(
http_archive,
name = "bazel_skylib",
url = "https://github.com/bazelbuild/bazel-skylib/archive/0.3.1.zip",
strip_prefix = "bazel-skylib-0.3.1",
sha256 = "95518adafc9a2b656667bbf517a952e54ce7f350779d0dd95133db4eb5c27fb1",
)
# Needed for Remote Build Execution
# See https://releases.bazel.build/bazel-toolchains.html
# Not strictly a dependency for all users, but it is convenient for them to have this repository
# defined to reduce the effort required to on-board to remote execution.
http_archive(
name = "bazel_toolchains",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/cdea5b8675914d0a354d89f108de5d28e54e0edc.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/cdea5b8675914d0a354d89f108de5d28e54e0edc.tar.gz",
],
strip_prefix = "bazel-toolchains-cdea5b8675914d0a354d89f108de5d28e54e0edc",
sha256 = "cefb6ccf86ca592baaa029bcef04148593c0efe8f734542f10293ea58f170715",
)
def _maybe(repo_rule, name, **kwargs):
if name not in native.existing_rules():
repo_rule(name = name, **kwargs)

View File

@ -1,94 +0,0 @@
# 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.
"""Package file which defines build_bazel_rules_typescript version in skylark
check_rules_typescript_version can be used in downstream WORKSPACES to check
against a minimum dependent build_bazel_rules_typescript version.
"""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# This file mirrored from https://raw.githubusercontent.com/bazelbuild/rules_typescript/0.20.3/package.bzl
VERSION = "0.20.3"
def rules_typescript_dependencies():
"""
Fetch our transitive dependencies.
If the user wants to get a different version of these, they can just fetch it
from their WORKSPACE before calling this function, or not call this function at all.
"""
# TypeScript compiler runs on node.js runtime
_maybe(
http_archive,
name = "build_bazel_rules_nodejs",
urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.15.3.zip"],
strip_prefix = "rules_nodejs-0.15.3",
)
# ts_web_test depends on the web testing rules to provision browsers.
_maybe(
http_archive,
name = "io_bazel_rules_webtesting",
urls = ["https://github.com/bazelbuild/rules_webtesting/archive/111d792b9a5b17f87b6e177e274dbbee46094791.zip"],
strip_prefix = "rules_webtesting-111d792b9a5b17f87b6e177e274dbbee46094791",
sha256 = "a13af63e928c34eff428d47d31bafeec4e38ee9b6940e70bf2c9cd47184c5c16",
)
# ts_devserver depends on the Go rules.
# See https://github.com/bazelbuild/rules_go#setup for the latest version.
_maybe(
http_archive,
name = "io_bazel_rules_go",
urls = ["https://github.com/bazelbuild/rules_go/archive/cbc1e32fba771845305f15e341fa26595d4a136d.zip"],
strip_prefix = "rules_go-cbc1e32fba771845305f15e341fa26595d4a136d",
sha256 = "d02b1d8d11fb67fb1e451645256e58a1542170eedd6e2ba160c8540c96f659da",
)
# go_repository is defined in bazel_gazelle
_maybe(
http_archive,
name = "bazel_gazelle",
urls = ["https://github.com/bazelbuild/bazel-gazelle/archive/109bcfd6880aac2517a1a2d48987226da6337e11.zip"],
strip_prefix = "bazel-gazelle-109bcfd6880aac2517a1a2d48987226da6337e11",
sha256 = "8f80ce0f7a6f8a3fee1fb863c9a23e1de99d678c1cf3c6f0a128f3b883168208",
)
# ts_auto_deps depends on com_github_bazelbuild_buildtools
_maybe(
http_archive,
name = "com_github_bazelbuild_buildtools",
url = "https://github.com/bazelbuild/buildtools/archive/0.12.0.zip",
strip_prefix = "buildtools-0.12.0",
sha256 = "ec495cbd19238c9dc488fd65ca1fee56dcb1a8d6d56ee69a49f2ebe69826c261",
)
###############################################
# Repeat the dependencies of rules_nodejs here!
# We can't load() from rules_nodejs yet, because we've only just fetched it.
# But we also don't want to make users load and call the rules_nodejs_dependencies
# function because we can do that for them, mostly hiding the transitive dependency.
_maybe(
http_archive,
name = "bazel_skylib",
url = "https://github.com/bazelbuild/bazel-skylib/archive/0.5.0.zip",
strip_prefix = "bazel-skylib-0.5.0",
sha256 = "ca4e3b8e4da9266c3a9101c8f4704fe2e20eb5625b2a6a7d2d7d45e3dd4efffd",
)
def _maybe(repo_rule, name, **kwargs):
if name not in native.existing_rules():
repo_rule(name = name, **kwargs)

View File

@ -51,6 +51,10 @@ def _esm5_outputs_aspect(target, ctx):
if not hasattr(target.typescript, "replay_params"):
print("WARNING: no esm5 output from target %s//%s:%s available" % (target.label.workspace_root, target.label.package, target.label.name))
return []
elif not target.typescript.replay_params:
# In case there are "replay_params" specified but the compile action didn't generate any
# outputs (e.g. only "d.ts" files), we cannot create ESM5 outputs for this target either.
return []
# We create a new tsconfig.json file that will have our compilation settings
tsconfig = ctx.actions.declare_file("%s_esm5.tsconfig.json" % target.label.name)
@ -165,7 +169,7 @@ def flatten_esm5(ctx):
ctx: the skylark rule execution context
Returns:
list of flattened files
depset of flattened files
"""
esm5_sources = []
result = []
@ -186,4 +190,4 @@ def flatten_esm5(ctx):
template = f,
substitutions = {},
)
return result
return depset(result)

View File

@ -18,18 +18,33 @@ function main(args) {
if (args.length < 3) {
console.error('Usage: $0 input.tsconfig.json output.tsconfig.json newRoot binDir');
}
[input, output, newRoot, binDir] = args;
const [input, output, newRoot, binDir] = args;
const data = JSON.parse(fs.readFileSync(input, {encoding: 'utf-8'}));
data['compilerOptions']['target'] = 'es5';
data['bazelOptions']['es5Mode'] = true;
data['compilerOptions']['outDir'] = path.join(data['compilerOptions']['outDir'], newRoot);
const {compilerOptions, bazelOptions} = data;
// Relative path to the execroot that refers to the directory for the ES5 output files.
const newOutputBase = path.posix.join(binDir, newRoot);
// Update the compiler options to produce ES5 output. Also ensure that the new ES5 output
// directory is used.
compilerOptions['target'] = 'es5';
compilerOptions['outDir'] = path.posix.join(compilerOptions['outDir'], newRoot);
bazelOptions['es5Mode'] = true;
bazelOptions['tsickleExternsPath'] =
bazelOptions['tsickleExternsPath'].replace(binDir, newOutputBase);
if (data['angularCompilerOptions']) {
const {angularCompilerOptions} = data;
// Don't enable tsickle's closure conversions
data['angularCompilerOptions']['annotateForClosureCompiler'] = false;
data['angularCompilerOptions']['expectedOut'] =
data['angularCompilerOptions']['expectedOut'].map(
f => f.replace(/\.closure\.js$/, '.js').replace(binDir, path.join(binDir, newRoot)));
angularCompilerOptions['annotateForClosureCompiler'] = false;
// Note: It's important that the "expectedOut" is only modified in a way that still
// keeps posix normalized paths. Otherwise this could cause unexpected behavior because
// ngc-wrapped is expecting POSIX paths and the TypeScript Bazel rules by default only pass
// POSIX paths as well.
angularCompilerOptions['expectedOut'] = angularCompilerOptions['expectedOut'].map(
f => f.replace(/\.closure\.js$/, '.js').replace(binDir, newOutputBase));
}
fs.writeFileSync(output, JSON.stringify(data));
}

View File

@ -169,7 +169,7 @@ def _expected_outs(ctx):
if short_path.endswith(".ts") and not short_path.endswith(".d.ts"):
basename = short_path[len(package_prefix):-len(".ts")]
if include_ng_files and (len(factory_basename_set) == 0 or basename in factory_basename_set):
if include_ng_files and (len(factory_basename_set.to_list()) == 0 or basename in factory_basename_set.to_list()):
devmode_js = [
".ngfactory.js",
".ngsummary.js",

View File

@ -0,0 +1,41 @@
# 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
"""Collect TypeScript definition files from a rule context.
This is used to find all files that will be copied into a "ng_package".
"""
def _filter_typing_files(files):
return [file for file in files if file.path.endswith(".d.ts")]
def collect_type_definitions(ctx):
"""Returns a file tree containing only TypeScript definition files.
This is useful when packaging a "ng_package" where we only want to package specified
definition files.
Args:
ctx: ctx.
Returns:
A file tree containing only TypeScript definition files.
"""
# Add all source files and filter for TypeScript definition files
# See: https://docs.bazel.build/versions/master/skylark/lib/File.html#is_source
collected_files = _filter_typing_files([d for d in ctx.files.deps if d.is_source])
# In case source files have been explicitly specified in the attributes, just collect
# them and filter for definition files.
if hasattr(ctx.attr, "srcs"):
collected_files += _filter_typing_files(ctx.files.srcs)
# Collect all TypeScript definition files from the specified dependencies.
for dep in ctx.attr.deps:
if hasattr(dep, "typescript"):
collected_files += dep.typescript.transitive_declarations.to_list()
return collected_files

View File

@ -30,6 +30,7 @@ load(
load("@build_bazel_rules_nodejs//:internal/node.bzl", "sources_aspect")
load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo")
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5")
load("//packages/bazel/src/ng_package:collect-type-definitions.bzl", "collect_type_definitions")
_DEFAULT_NG_PACKAGER = "@npm//@angular/bazel/bin:packager"
@ -153,11 +154,20 @@ def _flatten_paths(directory):
return result
# takes an depset of files and returns an array that doesn't contain any generated files by ngc
def _filter_out_generated_files(files):
def _filter_out_generated_files(files, extension, filter_external_files):
result = []
for file in files:
if (not (file.path.endswith(".ngfactory.js") or file.path.endswith(".ngsummary.js") or file.path.endswith(".ngstyle.js"))):
# If the "filter_external_files" parameter has been set to true, filter out files
# that refer to external workspaces.
if filter_external_files and file.short_path.startswith("../"):
continue
# Filter out files that are generated by the Angular Compiler CLI.
if (not (file.path.endswith(".ngfactory.%s" % extension) or
file.path.endswith(".ngsummary.%s" % extension) or
file.path.endswith(".ngstyle.%s" % extension))):
result.append(file)
return depset(result)
def _esm2015_root_dir(ctx):
@ -174,8 +184,9 @@ def _filter_js_inputs(all_inputs):
def _ng_package_impl(ctx):
npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name)
esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx))
esm5_sources = _filter_out_generated_files(flatten_esm5(ctx))
esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx), "js", False)
esm5_sources = _filter_out_generated_files(flatten_esm5(ctx), "js", False)
type_definitions = _filter_out_generated_files(collect_type_definitions(ctx), "d.ts", True)
# These accumulators match the directory names where the files live in the
# Angular package format.
@ -284,11 +295,7 @@ def _ng_package_impl(ctx):
ctx.files.srcs +
ctx.files.data +
esm5_sources.to_list() +
depset(transitive = [
d.typescript.transitive_declarations
for d in ctx.attr.deps
if hasattr(d, "typescript")
]).to_list() +
type_definitions.to_list() +
[f.js for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles] +
[f.map for f in fesm2015 + fesm5 + esm2015 + esm5 + bundles if f.map]
)
@ -321,15 +328,16 @@ def _ng_package_impl(ctx):
# placeholder
packager_args.add("")
packager_args.add_joined(_flatten_paths(fesm2015), join_with = ",")
packager_args.add_joined(_flatten_paths(fesm5), join_with = ",")
packager_args.add_joined(_flatten_paths(esm2015), join_with = ",")
packager_args.add_joined(_flatten_paths(esm5), join_with = ",")
packager_args.add_joined(_flatten_paths(bundles), join_with = ",")
packager_args.add_joined([s.path for s in ctx.files.srcs], join_with = ",")
packager_args.add_joined(_flatten_paths(fesm2015), join_with = ",", omit_if_empty = False)
packager_args.add_joined(_flatten_paths(fesm5), join_with = ",", omit_if_empty = False)
packager_args.add_joined(_flatten_paths(esm2015), join_with = ",", omit_if_empty = False)
packager_args.add_joined(_flatten_paths(esm5), join_with = ",", omit_if_empty = False)
packager_args.add_joined(_flatten_paths(bundles), join_with = ",", omit_if_empty = False)
packager_args.add_joined([s.path for s in ctx.files.srcs], join_with = ",", omit_if_empty = False)
packager_args.add_joined([s.path for s in type_definitions], join_with = ",", omit_if_empty = False)
# TODO: figure out a better way to gather runfiles providers from the transitive closure.
packager_args.add_joined([d.path for d in ctx.files.data], join_with = ",")
packager_args.add_joined([d.path for d in ctx.files.data], join_with = ",", omit_if_empty = False)
if ctx.file.license_banner:
packager_inputs.append(ctx.file.license_banner)

View File

@ -73,6 +73,9 @@ function main(args: string[]): number {
// List of all files in the ng_package rule's srcs.
srcsArg,
// List of all type definitions that need to packaged into the ng_package.
typeDefinitionsArg,
// List of all files in the ng_package rule's data.
dataArg,
@ -85,6 +88,7 @@ function main(args: string[]): number {
const esm2015 = esm2015Arg.split(',').filter(s => !!s);
const esm5 = esm5Arg.split(',').filter(s => !!s);
const bundles = bundlesArg.split(',').filter(s => !!s);
const typeDefinitions = typeDefinitionsArg.split(',').filter(s => !!s);
const srcs = srcsArg.split(',').filter(s => !!s);
const dataFiles: string[] = dataArg.split(',').filter(s => !!s);
const modulesManifest = JSON.parse(modulesManifestArg);
@ -134,7 +138,8 @@ function main(args: string[]): number {
* @param outDir path where we copy the file, relative to the out
*/
function writeEsmFile(file: string, suffix: string, outDir: string) {
const root = file.substr(0, file.lastIndexOf(suffix + path.sep) + suffix.length + 1);
// Note that the specified file path is always using the posix path delimiter.
const root = file.substr(0, file.lastIndexOf(`${suffix}/`) + suffix.length + 1);
const rel = path.dirname(path.relative(path.join(root, srcDir), file));
if (!rel.startsWith('..')) {
copyFile(file, path.join(out, outDir), rel);
@ -148,8 +153,9 @@ function main(args: string[]): number {
fesm2015.forEach(file => { copyFile(file, out, 'fesm2015'); });
fesm5.forEach(file => { copyFile(file, out, 'fesm5'); });
const allsrcs = shx.find('-R', binDir);
allsrcs.filter(hasFileExtension('.d.ts')).forEach((f: string) => {
// Copy all type definitions into the package. This is necessary so that developers can use
// the package with type definitions.
typeDefinitions.forEach((f: string) => {
const content = fs.readFileSync(f, 'utf-8')
// Strip the named AMD module for compatibility with non-bazel users
.replace(/^\/\/\/ <amd-module name=.*\/>\n/gm, '');
@ -235,12 +241,6 @@ function main(args: string[]): number {
return `./${result}`;
}
/** Gets a predicate function to filter non-generated files with a specified extension. */
function hasFileExtension(ext: string): (path: string) => boolean {
return f => f.endsWith(ext) && !f.endsWith(`.ngfactory${ext}`) &&
!f.endsWith(`.ngsummary${ext}`);
}
function copyFile(file: string, baseDir: string, relative = '.') {
const dir = path.join(baseDir, relative);
shx.mkdir('-p', dir);
@ -253,6 +253,12 @@ function main(args: string[]): number {
const outputPath = path.join(dir, ...path.basename(file).split('__'));
shx.mkdir('-p', path.dirname(outputPath));
shx.mv(path.join(dir, path.basename(file)), outputPath);
// if we are renaming the .js file, we'll also need to update the sourceMappingURL in the file
if (file.endsWith('.js')) {
shx.chmod('+w', outputPath);
shx.sed('-i', `${path.basename(file)}.map`, `${path.basename(outputPath)}.map`, outputPath);
}
}
}

View File

@ -36,7 +36,7 @@ def _protractor_web_test_impl(ctx):
specs = [
expand_path_into_runfiles(ctx, f.short_path)
for f in files
for f in files.to_list()
]
configuration_sources = []

View File

@ -70,6 +70,26 @@ describe('@angular/common ng_package', () => {
expect(shx.ls('-R', 'fesm2015').stdout.split('\n').filter(n => !!n).sort()).toEqual(expected);
});
it('should have the correct source map paths', () => {
expect(shx.grep('sourceMappingURL', 'fesm5/common.js'))
.toMatch('//# sourceMappingURL=common.js.map');
expect(shx.grep('sourceMappingURL', 'fesm2015/common.js'))
.toMatch('//# sourceMappingURL=common.js.map');
expect(shx.grep('sourceMappingURL', 'fesm5/http.js'))
.toMatch('//# sourceMappingURL=http.js.map');
expect(shx.grep('sourceMappingURL', 'fesm2015/http.js'))
.toMatch('//# sourceMappingURL=http.js.map');
expect(shx.grep('sourceMappingURL', 'fesm5/http/testing.js'))
.toMatch('//# sourceMappingURL=testing.js.map');
expect(shx.grep('sourceMappingURL', 'fesm2015/http/testing.js'))
.toMatch('//# sourceMappingURL=testing.js.map');
expect(shx.grep('sourceMappingURL', 'fesm5/testing.js'))
.toMatch('//# sourceMappingURL=testing.js.map');
expect(shx.grep('sourceMappingURL', 'fesm2015/testing.js'))
.toMatch('//# sourceMappingURL=testing.js.map');
});
describe('should have module resolution properties in the package.json file for', () => {
// https://github.com/angular/common-builds/blob/master/package.json
it('/', () => {

View File

@ -1,20 +1,19 @@
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
# TODO: these tests don't even compile under bazel right now
#
# ts_library(
# name = "test_lib",
# testonly = True,
# srcs = glob(["**/*.ts"]),
# tags = ["manual"]
# )
ts_library(
name = "test_lib",
testonly = True,
srcs = glob(["**/*.ts"]),
)
# jasmine_node_test(
# name = "test",
# deps = [
# ":test_lib",
# "//packages/benchpress"
# # "//tools/testing:node",
# ],
# tags = ["manual"]
# )
jasmine_node_test(
name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
deps = [
":test_lib",
"//packages/benchpress",
"//packages/core/testing",
"//tools/testing:node",
"@ngdeps//protractor",
],
)

View File

@ -9,19 +9,22 @@
import {$, browser} from 'protractor';
const benchpress = require('../../index.js');
const runner = new benchpress.Runner([
// use protractor as Webdriver client
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
// use RegressionSlopeValidator to validate samples
benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator),
// use 10 samples to calculate slope regression
benchpress.bind(benchpress.RegressionSlopeValidator.SAMPLE_SIZE).toValue(20),
// use the script metric to calculate slope regression
benchpress.bind(benchpress.RegressionSlopeValidator.METRIC).toValue('scriptTime'),
benchpress.bind(benchpress.Options.FORCE_GC).toValue(true)
]);
describe('deep tree baseline', function() {
// TODO: this test is currnetly failing. it seems that it didn't run on the ci for a while
xdescribe('deep tree baseline', function() {
const runner = new benchpress.Runner([
// use protractor as Webdriver client
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
// use RegressionSlopeValidator to validate samples
benchpress.Validator.bind(benchpress.RegressionSlopeValidator),
// use 10 samples to calculate slope regression
benchpress.bind(benchpress.RegressionSlopeValidator.SAMPLE_SIZE).toValue(20),
// use the script metric to calculate slope regression
benchpress.bind(benchpress.RegressionSlopeValidator.METRIC).toValue('scriptTime'),
benchpress.bind(benchpress.Options.FORCE_GC).toValue(true)
]);
it('should be fast!', function(done) {
browser.ignoreSynchronization = true;
browser.get('http://localhost:8001/playground/src/benchpress/');

View File

@ -20,7 +20,8 @@ const assertEventsContainsName = function(events: any[], eventName: string) {
expect(found).toBeTruthy();
};
describe('firefox extension', function() {
// TODO: this test is currnetly failing. it seems that it didn't run on the ci for a while
xdescribe('firefox extension', function() {
const TEST_URL = 'http://localhost:8001/playground/src/hello_world/index.html';
it('should measure performance', function() {

View File

@ -0,0 +1,29 @@
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library", "ts_web_test_suite")
ts_library(
name = "test_lib",
testonly = True,
srcs = glob(
["**/*.ts"],
),
deps = [
"//packages/common/http",
"//packages/common/http/testing",
],
)
jasmine_node_test(
name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
deps = [
":test_lib",
"//tools/testing:node",
],
)
ts_web_test_suite(
name = "test_web",
deps = [
":test_lib",
],
)

View File

@ -6,10 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ddescribe, describe, fit, it} from '@angular/core/testing/src/testing_internal';
import {HttpClient} from '../../src/client';
import {HttpClientTestingBackend} from '../src/backend';
import {HttpClient} from '@angular/common/http';
import {HttpClientTestingBackend} from '@angular/common/http/testing/src/backend';
describe('HttpClient TestRequest', () => {
it('accepts a null body', () => {

View File

@ -114,7 +114,7 @@ export class PercentPipe implements PipeTransform {
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `3`.
* Default is `0`.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).

View File

@ -68,6 +68,8 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
describe('transform', () => {
it('should return correct value for numbers', () => {
expect(pipe.transform(1.23)).toEqual('123%');
expect(pipe.transform(1.234)).toEqual('123%');
expect(pipe.transform(1.236)).toEqual('124%');
expect(pipe.transform(12.3456, '0.0-10')).toEqual('1,234.56%');
});

View File

@ -71,8 +71,10 @@ export function createBundleIndexHost<H extends ts.CompilerHost>(
indexFile = files[0];
} else {
for (const f of files) {
// Assume the shortest file path called index.ts is the entry point
if (f.endsWith(path.sep + 'index.ts')) {
// Assume the shortest file path called index.ts is the entry point. Note that we
// need to use the posix path delimiter here because TypeScript internally only
// passes posix paths.
if (f.endsWith('/index.ts')) {
if (!indexFile || indexFile.length > f.length) {
indexFile = f;
}

View File

@ -48,10 +48,9 @@ export class GeneratedShimsHostWrapper implements ts.CompilerHost {
fileName: string, languageVersion: ts.ScriptTarget,
onError?: ((message: string) => void)|undefined,
shouldCreateNewSourceFile?: boolean|undefined): ts.SourceFile|undefined {
const canonical = this.getCanonicalFileName(fileName);
for (let i = 0; i < this.shimGenerators.length; i++) {
const generator = this.shimGenerators[i];
const originalFile = generator.getOriginalSourceOfShim(canonical);
const originalFile = generator.getOriginalSourceOfShim(fileName);
if (originalFile !== null) {
// This shim generator has recognized the filename being requested, and is now responsible
// for generating its contents, based on the contents of the original file it has requested.

View File

@ -19,7 +19,9 @@ import {Inject, Optional, Self, SkipSelf} from './metadata';
*
* @publicApi
*/
export const enum InjectFlags {
export enum InjectFlags {
// TODO(alxhub): make this 'const' when ngc no longer writes exports of it into ngfactory files.
Default = 0b0000,
/**

View File

@ -86,6 +86,9 @@
{
"name": "INJECTOR_SIZE"
},
{
"name": "InjectFlags"
},
{
"name": "IterableChangeRecord_"
},

View File

@ -176,6 +176,9 @@
{
"name": "Inject"
},
{
"name": "InjectFlags"
},
{
"name": "InjectionToken"
},

View File

@ -17,6 +17,9 @@
{
"name": "Inject"
},
{
"name": "InjectFlags"
},
{
"name": "InjectionToken"
},

View File

@ -74,6 +74,9 @@
{
"name": "INJECTOR_SIZE"
},
{
"name": "InjectFlags"
},
{
"name": "IterableChangeRecord_"
},

View File

@ -371,6 +371,9 @@
{
"name": "Inject"
},
{
"name": "InjectFlags"
},
{
"name": "InjectionToken"
},

View File

@ -26,7 +26,9 @@ function _isAndroid(): boolean {
}
/**
* Turn this mode on if you want form directives to buffer IME input until compositionend
* @description
* Provide this token to control if form directives buffer IME input until
* the "compositionend" event occurs.
* @publicApi
*/
export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');

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