Translators are not allowed to write HTML which creates URI attributes. I opted to ban any values going into an attribute at all, to prevent even links to malicious content, rather than just sanitizing URIs.
I also converted this blocklist into an allowlist. Now, we only allowing setting known attributes (while sanitizing URI attributes). This significantly reduces risk of missing a vulnerable attribute and does not require an exhaustive list of all potential attributes.
BREAKING CHANGE: Angular now only applies known attributes from HTML in translated ICU content. Unknown attributes are dropped and not rendered.
(cherry picked from commit 03da204b6d)
This commit updates the DOM security schema and sanitization logic to properly recognize and sanitize `href` and `xlink:href` attributes on SVG `<script>` elements.
This commit implements a security fix to prevent XSS vulnerabilities where SVG animation elements (`<animate>`, `<set>`, etc.) could be used to modify the `href` or `xlink:href` attributes of other elements to `javascript:` URLs.
The fix introduces a runtime validation step:
- A new [ɵɵValidateAttribute](cci:1://file:///usr/local/google/home/alanagius/git/angular/packages/core/src/sanitization/sanitization.ts:276:0-288:1) instruction is used when `attributeName` is bound on SVG animation elements.
- If executed, a `RuntimeError` is thrown, preventing the binding.
- The compiler now identifies `attributeName` on SVG animation elements as security-sensitive and injects this validation.
Additionally, the DOM security schema has been updated to include a comprehensive list of MathML and SVG elements that accept `href` or `xlink:href` attributes, ensuring they are correctly treated as `SecurityContext.URL` and sanitized. This prevents malicious URLs from being bound to these attributes.
http://b/463880509
The XSRF interceptor previously failed to detect protocol-relative URLs (starting with `//`) as absolute URLs. This allowed requests to such URLs to include the XSRF token, potentially leaking it to external domains.
This change updates the interceptor to correctly identify protocol-relative URLs as absolute and exclude them from receiving the XSRF token.
* fix(core): introduce `BootstrapContext` for improved server bootstrapping
This commit introduces a number of changes to the server bootstrapping process to make it more robust and less error-prone, especially for concurrent requests.
Previously, the server rendering process relied on a module-level global platform injector. This could lead to issues in server-side rendering environments where multiple requests are processed concurrently, as they could inadvertently share or overwrite the global injector state.
The new approach introduces a `BootstrapContext` that is passed to the `bootstrapApplication` function. This context provides a platform reference that is scoped to the individual request, ensuring that each server-side render has an isolated platform injector. This prevents state leakage between concurrent requests and makes the overall process more reliable.
BREAKING CHANGE:
The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.
Before:
```ts
const bootstrap = () => bootstrapApplication(AppComponent, config);
```
After:
```ts
const bootstrap = (context: BootstrapContext) =>
bootstrapApplication(AppComponent, config, context);
```
A schematic is provided to automatically update `main.server.ts` files to pass the `BootstrapContext` to the `bootstrapApplication` call.
In addition, `getPlatform()` and `destroyPlatform()` will now return `null` and be a no-op respectively when running in a server environment.
The hardcoded config was introduced because suppressing the diagnostic
via `extendedDiagnostics` in the TS config was unreliable in google3.
This has since been fixed and the workaround is no longer needed.
PR Close#61622
Disables creation of the esbuild meta.json file, which is not utilized in the build process. This streamlines the output and avoids generating unused artifacts.
PR Close#61636
Prevents esbuild generated metadata files from being included in build artifacts. This reduces package size and avoids shipping unnecessary internal build data.
PR Close#61636
Since the duplication root-cause was solved by the previous commit, we
can revert/drop the logic that was added back then to overcome this
problem with Tsurge.
PR Close#61421
PR Close#61612
Currently there can be cases, exlusively in 3P, where multiple tsconfig
projects have overlap of source files. This is the default setup of new
CLI applications as well.
When this is the case, Tsurge will treat each tsconfig as an isolated
compilation unit (given the concepts and mental model to support
scalable batching). This is wrong though, and the same `.ts` source file
can appear in two migration invocations; resulting in duplicate
replacements or analysis (depending on the migration).
We've worked around this problem in the past by deduplicating
replacements, or migrating to an ID-based approach with natural
deduplication. This worked, but it's just working around the root cause.
This commit attempts to fix the root cause by adjusting Tsurge to ensure
that no source file ever appears in two compilation units. This is
naively achieved by not adding a source file to a migration unit, if it
was part of a previous one. This is expected to be fine given the nature
of Tsurge migrations that are built to operate on isolated pieces
anyway— so it shouldn't be problematic if e.g. `app.component.ts` ends
up being part of the test tsconfig compilation unit (we avoid this order
though by visiting build targets first).
PR Close#61421
PR Close#61612
In this commit, we check whether the application is destroyed before calling `serviceWorker.register(...)`. We should not register the worker because other resources will not be available.
PR Close#61101
Avoids duplication of the `FactoryTarget` enums. This is necessary
now because we are exposing the previously deeply-imported JIT facade
now via the exports; and the typing integration tests surface a type
conflict due to the different duplicated enums.
PR Close#61571
These helpers are often imported by various tests throughout the
repository, but the helpers aren't exported/exposed from the public
entry-point; even though they confusingly reside in there.
This commit fixes this, and moves the helpers into
`packages/private/testing`. This is a preparation for the `ts_project`
migration where we don't want to leverage deep imports between packages.
PR Close#61571
The observable terminates immediately when `error` is called, and no further emissions or completion notifications occur. Thus, we have to remove the `abort` listener in both the `error` and `complete` notifications.
PR Close#58306
Streams left in a pending state (due to `break` without cancel) may continue consuming or holding onto data behind the scenes. Calling `reader.cancel()` allows the browser or the underlying system to release any network or memory resources associated with the stream.
PR Close#61528
Currently we construct the HMR replacement URL inline by calling into the native `URL` constructor. This can cause conflicts with user code that defines a symbol called `URL`.
These changes resolve the issue by moving the URL construction into a separate function. This has a secondary benefit of making the generated code easier to follow and allowing us to update the URL without changing the compiled code.
Fixes#61517.
PR Close#61550
enforce content to be fluid until a specific max width, and rollback breakpoints to be applied when 1430px is the current win size
as widths between 1430px and 1431px will be broken
PR Close#61384
This change ensures that prior results for all files are retained even when
a request is made such that we only need a shim for a single file. Prior
to this change, any prior results that were not part of the request were discarded.
PR Close#61487
Use an unstamped version of the compiler when it runs in `ng_project` as it will get stamped appropriately
whenever the generated code gets stamped after its usage."
PR Close#61479
Instead of disabling sandbox/workers for every action; which also could
slow-down development turnaround significantly, the flag should only
disable sandboxing for the test actions; allowing for e.g. DevTools to
connect to them, even if they are inside the sandbox.
Arguably, this strategy isn't seemingly necessary in all environments,
but given that we enable network sandboxing in this repo, it seems
reasonable. Ideally we'd also expose `_debug` targets for e.g. Node
tests that have the proper no-sandbox, or requires-network tag.
PR Close#61468
Adds `__PURE__` annotations to non-default `new` expressions to enable tree-shaking, even if they are not referenced. These variables are not dropped when Angular is imported from a module that has `sideEffects` set to `true`.
PR Close#61452
Migrates `packages/core/schematics` to `ts_project`. As part of this,
this commit cleans up some of the mixed module types and tsconfigs in
the folder. A single tsconfig (and it's test variant) are now used.
For the shipped schematics, we explicitly use the `.cjs` extension, so
that the bundles are properly recognized as CommonJS; even if they are
part of the `type: module` `@angular/core` package.
The `package.json` with `type: commonjs` is removed from
`packages/core/schematics` as it's no longer needed given the explicit
extension & caused issues as schematics are compiled with ESM but are
only later bundled for shipping & some tests as ESM.
PR Close#61420
As we migrate more and more code to `ts_project`, we are ending up with
`.js` file extensions (ts_library did generate `.mjs` magically).
Since we don't want to get into the business of migrating
`nodejs_binary` targets at this point (in some cases we might)— we
should support pointing to such files.
PR Close#61420
Fixes the `update_all_goldens` script which was throwing, because the query command was also capturing the call into yarn and Bazel which in turn caused it to throw an error. I've also added some validation for the number of targets.
PR Close#61407
* Fixes that the symbol extractor approval script was broken after some recent build changes.
* Fixes the `run_all_symbol_extractor_tests` script which wasn't resolving any targets, because the rule name changed.
PR Close#61407
The `getBaseHref` method is called several times per request and currently queries through the entire document. We can speed it up by taking advantage of the fact that the `<base>` can only be a direct child of the `<head>` and is usually defined towards the beginning. Below are some benchmarks for a "Hello world" app before and after this change.
### Before:
```
Running 60s test @ http://localhost:4202
100 connections with 10 pipelining factor
┌─────────┬────────┬────────┬────────┬────────┬───────────┬──────────┬─────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼────────┼────────┼────────┼────────┼───────────┼──────────┼─────────┤
│ Latency │ 568 ms │ 853 ms │ 901 ms │ 904 ms │ 866.58 ms │ 437.6 ms │ 9915 ms │
└─────────┴────────┴────────┴────────┴────────┴───────────┴──────────┴─────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec │ 490 │ 826 │ 1,006 │ 1,643 │ 1,129.3 │ 234.69 │ 490 │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 10.4 MB │ 17.4 MB │ 21.3 MB │ 34.7 MB │ 23.9 MB │ 4.96 MB │ 10.3 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 60
69k requests in 60.04s, 1.43 GB read
90 errors (90 timeouts)
```
### After
```
Running 60s test @ http://localhost:4202
100 connections with 10 pipelining factor
┌─────────┬────────┬────────┬────────┬─────────┬───────────┬───────────┬─────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼────────┼────────┼────────┼─────────┼───────────┼───────────┼─────────┤
│ Latency │ 471 ms │ 831 ms │ 889 ms │ 1668 ms │ 835.91 ms │ 467.89 ms │ 9720 ms │
└─────────┴────────┴────────┴────────┴─────────┴───────────┴───────────┴─────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼────────┼─────────┤
│ Req/Sec │ 390 │ 860 │ 1,145 │ 1,572 │ 1,156.77 │ 222.65 │ 390 │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼────────┼─────────┤
│ Bytes/Sec │ 8.24 MB │ 18.2 MB │ 24.2 MB │ 33.2 MB │ 24.4 MB │ 4.7 MB │ 8.24 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
# of samples: 60
71k requests in 60.03s, 1.47 GB read
140 errors (140 timeouts)
```
PR Close#61392
This commit implements several enhancements to the adev docs update workflow pipeline:
- **Unify actions:** Merge the workflows into a single one.
- **Optimize Git cloning:** Clone the repo with `--depth=0` only once per push instead of 2 times.
- **Prevent concurrent runs:** Implement concurrency control to automatically cancel in-progress workflow runs for the same branch, ensuring only the latest commit is processed.
PR Close#61396
This prevents `core/testing` from throwing an error if ZoneJS is present
but does not patch the test FW APIs such that `fakeAsync` works
automatically. For example, there is currently no patching of the vitest
APIs, so if you try to use Vitest with Zone on the page, it will throw.
PR Close#61376
The Angular class metadata emit structure does not support the use of
private fields. If the class metadata emit is enabled and an ECMAScript
private (i.e., `#` prefixed) member contains a decorator, the member will
now be excluded from the emitting `setClassMetadata` call. This prevents
runtime errors due to invalid syntax.
PR Close#61227
The release process overview is out of date and does not accurately reflect section headers. It's not worth the maintenance effort of keeping it in sync with the rest of the doc.
Added a step 0 to check if there's actually anything to release, reusing the command from later in the doc.
Also makes a few random small corrections to reflect the new release process.
PR Close#60892
This commit adds an import to the `ng_dev_mode.ts` file that augments
`global` to have types for `ngDevMode`.
Notably this change is currently not needed because the file is loaded
by `ts_library` through `tsconfig#files`— but in a separate PR we are
switching the target to `ts_project` which no longer loads all Bazel
dependency files via `tsconfig#files`; resulting in the ambient types no
longer magically being available.
PR Close#61365
fix new global layout issues, and make other pages adhere to the new centered layout like cli ref page, cli ref details, api ref details pages
PR Close#61256
As we roll out more PRs that migrate to `ts_project`, we need to make
sure that we don't break existing `tsec` targets. This PR copies the
original `tsec` Starlark code and adjusts it to work with the interop.
Note that we don't patch as this would unnecessarily complicate this
file that only exists during migration. Long-term, after migration, we
either need to consider switching to the new ESLint plugin that is being
worked on (I'm in contact with the team), or we send a CL to update the
Tsec Starlark code to keep our changes minimal and avoid scope increase.
PR Close#61336
This aligns with how angular/components marks their hidden APIs.
`@nodoc` has been broken since the switch to adev, this change should
properly hide the APIs again.
PR Close#61196
As part of the Bazel toolchain migration we noticed that implicit types
generated by the TypeScript compiler sometimes end up referencing types
from other packages (i.e. cross-package imports).
These imports currently work just because the Bazel `ts_library` and
`ng_module` rules automatically inserted a `<amd-module
name="@angular/x" />` into `.d.ts` of packages. This helped TS figure
out how to import a given file. Notably this is custom logic that is not
occuring in vanilla TS or Angular compilations—so we will drop this
magic as part of the toolchain cleanup!
To improve code quality and keep the existing behavior working, we are
doing the following:
- adding a lint rule that reduces the risk of such imports breaking. The
failure scenario without the rule is that API goldens show unexpected
diffs, and types might be duplicated in a different package!
- keeping the `<amd-module` headers, but we manually insert them into
the package entry-points. This should ensure we don't regress
anywhere; while we also improved general safety around this above.
Long-term, isolated declarations or a lint rule from eslint-typescript
can make this even more robust.
PR Close#61316
take the full width of the page for all the pages that use docs-viewer, also reserve an area for table of contents on-demand
Resolves: #52648
PR Close#58831
Migrates `manual_api_docs` to `rules_js`. Since compiler CLI is ESM
compiled but doesn't have extensions, we can either bundle or simply use
the dependency as type only. This is easier and sufficient for this
use-case.
PR Close#61237
Updates the name which accidentally remained unchanged from when I
copied it from the CLI help script
Also marks the PR for merge immediately. The caretaker can sanity check
it, approve it, and merge it.
PR Close#61195
We don't need this tooling anymore because we are already validating
that there are no circular dependencies via the `ng-dev` tooling that
checks `.ts` files directly.
Also these tests never actually failed to my knowledge.
PR Close#61209
Replaces incorrect use of GitHub Actions expression syntax `${{CURRENT_BRANCH }}` inside a run block with proper bash variablesyntax `$CURRENT_BRANCH`, preventing 'Unrecognized named-value' errors.
PR Close#61212
This workflow addresses a limitation with Renovate's behavior in fork mode. Renovate does not automatically sync non-default branches in forked repositories.
This workflow automates syncing forked non-default branches with their upstream counterparts. This ensures Renovate can detect and apply updates to these branches, maintaining up-to-date dependencies across all relevant branches.
PR Close#61201
The `false` behavior has existed for a long time but hasn't really
been documented. It's also not _quite_ what the browser would do.
Finally, the page explicitly discourages the implicit `false` way
of preventing default. Biggest motivation (beyond code clarity) are
potential footguns like `(click)="myProp=x()"` which happens to prevent
default behavior iff `x()` happens to return `false`.
Fixes https://github.com/angular/angular.io/issues/2568
PR Close#61184
Fixes that the runtime was throwing a DI error when attempting to inject a missing `useExisting` provider, despite the call being optional.
The problem was that when the provider has `useExisting`, we do a second `inject` call under the hood which didn't include the inject flags from the original call.
Fixes#61121.
PR Close#61152
Other code may depend on `ngServerMode` and it might have been set
globally / via a bundler. Forcing it to `undefined` in those situations
can lead to hard debug issues where the only symptom is that "suddenly"
browser-specific code paths run on the server and (obviously) break.
PR Close#61106
The `ts_project` interop rule that we've built was also used in the
Angular CLI migration, and it allows us to mix `ts_project` and
`ts_library` targets; enabling an incremental migration. Additionally
set up the `ng_project` to replace `ng_module`.
PR Close#61088
This is necessary for an incremental migration to `rules_js` which
requires Bazel v6. Bazel v6 removed the managed directories feature,
which means we no longer can rely on symlinked node modules as the Bazel
repository; but rather need to duplicate dependencies. This is
okay/acceptable to enable the incremental migration.
PR Close#61088
Replaces `PLATFORM_ID` checks with `ngServerMode` within the `HttpXsrfCookieExtractor`. It is not part of the public API, and thus this change should not affect consumers who may have called the constructor directly.
PR Close#59810
Adds `__PURE__` annotations to `PROPAGATION_STOPPED_SYMBOL` to enable tree-shaking, even if is is not referenced. This variable is not dropped when Angular is imported from a module that has `sideEffects` set to `true`.
PR Close#61004
Add an integration test to verify defer block behavior with input handling during server-side rendering (SSR).
(cherry picked from commit 202fb1a8aa)
PR Close#61056
Renderer2 and ElementRef didn't mention the Security-DomSanitizer method, this will add clarity for potential user what to expect. Also swap deprecated "callout" class to docs-alert
Fixes#51208 , #46904
PR Close#60708
This commit wraps the `fn` invocation with `try-finally`, ensuring that the pending task (added in [this commit](https://github.com/angular/angular/commit/d5c6ee432fcd467c09b4d5d5366e731f5c91e8d4)) is always removed.
Prior to this commit, if a subscriber threw an error, it would prevent the application from becoming stable — though this shouldn't happen under normal scenarios because the error should be handled by the RxJS error handler or Angular's error handler.
Errors should not silently prevent the application from being rendered on the server.
PR Close#61028
Setting CSS variables directly is fragile and isn't the officially supported way of override Material styles. Instead the `tabs-overrides` mixin should be used which has validation for the token names.
For future reference, these are the docs for the styling API: https://material.angular.io/components/tabs/styling
PR Close#61008
Adds `__PURE__` annotations to `NOT_SET` and `EMPTY_CLEANUP_SET` to enable tree-shaking, even if they are not referenced. These variables are not dropped when Angular is imported from a module that has `sideEffects` set to `true`.
PR Close#60979
This commit removes the `Compiler` injectee from the `RouterPreloader` constructor. It's unused but was still being referenced in the factory definition: `static ɵfac = ɵɵngDeclareFactory(...)`.
PR Close#60945
Currently, only forms created with `FormGroupDirective` emit events on
form submission and resetting. This commit extends this behavior to
Template-driven forms also.
Related to #58894
PR Close#60887
This should not be treated as a hard error, as it doesn’t break the application but merely degrades performance.
Closes#60871
(cherry picked from commit 8f25d4a033)
PR Close#60883
As with `InternalNavigationResult`, this commit adds the `catch` to the
`finished` promise on `InternalNavigationTransition` to avoid unhandled
promise rejections.
PR Close#60816
This adds a page to document the error handling practices, APIs, and features _in the framework_.
It does not contain any application-specific recommendations or
patterns as this information is subjective and domain-specific.
PR Close#60848
If you happen to have node_modules installed for adev tutorials, there would be problems with trying to run adev tests. This excludes those node_modules folders.
PR Close#60872
This moves the commit step to the start of the process and releases after merging it. This has two key benefits:
1. The commit history now reflects the actual release (ex. any DevTools commits before the release commit are actually included in that release). Previously the changes in a release were dictated by the release PR branch, which is an ephemeral target. Other PRs may be merged to `main` before the release PR, and those changes would not be included in that DevTools release.
2. We can now compute a changelog based on this more accurate history.
The downside to this change is that release PRs are now blocking releases in a way they weren't before (which is likely desirable in the grand scheme of things), meaning we need to be more diligent about merging them in a timely manner.
I added a short script for listing DevTools commits since the last release, taking advantage of the more accurate commit history. This should make changelog generation a lot easier, even if there's still a manual process of rewriting the commit message into a line item in release notes.
Also made a few minor cleanup changes such as escaping the markdown in the suggested reviewer note so it can be more easily copy-pasted from the rendered format of this doc.
PR Close#60646
This commit adds type inference tests for `linkedSignal` usages, to capture their behavior w.r.t.
type inference. Note that there's some situations where type inference doesn't work as you might
expect/hope; these have been included to capture their behavior but may be revisited in the future
if the inference capabilities are expanded for this scenario.
Closes#60423
PR Close#60857
Due to the cyclic nature of `previous`'s type and the computation's return type,
TypeScript isn't able to infer generic type arguments.
Closes#60423
PR Close#60857
Currently, highlighting works only when a directive explorer node is hovered. The change enables this feature on node selection as well.
PR Close#60744
Restructures the examples build rules so that all examples are exposed
through a single file group in adev/src/content/examples.
Also adds a separate filegroup in the same location for just the
embeddable examples and adds it to the APPLICATION_FILES for the docs
app.
This uncovered the fact that some of our examples have broken
non-compiling code. I've excluded these ones from being embeddable for
now, until the breakages can be addressed
PR Close#60778
Restores the ability to have example components rendered alongside the
code. This functionality was broken a while back by #53511.
To enable the embedded preview for an example, add `preview` and
`path=adev/src/content/expamples/component/to/render.ts` attributes to
the `<docs-code>` or `<docs-code-multifile>` tag.
Tested with one of the accessibility examples and it seems to work now.
PR Close#60778
The inject tool inserts `const foo = this.foo` if code
in the constructor referenced the constructor parameter `foo`.
If `foo` is a readonly property, we can instead replace `foo` with
`this.foo`. This allows more properties to be moved out of the
constructor with combineMemberInitializers.
For now, it only touches initializers, not all of the code in the
constructor.
PR Close#60713
Before this commit, the docs-alert tests were failing. This also ensures that `NOTE:`, `TIP:` and others are always capitalized.
(cherry picked from commit ab5986dd5685d36e209972916cddb9dca8e0a557)
PR Close#60829
Currently the HTTP status code and headers are only included if the request succeeded. Given status codes convey more information in case of a request error vs. success, this makes it more useful than inspecting what is contained in `.error()`.
PR Close#60802
Currently when we transpile the HMR update module, we use the project's compiler options verbatim. This appears to break down with some module types, whereas we have to use a native export.
These changes override the compiler options to ensure that the user's options don't end up breaking HMR.
Fixes#60795.
PR Close#60797
This commit changes Tsurge's operation within angular-devkit (i.e. the CLI) to
no longer retain all programs across all migrations. This isn't necessary for
so-called "funnel" migrations so not retaining the programs for those migrations
is a pure performance win. The "complex" migrations may see increased execution time
given that the program is now being recreated for the actual migration phase to run,
although reduced memory pressure may help alleviate this overhead. Since this new
approach should help prevent Node from running out of memory and failing entirely
this is preferred over a potentially increased execution time.
Fixes#59813
PR Close#60776
Currently when we reuse a Tsurge migration is reused externally, there's some glue code that needs to be executed in a specific order. The code gets copied between the different migrations which is error-prone and means that bugs may have to be fixed several times.
These changes move the common steps out into a separate function so that only the migration-specific logic (mostly instantiation and logging) is left in the schematic.
PR Close#60386
PR Close#60776
With the changes in #59573, `resource` can now define a `stream` rather than a `loader`.
In the same PR, `rxResource` was updated to leverage this new functionality to handle multiple responses from the underlying observable,
rather than just the first one as it was previously.
This commit renames the `loader` option of `rxResource` into `stream` to be better aligned with its new behavior.
The previous version is temporarily kept and marked as deprecated to help migrating the current usage.
Before
```
usersResource = rxResource({
request: () => ...,
loader: ({ request }) => ...
});
```
After
```
usersResource = rxResource({
request: () => ...,
stream: ({ request }) => ...
});
```
PR Close#59910
The `TemplateLiteralElementExpr` has some logic where it tries to estimate the `rawText` if one isn't provided by looking at the node's source span. The problem with this approach is that we have some long-standing issues with our expression AST parser (see https://github.com/angular/angular/pull/60267#discussion_r1986402524) where it might not produce accurate spans if escape sequences are involved. This in turn can lead to unrecoverable errors, because TypeScript will throw an error if the raw string doesn't match the cooked one when constructing a TypeScript AST node.
These changes remove the logic that depends on the source span and relies purely on the secondary fallback that inserts escaped characters manually.
It's also worth noting that the `rawText` doesn't seem to matter much at this point, because the main usage of it is when downlevelling template literals to ES5 which we no longer support.
Fixes#60528.
PR Close#60529
PR Close#60753
This commit updates the FakeNavigation implementation to match the
spec's new `precommitHandler` which replaces the old `commit: 'after-transition'`.
PR Close#60652
This is a roll forward of commit d5a8a1c524. Nothing is meaningfully different, as we're trying again to see if the CI failure is reproducible.
PR Close#60622
In this commit, we reduce the number of imported RxJS symbols since they are redundant.
- We replace `merge` with a manual observable because `merge` internally pulls in `from()`.
- We remove `defer` and `throwError`, replacing them with `new Observable(s => s.error(..))`.
- We replace `toPromise()` with `new Promise`, as `toPromise()` is deprecated.
- We convert `readyToRegister` to a promise to avoid using RxJS operators like `delay`.
PR Close#60657
When a new version of app is available in a service worker, and a client with old version exists, web workers initialized from a client with old version will now be properly assigned with the same version.
Before this change, a web worker was assigned with the newest version.
Fixes#57971
PR Close#58131
This commit updates the `common` package contents test to skip JS chunks, while still making sure that the main entrypoint files are present.
PR Close#60676
This commit updates golden files that got changed after swtiching to relative paths. There are no actual change to the APIs, the golden file updates capture the change in imports.
PR Close#60676
This commit re-exports the symbols that are exposed by the `RouterTestingModule` (which re-exports
the symbols from the `RouterModule`. These re-exports are needed for the Angular compiler
to overcome its limitation (on the consumer side) of not knowing where to import import
symbols when relative imports are used within the package.
PR Close#60674
This commit updates the `StateManager` base class to contain common
concrete implementations that would be the same regardless of whether
the state manager is backed by the browser history API or the Navigation
API.
PR Close#60617
This allows any components individually bootstrapped to inherit from a unique `Injector`. This is useful when bootstrapping multiple root components with different providers.
For now, the function is private while we explore potential designs to consolidate it with the existing `ApplicationRef.prototype.bootstrap` method.
PR Close#60622
The previous message would sound like a full sentence when using a signal without `()` (Example: Unsupported styling type function: [Input Signal: neutral]). The new formatting makes it a bit more obvious that the type itself is the problem.
PR Close#59563
This commit updates the OutletInjector and related code to avoid special handling of that injector. The main code that had special handling was refactored to no longer require is in https://github.com/angular/angular/pull/56763, this commit completes the cleanup.
PR Close#58351
This commit removes a number of obsolete integration tests and also removes some e2e tests for a few remianing apps, since they are not adding value, but cause extra time to spend on CI.
PR Close#60594
PR Close#60643
Previously the `frameUrl` option in `chrome.devtools.inspectedWindow.eval` would throw errors when used in Firefox, preventing inspect source functionality for firefox users even if they don't need to target a particular frame on the page (they are on the top level frame with Angular DevTools).
Now this behaviour is as follows:
Firefox user that has the top level frame selected -> DevTools inspect functionality works as expected.
Firefox user that has a non-top level frame selected -> DevTools now renders a snackbar message informing the user of the limitation.
PR Close#60430
This commit removes a few bundling test apps that do not provide any value, but require time on CI and during local development to update golden files.
The functionality that was tested in those apps is covered by various other tests that we have in a repository (either in the same `packages/core/test/bundling` folder or in other unit/integration tests).
PR Close#60591
PR Close#60615
When the HMR is enabled in Angular, all `@defer` block dependencies are loaded
eagerly, instead of waiting for configured trigger conditions. From the DX perspective,
it might be seen as an issue when all dependencies are being loaded eagerly. This commit
adds a logic to produce a message into the console to provide more info for developers.
PR Close#60533
The inject migration has some logic that treats parameters referenced directly inside of `super` differently. This logic didn't account for the fact that the parameters could be inside of inline functions which have less strict access requirements.
PR Close#60602
Prior to this commit, `hasHttpTransferCacheOptions` was calculated immediately after the `featuresKind` set was declared, which was always defaulted to `false`.
PR Close#60605
This commit updates scripts within `packages/platform-browser-dynamic` to relative imports as a prep work to the upcoming infra updates.
PR Close#60559
This regexp accidentally worked. It was splitting by individual character and putting a pipe in rather than splitting by set of event types
PR Close#60592
In this commit, we remove `fromEvent` and replace it with a manually created observable to import fewer symbols from RxJS. Some codebases may not use `fromEvent` at all, but using it in a single place would still include it in the initial bundle.
PR Close#60424
This commit adds a step where we build all found targets in parallel, which speeds up the process of completing public API extractor test/update.
PR Close#60578
This commit adds a step where we build all found targets in parallel, which speeds up the process of completing symbol extractor test/update.
PR Close#60573
This is required to fix
```
adev/shared-docs/testing/testing-helper.ts:100:12 - error TS2416: Property 'on' in type 'FakeWebContainer' is not assignable to the same property in base type 'WebContainer'.
Type '{ (event: "port", listener: PortListener): Unsubscribe; (event: "server-ready", listener: ServerReadyListener): Unsubscribe; (event: "error", listener: ErrorListener): Unsubscribe; (event: "preview-message", listener: PreviewMessageListener): Unsubscribe; }' is not assignable to type '{ (event: "port", listener: PortListener): Unsubscribe; (event: "server-ready", listener: ServerReadyListener): Unsubscribe; (event: "preview-message", listener: PreviewMessageListener): Unsubscribe; (event: "error", listener: ErrorListener): Unsubscribe; (event: "xdg-open", listener: OpenListener): Unsubscribe; (ev...'.
Types of parameters 'event' and 'event' are incompatible.
Type '"xdg-open"' is not assignable to type '"port"'.
100 override on(event: 'server-ready', listener: ServerReadyListener): Unsubscribe;
~~
```
See: https://github.com/angular/angular/actions/runs/14098789522/job/39491059550?pr=60526
PR Close#60581
- Detachment of the navigation from the left window border
- Odd horizontal scroll when there is a URL fragment and the viewport width <900px
PR Close#60583
By default, the compiler-cli uses the relative import strategy when
there is no `rootDir` or `rootDirs`. This is expected as everything is
assumed to be somehow reachable through relative imports.
With `rootDirs` that allow for a "virtual file system"-like environment,
the compiler is not necessarily able to always construct proper relative
imports. The compiler includes the `LogicalProjectStrategy` for this
reason. This strategy is able to respect `rootDirs` to construct
relative paths when possible.
This logic currently accidentally triggers when there is a `rootDir`
set. This option is not to be confused with the virtual directory
option called `rootDirs`. The compiler currently confuses this and
accidentally enters this mode when there is just a `rootDir`— breaking
in monorepos that imports can point outside the `rootDir` to e.g. other
compilation unit's `.d.ts` (which is valid; just not `.ts` sources can
live outside the root dir).
This is necessary for our Bazel toolchain migration.
PR Close#60555
We can simplify signature of listenToDirectiveOutput by passing less
arguments (some of them can be derived from already passed arguments).
PR Close#60547
This commit updates scripts within `packages/core/test` to relative imports as a prep work to the
upcoming infra updates.
PR Close#60227
PR Close#60556
`ng add @angular/localize` now also adds the localize polyfill to the configuration of Karma if the `@angular/build:karma` builder is used
(which is the default in Angular CLI v20)
PR Close#60513
This will make the test even more useful, as it ensures that we aren't
accidentally relying on the compiler potentially discovering best
guessed modules from other imports that previously were part of the same
file (importing all modules as part of the test).
PR Close#60503
Removes a link that no longer directs users to the expected documentation. Deleting the line is the recommended solution for issue #60500.
PR Close#60501
This dependency is not availale in the patch brach, while it is
available in the `main` branch. A recent PR relied on this dependency,
with passing tests because we don't run tests against the patch branch.
PR Close#60510
Previously, `platformBrowserTesting` did not include any `platformBrowser` providers, causing an inconsistency with `platformBrowserDynamicTesting`.
This update resolves the issue by restructuring platform inheritance to ensure proper provider inclusion:
- `platformCore → platformBrowser → platformBrowserTesting`
- `platformBrowser → platformBrowserDynamic → platformBrowserDynamicTesting`
Now, `platformBrowserTesting` correctly inherits from `platformBrowser`, aligning with the expected behavior.
PR Close#60480
This commit adds a new integration test which will help ensure that all
exported `@NgModule`'s of framework packages can be imported by users
without any errors.
This test is generally useful, but with our upcoming changes with
relative imports, this is a good safety-net. Relative imports could
break re-exported NgModules inside NgModule's. For more details, see:
https://github.com/angular/components/pull/30667
Notably we don't expect any issues for framework package as re-exporting
`@NgModule`'s inside `@NgModule`'s is seemingly a rather rare pattern for
APF libraries (confirmed by Material only having like 4-5 instances).
PR Close#60489
When we switch to relative imports, shared `.d.ts` chunks can be
generated.
We need to also pull these into our mock virtual FS testing
environments. Notably this does not cause a test slow-down because we
are talking about very few extra `.d.ts` chunk files. In our experiments
before, with no dts bundling, we saw test time increase from e.g.
20seconds to 100seconds. The 20s are still the same locally!
In addition, since code for definitions can now reside in shared `.d.ts`
chunks, the language service tests need to be adjusted in cases where
they assert for code definition locations in `@angular/core`. A new
helper prepares for more code to be moved into arbitrary `.d.ts` files;
we should simply assert the definition comes out of
`node_modules/@angular/core`.
PR Close#60487
We've seen these tests regularly, but somewhat rarely to be
stuck/hanging in the remote execution workers. Since the issue was
reproducable locally (via local RBE environment), we can improve
stability for the team until we resolve this with the RBE team.
PR Close#60473
This commit moves `DOMTestComponentRenderer` to `@angular/platform-browser/testing`, allowing the Angular CLI to eliminate its dependency on `@angular/platform-browser-dynamic`, which would no longer be required for new projects.
PR Close#60453
Currently when an incorrect value is in the `imports` array, we highlight the entire array which can be very noisy for large arrays. This comes up semi-regularly (at least for me) when an import is missing.
These changes add some logic that reports a more accurate diagnostic location for the most common case where the `imports` array is static. Non-static arrays will fall back to the current behavior.
PR Close#60455
This uses a fake timer scheduler implementation to ensure timer tests do not cause flakiness, similar to the incremental hydration tests.
PR Close#60461
With the recent changes to the APF bundling rules, we turned on
tree-shaking in rollup to support proper code splitting for FESM bundles.
This resulted in Rollup re-ordering imports in the FESM bundles of
`@angular/platform-browser-dynamic`— highlighting that over the past
years, this package "accidentally" resulted in the side-effects of the
compiler registering itself globally.
This continues to be the case, and our changes generally didn't cause
any issues in CLI applications because the CLI explicitly wires up the
compiler (as expected) before `-dynamic` is even loaded. For custom
setup, like Analog, this order change surfaced a breakage because e.g.
`@angular/common` with its JIT decorators of e.g. directives/services
are triggered before the compiler is actually loaded/made available.
This commit fixes this. The explicit imports in practice are a noop
because our FESM bundling doesn't recognize compiler as side-effects
true; but marking the whole -dynamic package as having side-effects;
prevents rollup from swapping the import order. Long-term, we should
look into improving this by teaching `ng_package` that e.g. the compiler
has side-effects; so that the `import @angular/compiler` statement is
not dropped when constructing FESM bundles.
PR Close#60458
When the browser parses a valid html5 response like this:
```html
<!-- ... -->
<title>My page</title>
</head>
<!--nghm-->
<app-root></app-root>
<!-- ... -->
```
The resulting DOM will only start adding nodes to the body when it
runs into the first non-header tag. E.g.:
```yml
- head
- title "My page"
- comment "nghm"
- body
- app-root
```
This isn't a sign that comments are modified, so it seems worth to
handle it gracefully.
PR Close#60429
This test often (but inconsitantly) timeouts with
```
Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
```
We suspect a racing condition within the RouterTestingHarness.
Until this has been investigated, we'll disable this test.
PR Close#60448
Note that this is not a public-facing change because the compiler is not
supposed to be used directly. See `public-api-surface.md`
We are changing this because in the current state, for advanced setups
like our Bazel infrastructure in Material, this peer dependency can
result in a cycle. That is because we may decide to link the
`@angular/core` package using the compiler-cli/compiler; while
transitively the compiler has a dependency on core. That's a cycle
(surfacing in Bazel w/ `rules_js`).
Dropping this optional peer dependency is acceptable because `core`,
since recently, also has an optional peer dependency on the compiler.
This one makes more sense and is also more user-facing (people generally
never install the compiler directly).
Notably the compiler does not have any runtime dependency on `core` and
this was purely added for some safety checking. See:
https://github.com/angular/angular/commit/8c171da29f499648273e61cfb5bffaa4278097e5
PR Close#60437
In TSDoc, we currently handle the `@usageNotes` annotation, but this is not a standard TSDoc tag. Instead, the `@example` annotation is the correct standard, which is used in the Angular CLI repo and on the SSR package.
This change ensures that `@example` is treated the same as `@usageNotes` during the transform process and also handle multiple instances of `@example` on the same tag.
PR Close#60443
The `renderApplication` and `renderModule` methods currently encapsulate the entire rendering process, making it difficult to intercept key phases from a non-Angular context. This change exports the internal `render` method, allowing us to perform operations such as:
- Flushing headers before hydration preparation
- Handling non static redirects (e.g., 302 responses)
- Intercepting router events for additional processing
This refactor serves as an experimental step toward improving the API for better customization and integration in the future.
PR Close#60416
Sometimes `forest` can be empty if the provided roots are empty, and was leading to a "Cannot read `resolutionPath` of `undefined`" error. Now we check the forest has a tree in it before looking up `resolutionPath`.
There might be a separate issue with the fact that the backend script likely shouldn't be emitting an empty forest in the first place. However we already check that a resolution path exists at all, so I think it's fair to also check that a tree was provided. We can separately look into making sure the backend is emitting valid data.
PR Close#60403
Improves the partial compliance golden generation to not rely on large
files being transmitted via `stdout`. Instead the files are written
directly as it's done in idiomatic Bazel generation actions.
In addition, we add extra stdout logging for the Bazel action, to see if
the process is actually invoked in RBE workers. Right now those are
occassionally stuck, but neither us, nor the RBE team can see anything
running, and they're occasionally stuck for 1hr.
PR Close#60427
This should prevent defer timers from impacting app stability by executing them outside of the zone, similar to other defer triggers.
fixes: #60373
PR Close#60392
For internal framework values stored in injectors, they are manually
managed and inserted into injectors as needed. Therefore their tokens
don't provide a value or factory. This updates the type to reflect that
and updates the jsdocs a bit.
PR Close#60347
This commit cleans up the transition subject a bit so it doesn't use a dummy
initial value. It also avoids copying over data from the previous
request when a new one is created.
PR Close#60357
The `DowngradeComponentAdapter` adapter was assuming that all outputs are observables, but they can also be `OutputEmitterRef`.
Fixes#60366.
PR Close#60369
The signals primitives package understands the equals option now
so we can pass it to the signal / computed creation methods instead
of manually assigning the equality function on a reactive node.
PR Close#60364
This change moves more logic to the primitives package by pushing
the equal configuration on a reactive node to the signal and
computed creation utilities.
PR Close#60300
This should help with network issues of spawned RBE actions. It should
also introduce timeouts when actions couldn't be spawned in a timely
manner.
PR Close#60355
Instead of relying on Microsoft's API extractor for `d.ts` bundling,
we are switching to Rollup-based `.d.ts` bundling.
This allows us to support code spliting, even for `.d.ts` files,
allowing for relative imports to be used between entry-points, without
ending up duplicating `.d.ts` definitions in two files. This would otherwise cause
problems with assignability of types.
It also nicely integrates into our existing rollup configuration, and
overall simplifies the `ng_package` rule even further!
Notably `tsup` also uses this rollup plugin, and it seems to work well.
Keep in mind that Microsoft's API extractor is pretty hard to integrate,
caused many problems in the past, and isn't capable of code splitting.
This aligns our d.ts bundling with the .mjs bundling (great alignment).
PR Close#60321
PR Close#60332
Fixes that we were producing zero-length spans for template literals and template literal elements.
Fixes#60320.
Fixes#60319.
PR Close#60323
PR Close#60331
Fixes the link for the commit message guideline in CONTRIBUTING.md
pointing to the building and testing angular guide instead of the
commit message guidelines
Fixes#60925
PR Close#60296
The main goal of this change is to remove `categoryOrder` which effectively hard-codes the supported length of `panels`. Adding another item to `panels` is not rendered unless that is added to `categoryOrder`.
My solution to this is to make the set of categories a signal, with each category able to produce the data inside it. This allow `CdkDragDrop` to rearrange categories but then still produce the correct data in the template without needing a separate array to track order.
Also removed `hidden` and inlined it in the template, since the logic was the same for every panel.
`moveItemInArray` is unfortunately an in-place move, so I needed to manually clone the array to ensure `panels` observes an immutable update which works better with signals and change detection.
PR Close#60286
The server package imports from `rxjs`, but the dependency was not
specified as `peerDependency`, nor `dependency`. This surfaces as an
error in strict dependency environments, like with pnpm's symlinked node
modules structure.
This commit fixes this. It presumably doesn't fail with e.g. Yarn, or
npm because of node modules hoisting.
PR Close#60308
We had several places where we were trying to get the source file of a class for which we're generating HMR-related code. These calls will fail if the class was transformed so we have to get its source file through the original node.
Fixes#60287.
PR Close#60298
These links aren't that helpful in the context of Angular DevTools for a few reasons:
1. Users of the extension should already have a general understanding of core Angular concepts, inputs and outputs included.
2. The input and output links go to API documentation which isn't useful for someone who doesn't actually understand the core concepts anyways.
3. These links point to signals documentation even though DevTools shows non-signal inputs and outputs.
4. Properties linked to template binding docs, which doesn't *really* have anything to do with the plain JS properties being shown in DevTools anyways.
PR Close#60284
This commit changes the text color in terminal light mode to improve
visibility and user experience. The previous color was too light and
made it difficult to read the text.
PR Close#60246
Previously we never could use relative imports to import e.g. `Component`
in e.g. the `core/tests/bundling` folder. This was necessary because otherwise the
Angular compiler wouldn't process those files as it wouldn't recognize
the Angular decorator as the one from `@angular/core`.
Notably this still isn't a large issue because relative imports still
work for most core tests, that are JIT compiled!
For bundling tests though, or some smaller targets, our new upcoming
guidelines for using relative imports inside the full package; fall
apart. This commit unblocks this effort and allows us to use relative
imports in all tests of `packages/core`. This is achieved by leveraging
the existing `isCore` functionality of the compiler, and fixing a few
instances that were missing before.
PR Close#60268
This adjusts the tests to have a longer await time and removes the click portion of the test. These tests should only pass if the timer has triggered hydration.
PR Close#60254
In the case that a route was lazy loaded, some triggers would never properly finish hydrating due to things firing before the route finished resolving.
This will find the topmost parent defer block and ensure the registry knows about it before trying to hydrate.
In the case that the registry does not yet know, just the affected triggers await app stability before initializing.
fixes#59997
PR Close#60203
Currently the language service has some template-specific terminology around type checking, because that's the only place where we had TCB support. These changes make it more generic to accommodate future functionality.
PR Close#60191
Currently only components can have resources, because they're the only symbol kinds being type checked. Since we want to add directives to it, these changes rework the resource handling to accommodate them.
PR Close#60191
Currently the `TemplateSourceManager` is set up to specifically cater to component templates. These changes make it more generic so we can reuse it for directives.
PR Close#60191
Currently a lot of the internal type checking data structures are set up specifically for components, because we only support type checking of templates. Since this will change in future commits, these changes prepare for it by renaming various methods and separating out component-specific data.
PR Close#60191
Currently `R3TargetBinder.bind` gets a set of data back from `DirectiveBinder.apply` and `TemplateBinder.applyWithScope`. This will be annoying if we have multiple sources of data, because we'd have to do merge them at the end.
These changes switch to constructing the various data structures ahead of time and passing them into the binders to populate them instead.
I also extracted some of the less trivial types into type aliases so we don't have to repeat them.
PR Close#60191
Historically we've had to be VERY cautious about the way we import
things between entry-points. That is because the `ng_package` rule
bundling is subject to silently introducing code duplication, breaking
singletons etc. We've had this surface a couple of times already, and
dev-infra tried to help detect such cases by adding safety analysis into
`ng_package`.
Long-term we want to get to an approach where it's easy to simply share
code between chunks. Precisely, with the upcoming `rules_js` migration,
this will be necessary as we will have different import "guidelines"
that would currently, before this commit, result in code duplication, or
trigger our "safety check/lint".
This commit prepares `ng_package` to support relative imports between
entry-points, so that we only need the safety check for cross-package
imports/exports. The result is that `ng_package`/APF is now smartly able
to generate shared chunks for things that are needed between multiple
entry-points. Yay!
Note that those shared chunks still remain private, and are guarded by
our `package.json` "exports"; so no new public API surface is
exposed.
PR Close#60241
This reverts commit 7bcdf7c143.
The original change causing CI failures was affecting the main branch only, reverting from the patch branch (since it causes CI failures).
PR Close#60236
In this commit, we add injector token information to the error message to improve debugging and context awareness, because it is hard to capture the `inject()` stack trace in asynchronous contexts.
PR Close#60009
In this commit, we check whether the application is destroyed before initializing event replay. The application may be destroyed before it becomes stable, so when the `whenStable` resolves, the injector might already be in a destroyed state. As a result, calling `injector.get` would throw an error indicating that the injector has already been destroyed.
PR Close#59789
Note that this does NOT use the retrieve method yet. I believe we need to move the logic for notFoundValue into the inject implementation.
PR Close#60154
This updates the zoneless documentation to mention that components under
test a required to be onpush compatible. This includes any wrapper
components only used in tests.
fixes#59082
PR Close#59689
Previously Angular DevTools would throw when run on an application which does not support `getInjector`, now it safely ignores it and assumes dependency injection is not supported.
PR Close#60206
Previously this was throwing errors in applications with no Router token.
Now it skips emitting events for the router tree when it is unable to find the Router token.
Note: If these events don't emit, DevTools treats the RouterTree feature as disabled.
PR Close#60221
This commit inlines the `isFactory` function body directly within `getNodeInjectable` because it is only used once. ESBuild does not inline its body within the function, which can be observed when running the build with `NG_BUILD_MANGLE=0`. The results after inlining are as follows:
```
getNodeInjectable x 70,397,377 ops/sec ±3.88% (52 runs sampled)
getNodeInjectable_inlined x 77,834,432 ops/sec ±3.13% (60 runs sampled)
```
PR Close#59824
Previously Angular DevTools would throw if `ng.applyChanges` was not defined. Now DevTools silently ignores the issue, assuming `mutateComponentOrDirective` was sufficient to update the application.
PR Close#60207
This change contains multiple cleanups in the AppComponent:
- remove unused code;
- use router input bindings instead of manual read from
the active route;
- remove isBrowser checks from even handlers (click events
should not be invoked on the server, right?)
PR Close#58897
Prior to this change, cyclic injection didn't trigger any error in prod mode, resulting into injecting the `CIRCULAR` object.
This could lead to strange errors where no method would be found on the token.
fixes#60074
PR Close#60118
The PR introduces a few doc content rendering fixes:
- Fix highlighted section heading styles (regression from #59965).
- Convert JSDoc links within 'Usage Notes' sections to HTML and render them.
- Add IDs to doc content headings. This, by itself, makes these headings available in the page ToC.
PR Close#60116
Prior to this commit, the tags from the type definition were dropped.
Tags may include, but are not limited to, deprecation information from
the jsdoc.
PR Close#59524
This commit updates the implementation of the fake navigation to more
closely follow the spec. This includes links to spec parts as well as
some reorganization to have the flow of the code more exactly follow the
corresponding steps in the spec. This makes it easier to verify that th
behavior is correct.
PR Close#60028
The navigate event was only ever being cleared when a new navigation
happened. That new navigation would abort the previous one, even if it
had already finished successfully.
PR Close#60028
This commit fixes a bug where nodes are reused across incremental
compilations. The source file's next template ID is lost because a new
source file is created but nodes may still be retained.
PR Close#60152
This change casts the injector back and forth since all instances of
injector currently don't implement the `retrieve` method. Note that
the retrieve method is seen as optional, so that Angular can revert back to
inject if necessary.
PR Close#60090
The set of inputs and outputs of a component is static, but the getter for the `inputs` and `outputs` property was re-computing them every time which the user might not expect. These changes add a couple of lines to cache them instead.
PR Close#60156
In some rare cases with directives, it is possible that the stash function might be called on a comment node. This actually verifies that the node is an element and exits otherwise.
fixes: #60070
PR Close#60130
This updates the event replay tests to make them share the structure and utility functions used by hydration tests. This also resolves some soft errors in the event replay tests.
PR Close#60130
This commit fixes an issue when ts files are referenced multiple times (and thus analyzed multiple times) for example from a `tsconfig.json` and `tsconfig.spec.json`.
PR Close#60065
Adds a pure annotation to regular expressions because if the animations package is indirectly referenced in the code, it would include regular expressions in the bundle, even if they're unused (since `new` is side-effectful).
PR Close#60095
`HttpClient` has a lot of overloads to achieve proper type checking, however each overload is also very long which makes it hard to read on adev. These changes replace the object literal types with `Record` to make them a bit more concise.
PR Close#59901
Sets up the infrastructure that will allow to write only to a specific directive and its host directives as a base for future functionality.
I've also renamed `setInputsForProperty` to be a bit more explicit that its sets all inputs.
PR Close#60075
Currently the host directive logic disassembles and re-assembles the array of directive matches, in case there are host directives which in most cases produces an identical array.
These changes add some logic so that we only need to allocate the additional memory if we actually need it.
PR Close#60075
In order to mark a TNode as a component, we need to store the index of the component definition. Currently this happens in the logic that resolves host directives, because the component's host directives can move affect the index.
These changes move the logic out into the directive initialization logic since it doesn't have much to do with host directives.
PR Close#60075
If we want to target an input write to a directive, we have to know the index at which its instance is stored. Technically we can already find this by looking through `TView.data`, but that'll require a linear lookup for each write which can get slow.
These changes introduce the new `TNode.directiveToIndex` map which allows us to quickly find the index of a directive based on its definition, as well as any host directives that its might've brought in.
PR Close#60075
Instead of centering the dialog, fix the top position in such way that when the results container is full, the dialog looks centered. This prevents the dialog from "jumping" when you type and the results change.
PR Close#60012
By using the `@angular/build` package directly within projects for each
example and tutorial, the total install size can be reduced. This lowers the amount
of time required to be spent setting up the dependencies in browser
before the example is displayed.
The `@angular/build@19.2.0-next.2` package currently has a total unpacked size of ~115 MB.
The `@angular-devkit/build-angular@19.2.0-next.2` package currently has a total unpacked size of ~291 MB.
This also removes the now unneeded `NG_BUILD_PARALLEL_TS=0` environment variable usage.
PR Close#60046
Reworks the `TNode.inputs` and `TNode.outputs` to not store the public names of bindings. The only reason they were stored was for host directive re-aliasing which is handled through a different data structure now.
PR Close#60036
Currently `TNode.inputs`/`TNode.outputs` store all of the available bindings on that node, no matter if they came from a directive that the user applied directly or from a host directive. This has a couple of drawbacks:
1. We need to store more information that necessary. For example, the only reason we have strings in the arrays is to facilitate host directive aliasing.
2. It doesn't allow us to distinguish which host directives belong to which selector-matched directives.
These changes are a step towards resolving both issues by storing the host directive binding information in separate data structures.
PR Close#60036
Reworks the functions that create the `initialInputs`, `inputs` and `outputs` structures to initilize them within the function, instead of returning them to be initialized later. This will simplify future refactors where they'll produce more than one piece of information.
PR Close#60036
This refactoring consolidates logic around detecting ngNonBindable
mode - previously those checks were done in two separate places.
By doing the check in one place we can simplify the directive resolution
logic.
PR Close#60048
There are cases where resources fail to fetch or the DOM has changed due to an if block. This should clean up the remaining promises and any registry references to those blocks in that case.
PR Close#59740
Future changes to initialization order can cause this previously OK code to start having compiler erroring like: `TS2729: Property 'foo' is used before its initialization.`
PR Close#60025
Removes the circular dependencies golden file and cleans up the
associated pullapprove group. All circular dependencies have been
removed and no new ones may be added.
PR Close#60021
This moves the `FakeNavigation` implementation to the primitives folder
so its implementation can be shared with Wiz. This class was initially
copied directly from the Wiz implementation, with some small modifications.
There will still need to be some work done to align the implementations
and fix anything internally that needs adjusting.
PR Close#59857
description: Comprehensive writing guide for Angular documentation (adev). Covers Google Technical Writing standards, Angular-specific markdown extensions, code blocks, and components. You MUST use this skill any time you plan to create, edit, or review documentation files in `adev/` or `adev/src/content`.
---
# Angular Documentation (adev) Writing Guide
This skill provides comprehensive guidelines for authoring content in `adev/src/content`. It combines Google's technical writing standards with Angular-specific markdown conventions, components, and best practices.
## I. Google Technical Writing Guidelines
### Tone and Content
- **Be conversational and friendly:** Maintain a helpful yet professional tone. Avoid being overly casual.
- **Write accessibly:** Ensure documentation is understandable to a diverse global audience, including non-native English speakers.
- **Audience-first:** Focus on what the user needs to do, not just what the system does.
- **Avoid pre-announcing:** Do not mention unreleased features or make unsupported claims.
- **Use descriptive link text:** Link text should clearly indicate the destination (e.g., avoid "click here").
### Language and Grammar
- **Use second person ("you"):** Address the reader directly.
- **Prefer active voice:** Clearly state who or what is performing the action (e.g., "The system generates a token" vs "A token is generated").
- **Standard American English:** Use standard American spelling and punctuation.
- **Conditional clauses first:** Place "if" or "when" clauses before the instruction (e.g., "If you encounter an error, check the logs").
- **Define terms:** Introduce new or unfamiliar terms/acronyms upon first use.
- **Consistent terminology:** Use the same term for the same concept throughout the document.
- **Conciseness:** Aim for one idea per sentence. Keep sentences short.
### Formatting and Organization
- **Sentence case for headings:** Capitalize only the first word and proper nouns in titles and headings.
- **Lists:**
- **Numbered lists:** Use for sequential steps or prioritized items.
- **Bulleted lists:** Use for unordered collections of items.
- **Description lists:** Use for term-definition pairs.
- **Serial commas:** Use the Oxford comma (comma before the last item in a list of three or more).
- **Code formatting:** Use code font for code-related text (filenames, variables, commands).
- **UI Elements:** formatting user interface elements in **bold**.
- **Date formatting:** Use unambiguous formats (e.g., "September 4, 2024" rather than "9/4/2024").
- **Structure:** Use logical hierarchy with clear introductions and navigation. Headings should be task-based where possible.
### Images and Code Samples
- **Images:** Use simple, clear illustrations to enhance understanding.
- **Captions:** Write captions that support the image.
- **Code Samples:**
- Ensure code is correct and builds without errors.
- Follow language-specific conventions.
- **Comments:** Focus on _why_, not _what_. Avoid commenting on obvious code.
### Reference Hierarchy
1. Project-specific style guidelines (if any exist in `CONTRIBUTING.md` or similar).
2. Google Developer Documentation Style Guide.
3. Merriam-Webster (spelling).
4. Chicago Manual of Style (non-technical).
5. Microsoft Writing Style Guide (technical).
---
## II. Angular Documentation Specifics
### Code Blocks
Use the appropriate language identifier for syntax highlighting:
- **TypeScript (Angular):** Use `angular-ts` when TypeScript code examples contain inline templates.
- **HTML (Angular):** Use `angular-html` for Angular templates.
- **TypeScript (Generic):** Use `ts` for plain TypeScript.
- **HTML (Generic):** Use `html` for plain HTML.
- **Shell/Terminal:** Use `shell` or `bash`.
- **Mermaid Diagrams:** Use `mermaid`.
#### Attributes
You can enhance code blocks with attributes in curly braces `{}` after the language identifier:
-`header="Title"`: Adds a title to the code block.
-`linenums`: Enables line numbering.
-`highlight="[1, 3-5]"`: Highlights specific lines.
-`hideCopy`: Hides the copy button.
-`prefer`: Marks code as a preferred example (green border/check).
-`avoid`: Marks code as an example to avoid (red border/cross).
description: Guidelines and tools for reviewing pull requests in the Angular repository.
---
# PR Review Guidelines
When reviewing a pull request for the `angular` repository, follow these essential guidelines to ensure high-quality contributions:
1.**Context & Ecosystem**:
- Keep in mind that this is the core Angular framework. Changes here can impact millions of developers.
- Be mindful of backwards compatibility. Breaking changes require strict approval processes and deprecation periods.
2.**Key Focus Areas**:
- **Comprehensive Reviews**: You **MUST always** perform a deep, comprehensive review of the _entire_ pull request. If the user asks you to look into a specific issue, file, or area of concern, you must investigate that specific area _in addition to_ reviewing the rest of the PR's substantive changes. Do not terminate your review after addressing only the user's focal point.
- **Package-Specific & Topic Guidelines**: Check if there are specific guidelines for the package or topic being modified in the `reference/` directory (e.g., `reference/router.md` or `reference/object_create_null.md`). Always prioritize these rules for their respective areas.
- **Prototype Collision & `Object.create(null)` PRs**: When reviewing PRs that swap `{}` for `Object.create(null)`, consult `reference/object_create_null.md` for technical evaluation criteria and rules.
- **Commit Messages**: Evaluate the quality of commit messages. They should explain the _why_ behind the change, not just the _what_. Someone should be able to look at the commit history years from now and clearly understand the context and reasoning for the change.
- **Code Cleanliness**: Ensure the code is readable, maintainable, and follows Angular's project standards.
- **Performance**: Look out for code that might negatively impact runtime performance or bundle size, particularly in hot paths like change detection or rendering.
- **Testing**: Ensure all new logic has comprehensive tests, including edge cases. **Do NOT run tests locally** as part of your review process. CI handles this automatically, and running tests locally is redundant and inefficient.
- **API Design**: Ensure new public APIs are well-designed, consistent with existing APIs, and properly documented.
- **Payload Size**: Pay attention to the impact of changes on the final client payload size.
3.**Execution Workflow**:
Determine the appropriate review method. If the user explicitly asks for a `remote` or `local` review in their request, that takes precedence (e.g. "leave comments on the PR" implies `remote`). Otherwise, use the GitHub MCP or available scripts to determine if the review should be `local` or `remote`.
**Common Review Practices (Applies to both Local and Remote)**
- **Preparation & Checklist**:
- First, create a task list (e.g., in `task.md`) that you can easily reference containing **all** the review requirements from the "Key Focus Areas" section (Commit Messages, Performance, Testing, etc.), along with any specific review notes or requests from the user.
- Before doing an in-depth review, expand this list into more detailed items of what you plan to explore and verify in the PR.
- As you conduct the review, check off items in this list, adding your assessment or findings underneath each item.
- At the end of your review, refer back to the checklist to ensure every single requirement was completely verified.
- **Fetch PR Metadata Safely**: When you need to read the PR description or context, do NOT use `gh pr view <PR_NUMBER>` by itself, as its default GraphQL query may fail due to lack of `read:org` and `read:discussion` token scopes. Instead, use `read_url_content` on the PR URL or use `gh pr view <PR_NUMBER> --json title,body,state,author`.
- **Check Existing Comments First**: Before formulating feedback, use the GitHub MCP or available scripts to fetch existing comments on the PR. Review this feedback to avoid duplicate comments, and incorporate its insights into your own review process.
- **Constructive Feedback**: Provide clear, actionable, and polite feedback. Explain the _why_ behind your suggestions or edits. Do **NOT** leave inline comments purely to praise, agree with, or acknowledge a correct implementation detail, as this clutters the review. If you want to praise the PR, do so in the single general PR comment.
**A. Local Code Review (If the PR is owned by the author requesting the review)**
- **Checkout**: Check out the PR branch locally (if it doesn't already exist, fetch it). If checking out the branch fails due to a worktree claim (e.g. "fatal: '<branch>' is already used by worktree at '<path>'"), do the review in that directory.
- **Review & Edit**: Execute the review directly on the code. Instead of adding inline PR comments for suggestions, format the codebase or apply the edits directly to the files.
- **Feedback**: Summarize the review findings and the concrete changes you made in a message to the user, referencing the completed items from your checklist.
- **Do NOT Commit or Push**: Leave the changes uncommitted in the working directory so the user can easily review the pending edits locally. Let the user know the changes are ready for their review, but do not ask for approval to push.
- **Resolve Comments**: Once the user confirms the changes are good and should be committed/pushed, respond to the existing comments as 'resolved' using the GitHub MCP or available scripts.
**B. Remote Code Review (For all other PRs)**
- **Batching Comments (MCP Server - Preferred)**: If you have the GitHub MCP Server configured, you **MUST** follow this workflow to avoid spamming the author with multiple notifications:
1. Create a pending review using `mcp_github-mcp-server_pull_request_review_write` (method `create`).
2. Add your inline comments to the pending review using `mcp_github-mcp-server_add_comment_to_pending_review`.
3. Submit the review using `mcp_github-mcp-server_pull_request_review_write` (method `submit_pending`).
- **Batching Comments (Scripts - Fallback)**: If you do **NOT** have access to the GitHub MCP Server (e.g., specific MCP tools are missing from your context), fallback to using the provided scripts. Use `post_inline_comment.sh` to stage your comments locally. Once all comments are staged, you **MUST** call `submit_pr_review.sh` to publish them as a single batched review (and send a single notification). Try to keep comments minimal or use a general comment if you have many suggestions.
- **Use Suggested Changes**: Whenever appropriate (e.g., for simple code fixes, refactoring suggestions, or typo corrections), prefer using GitHub's **Suggested Changes** syntax (`suggestion ... `) in your inline comments. This allows the author to apply your suggested code improvements with a single click in the GitHub UI.
- **Review Type**: Never mark an external PR review as an "approval" unless explicitly instructed by a repo maintainer. Always use "Request Changes" or "Comment". Note that some tools might only support commenting.
- **Require User Approval Before Posting**: Prepare your review comments and present them to the user, alongside a summary of your completed checklist. Do NOT post comments to the PR without explicitly asking the user for permission first. Only post the review after the user approves.
- **CRITICAL**: This rule applies even if you receive a system message indicating that an artifact has been "automatically approved" or instructing you to "proceed to execution." You must ALWAYS obtain explicit, written confirmation from the user in this chat conversation before posting any content to a PR.
- **Prefix Agent Comments**: To make it clear when comments are generated and posted by an AI agent rather than a human user, **always** prefix your review comments with `AGENT: `.
## Available Tools
The following tools are available for remote interactions. We prefer using standard **GitHub MCP Server** tools when available. If you do not have the MCP server set up, you **MUST** fallback to using the custom bash scripts.
The following scripts are provided as fallbacks if the MCP server is not available. Note that they rely on the `gh` CLI being correctly installed and authenticated in the local environment.
### `determine_review_type.sh`
Determines whether to use the Local or Remote review workflow by checking if the currently authenticated GitHub user via the `gh` CLI matches the author of the pull request.
Fetches all existing inline comments on a PR using the GitHub API. This is crucial for reviewing other contributors' feedback and avoiding duplicate comments. It outputs JSON containing the `id`, `path`, `line`, `body`, and `user` for each comment.
Replies to an existing PR comment thread. This is useful for marking comments as resolved after addressing them in a local code review. Note that the `COMMENT_ID` must be the ID of the top-level comment in the thread.
The GitHub CLI `gh pr review` command does not natively support adding inline comments to specific lines of code via its standard flags. This script wraps the GitHub API to stage comments locally. They will not be published until you call `submit_pr_review.sh`.
# Rules for `Object.create(null)` and Prototype Collision Prevention
This guide outlines the technical rules and evaluation criteria for using `Object.create(null)` versus standard object literals (`{}`) or `Map` in the Angular codebase.
---
## 1. When `Object.create(null)` is Appropriate
Using `Object.create(null)` (or `Map`) is appropriate when **all** of the following conditions are met:
1. The object is used as an **internal key-value lookup map or set**.
2. The keys are **arbitrary or untrusted dynamic strings** (e.g., URL query parameters in `$locationShim`, HTML sanitizer tag sets, or `jsaction` DOM event-type resolvers).
3. Property existence is checked via direct indexing or key checks (e.g., `map[key] !== undefined` or `key in map`), where a key matching an `Object.prototype` member (such as `'toString'`, `'constructor'`, or `'hasOwnProperty'`) causes false positive matches or incorrect behavior.
---
## 2. Handling Public API and Boundary Objects
If an object receives untrusted dynamic keys **and** is exposed to public consumers or third-party code (e.g., `SimpleChanges` in `ngOnChanges`):
- **Do NOT blindly change the object to `Object.create(null)`**: Stripping `Object.prototype` from public objects is a breaking API change. Consumer code calling `.hasOwnProperty()`, `.toString()`, `.valueOf()`, or using string interpolation (`` `${obj}` ``) will fail at runtime (`TypeError: obj.hasOwnProperty is not a function`).
- **Safe Alternatives for Public Objects:**
- **`Object.hasOwn(obj, key)`**: Use `Object.hasOwn` for internal framework property lookups instead of direct index or `in` checks. This prevents prototype collision during internal reads without breaking the object's prototype for consumers.
- **Input Key Sanitization**: Filter or delete dangerous key names (`__proto__`, `constructor`, `prototype`) when populating the object.
- **`Map` or Custom Classes**: For new public APIs requiring key-value stores with dynamic keys, prefer `Map<K, V>` or dedicated classes with explicit `.get()` and `.has()` methods.
- **Deprecation / Breaking Change Process**: If changing a public object's prototype to `null` is unavoidable, it must follow Angular's formal deprecation and major version breaking change process.
---
## 3. When `Object.create(null)` Should NOT Be Used
Do not replace `{}` with `Object.create(null)` in the following scenarios:
1.**Fixed-Shape Structs and DTOs:** Objects with hardcoded static property names (e.g., `let sortedBreakpoints: {breakpoints?: number[]} = {}`). `Object.assign({}, ...)` only copies _own_ enumerable properties, so prototype properties on sources are never copied.
2.**Numeric-Key Maps:** Objects indexed by numbers (e.g., `tasksByHandleId: {[id: number]: Task}`). Numeric keys do not collide with `Object.prototype` string members.
3.**Reference Sentinels:** Objects used purely for reference identity checks (e.g., `const EMPTY_OBJECT = {}` or `const IN_PROGRESS_RESOLUTION = {}`).
4.**Internal Compiler AST and Visitor State:** Temporary objects with internally generated keys where untrusted user input cannot poison key names.
5.**Hot Performance Paths and Size-Critical Bundles:** Standard `{}` literals use V8 fast hidden classes and monomorphic inline caching. `Object.create(null)` forces V8 dictionary mode and increases minified bundle size (e.g., in inline polyfills like `event-dispatch-contract` or SSR hydration bundles).
When reviewing pull requests that modify the Angular Router (`packages/router`), pay special attention to the following:
- **Timing Sensitivity**: The router is extremely sensitive to timing changes. Any changes that alter the asynchronous timing of navigations, resolvers, or guards are almost always breaking changes and must be scrutinized carefully.
- **Testing Practices**: Tests should usually use the `RouterTestingHarness`. Many existing tests are older and do not use this harness. Do not blindly follow the shape of existing tests when writing or reviewing new ones; encourage the use of modern testing utilities.
- **Feature Justification**: Changes to router core code should be well-justified. Consider whether the change is proven to be a core developer ask, such as resolving a highly upvoted GitHub issue or addressing a critical bug.
description: Explains the mental model and architecture of the code under `packages/compiler-cli`. You MUST use this skill any time you plan to work with code in `packages/compiler-cli`
---
# Angular Compiler CLI (`ngtsc`) Architecture
## Overview
The `packages/compiler-cli` package contains the Angular Compiler (Ivy), often referred to as `ngtsc`. It is a wrapper around the TypeScript compiler (`tsc`) that extends it with Angular-specific capabilities.
The core goal of `ngtsc` is to compile Angular decorators (like `@Component`, `@Directive`, `@Pipe`) into static properties on the class (Ivy instructions, e.g., `static ɵcmp = ...`). It also performs template type checking and ahead-of-time (AOT) compilation.
## Mental Model
The compiler is designed as a **lazy, incremental, and partial** compilation pipeline.
1.**Wrapper Pattern**: `NgtscProgram` wraps the standard `ts.Program`. It intercepts calls to act as a drop-in replacement for standard tooling.
2.**Traits System**: Every class with an Angular decorator is considered a "Trait". The compiler manages the state of these traits through a state machine:
- **Resolved**: Dependencies (directives/pipes in template) resolved, import cycles handled.
- **Skipped**: Not an Angular class.
3.**Lazy Analysis**: Analysis only happens when necessary (e.g., when diagnostics are requested or emit is prepared).
4.**Output AST**: The compiler generates an intermediate "Output AST" (`o.Expression`) for the generated code, which is then translated into TypeScript AST nodes during the emit phase.
## Key Subsystems
### 1. Core Orchestration (`ngtsc/core`)
- **`NgtscProgram`**: The public API implementing `api.Program`. It manages the `ts.Program` and the `NgCompiler`.
- **`NgCompiler`**: The brain of the compiler. It orchestrates the compilation phases (Analysis, Resolution, Type Checking, Emit). It holds the `TraitCompiler`.
### 2. Trait Compilation (`ngtsc/transform`)
- **`TraitCompiler`**: Manages the lifecycle of "Traits". It iterates over source files, identifies decorated classes, and delegates to the appropriate `DecoratorHandler`.
- **`Trait`**: A state container for a class, holding its handler, analysis results, and resolution results.
### 3. Decorator Handlers (`ngtsc/annotations`)
- **`DecoratorHandler`**: An interface for handling specific decorators.
- **`ComponentDecoratorHandler`**: The most complex handler. It:
- Extracts metadata (selector, inputs, outputs).
- Parses the template.
- Resolves used directives and pipes (`R3TargetBinder`).
- Generates the `ɵcmp` instruction.
- **`DirectiveDecoratorHandler`**, **`PipeDecoratorHandler`**, **`NgModuleDecoratorHandler`**: Handle their respective decorators.
### 4. Template Type Checking (`ngtsc/typecheck`)
- **`TemplateTypeChecker`**: Generates "Type Check Blocks" (TCBs). A TCB is a block of TypeScript code that represents the template's logic in a way `tsc` can understand and check for errors.
- **`TypeCheckBlock`**: The actual generated code that validates bindings, events, and structural directives.
- **`MetadataReader`**: Reads Angular metadata from source files (using `LocalMetadataRegistry`) and `.d.ts` files (using `DtsMetadataReader`).
- **`ScopeRegistry`**: Determines the "compilation scope" of a component (which directives/pipes are available to it), handling `NgModule` transitive exports and Standalone Component imports.
### 6. Emit & Transformation (`ngtsc/transform`)
- **`ivyTransformFactory`**: A TypeScript transformer factory.
- **`IvyCompilationVisitor`**: Visits classes, triggers compilation via `TraitCompiler`, and collects the Output AST.
- **`IvyTransformationVisitor`**: Translates the Output AST into TypeScript AST, injects the `static ɵ...` fields, and removes the original decorators.
## Compilation Phases
1.**Construction**: `NgtscProgram` creates `NgCompiler`, which sets up all registries and the `TraitCompiler`.
2.**Analysis** (`analyzeSync`):
- The `TraitCompiler` scans files.
-`DecoratorHandler`s extract metadata and parse templates.
- No cross-file resolution happens here (allowing for parallelism and caching).
3.**Resolution** (`resolve`):
-`TraitCompiler` resolves traits.
- Components link their templates to specific Directives and Pipes (found via `ScopeRegistry`).
- Import cycles are detected and handled (e.g., via "remote scoping").
4.**Type Checking**:
-`TemplateTypeChecker` creates TCBs for all components.
- TypeScript diagnostics are retrieved for these TCBs.
5.**Emit** (`prepareEmit`):
-`ivyTransformFactory` is created.
- TS `emit` is called.
- The transformers run, injecting the compiled Ivy instructions into the JS/DTS output.
## Important File Locations
-`packages/compiler-cli/src/ngtsc/program.ts`: Entry point (`NgtscProgram`).
description: Explains the mental model and architecture of the code under `packages/core`. You MUST use this skill any time you plan to work with code in `packages/core`
---
# Angular Core (`packages/core`) Mental Model
This document outlines the architecture and mental model for `packages/core`, the heart of the Angular framework.
## 1. High-Level Architecture
`packages/core` contains the runtime logic for Angular. Its primary responsibilities are:
1.**Rendering (Ivy/Render3)**: Transforming templates into DOM updates.
2.**Dependency Injection (DI)**: Managing object creation and lifetime.
3.**Change Detection**: Synchronizing the model with the view.
4.**Reactivity**: Signals and Zone.js integration.
## 2. Rendering Engine (Ivy / Render3)
The rendering engine (located in `packages/core/src/render3`) uses an **instruction-based** approach.
### Key Concepts
- **Instructions**: The Angular compiler transforms templates into a sequence of instruction calls (e.g., `ɵɵelementStart`, `ɵɵtext`, `ɵɵproperty`). These instructions are executed at runtime to create and update the view.
- **TView (Template View)**: An array containing the _static structure_ of a view. It is shared across all instances (`LView`s) of the same component/template. It holds:
- Configured via `@Component.providers` or `@Directive.providers`.
- **Not a class**, but a data structure embedded in the `LView` ("Expando" section).
- Uses **Bloom Filters** (`TView.data`) to quickly check if a token is present at a specific node index before traversing up the tree.
- Resolves tokens starting from the current node, walking up the view tree (Element Injector hierarchy), and falling back to the Module Injector if not found.
## 4. Change Detection
- **Dirty Checking**: Angular checks if values bound in templates have changed.
- **Strategies**:
-`Default`: Checks everything.
-`OnPush`: Checks only if inputs change, events fire, or signals update.
- **Signals**: The new reactivity primitive. Signals notify the scheduler when they change, potentially allowing for fine-grained updates (Zoneless).
## 5. Key Directories to Know
-`src/render3`: The Ivy rendering engine.
-`instructions`: The runtime instructions called by compiled code.
-`src/signal`: Signals implementation (if present in this version, otherwise likely in `primitives`).
## 6. Conventions & Gotchas
- **Prefixes**: Private/Internal exports often start with `ɵ`.
- **Global State**: Ivy relies heavily on global state (e.g., `getLView()`) during instruction execution to avoid passing context arguments everywhere. This is for performance and code size.
- **Performance**: The code is highly optimized for performance and memory. You will see arrays used instead of objects, bitmasks, and manual memory management patterns. **Respect these patterns.**
## 7. How to Modify Core
1.**Understand the Instruction**: If modifying runtime behavior, find the corresponding instruction in `src/render3/instructions`.
2.**Check `LView`/`TView` Impact**: If adding state, understand where it fits in the `LView` array.
3.**Tests**: Core has extensive tests. Run them using Bazel.
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
---
# Signal Forms Architecture
The `packages/forms/signals` directory contains the signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.
## Mental Model
1.**Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).
2.**Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.
3.**Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
This separates the _structure_ of the data from the _rules_ governing it.
4.**Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
It handles:
- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).
## Key Components
### 1. `FieldNode` (`src/field/node.ts`)
The central internal class representing a single field in the form graph. It aggregates several state managers:
-`structure`: Manages parent/child relationships and signal slicing.
This document explains how the Signal Forms system hooks into the Angular compiler and runtime to provide seamless type-checking and efficient updates.
## 1. Compiler Integration (Type Checking)
The `packages/compiler` package contains specific logic to support `[formField]`. This is primarily handled in `src/typecheck/ops/signal_forms.ts`.
### Key Mechanisms:
- **Detection**: The compiler identifies a directive as a "Field Directive" if it has the `ɵNgFieldDirective` property or comes from `@angular/forms/signals`.
- **Synthetic Binding Expansion**: When you write `<input [formField]="mySignal" />`, the type checker doesn't just check `formField`. It synthetically expands this into a set of bindings for validation:
-`[value]="mySignal()"` (or `checked` for checkboxes)
-`[disabled]="mySignal.disabled()"`
-`[required]="mySignal.required()"`
- ...and so on.
- This ensures that `mySignal` (the `FieldNode`) has all the necessary properties to drive the form control.
- **Conflict Detection**: It actively prevents "double binding". If you bind `[formField]`, you are _banned_ from also binding `[value]`, `[disabled]`, `[required]`, etc., as the signal form should be the single source of truth.
- **Element Type Validation**:
- **Native Elements**: Checks that the signal's value type matches the element type (e.g., `<input type="checkbox">` requires a `boolean` signal).
- **Custom Controls**: Detects if a custom component is a "Form Value Control" (has a `value` input/output) or "Form Checkbox Control" (has a `checked` input/output) and validates against that.
### Relevant Files:
-`packages/compiler/src/typecheck/ops/signal_forms.ts`: The core Signal Forms type-checking logic, including `TcbNativeFieldOp`.
## 2. Core Runtime Integration
The `packages/core` package provides the low-level instructions that power the `FormField` directive. This allows it to do things normal directives cannot, like efficiently syncing state without change detection overhead for every property.
### Key Mechanisms:
- **`ɵngControlCreate` Hook**: The `FormField` directive defines a special method `ɵngControlCreate`, which causes the compiler to install `ɵɵControlFeature`.
- **`ɵɵcontrol` Instructions**: A `formField` binding causes the compiler to emit:
-`ɵɵcontrolCreate`: Called during the creation phase.
-`ɵɵcontrol`: Called during the update phase.
- **`ControlDirectiveHost`**: These instructions provide the directive with a `ControlDirectiveHost`. This is a privileged interface that allows the `FormField` directive to:
- **Access the Element**: Get direct access to the native element or component instance.
- **Set Inputs**: Write directly to inputs of _other directives_ on the same node (e.g., setting the `value` input of a custom control).
- **Listen to Outputs**: Subscribe to outputs of other directives (e.g., `valueChange`).
- **Bypass Templates**: It effectively acts as a "meta-directive" that manages the bindings for you, bypassing the need for explicit template syntax for every property.
### Relevant Files:
-`packages/core/src/render3/instructions/control.ts`: Implementation of `ɵɵcontrol` instructions.
-`packages/forms/signals/src/directive/form_field.ts`: The directive that implements the hook.
This folder contains configuration files that can be used to opt into working on this repository in a [Docker container](https://www.docker.com/resources/what-container) via [VSCode](https://code.visualstudio.com/)'s Remote Development feature (see below).
Info on remote development and developing inside a container with VSCode:
- [VSCode: Developing inside a Container](https://code.visualstudio.com/docs/remote/containers)
- [VSCode: Remote Development FAQ](https://code.visualstudio.com/docs/remote/faq)
## Usage
_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._
@@ -15,7 +15,6 @@ _Prerequisite: [Install Docker](https://docs.docker.com/install) on your local e
To get started, read and follow the instructions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](.) directory contains pre-configured `devcontainer.json` and `Dockerfile` files, which you can use to set up remote development with a docker container.
In a nutshell, you need to:
- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
- Copy [recommended-Dockerfile](./recommended-Dockerfile) to `Dockerfile` (and optionally tweak to suit your needs).
- Copy [recommended-devcontainer.json](./recommended-devcontainer.json) to `devcontainer.json` (and optionally tweak to suit your needs).
@@ -24,6 +23,7 @@ In a nutshell, you need to:
The `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile` files are ignored by git, so you can have your own local versions. We may occasionally update the template files ([recommended-devcontainer.json](./recommended-devcontainer.json), [recommended-Dockerfile](./recommended-Dockerfile)), in which case you will need to manually update your local copies (if desired).
## Updating `recommended-devcontainer.json` and `recommended-Dockerfile`
You can update and commit the recommended config files (which people use as basis for their local configs), if you find that something is broken, out-of-date or can be improved.
description="Researches part of the codebase and creates a skill for it"
prompt="""
## Role
You are an experienced senior developer specializing in reverse engineering and understanding
complex code, prompt engineering, and context engineering.
Your task is to build a complete understanding of the mental model and architecture of the code,
and to create an efficient context file that allows a coding agent to understand and work with the
code.
## Guiding Principles
1. **Deep Analysis:** Understand the _why_ behind the code. Not just a surface level listing of
files and classes.
2. **Curiosity:** Be curious. If something is unclear, confusing, or unexpected you _MUST_
investigate further until you fully understand.
3. **Efficient Token Use:** The final output will be directly included into the context of the
coding assistant, so be sure to make efficient use of tokens. Think deeply, but only capture the
most important information for the coding agent in the final output
## Procedure
1. Fully explore the code before first, with a focus on understanding the architecture and how all
of the pieces fit together.
2. Develop an understanding of the mental model behind the architecture. _Why_ is the code is
architected this way? How should developers think about the system?
3. Document your findings using the given output format described in the next section.
## Output Format
Note the following placeholders below:
- `[package]`: is a unique identifier for the current code package (for example if you're looking at
code under `packages/forms/signals` you might use `signal-forms` as the `[package]`)
- `[code-location]`: is the location of the current code within the larger repository
- `[context]`: is the context to add to the coding agent when it is working with this code.
With those placeholders in mind, write a file create a new directory under `.gemini/skills` with the
name `reference-[package]/`, and under that directory add a `SKILL.md` file with the following
content:
```md
---
name: reference-[package]
description: Explains the mental model and architecture of the code under `[code-location]`. You MUST use this skill any time you plan to work with code in `[code-location]`
---
[context]
```
## Additional User Instructions
The user may have additional instructions.
- The user should indicate what package to research
- The user may indicate that they want to update a package that has already been researched. In this
case, read the existing skill and make any required updates based on your research
- The user may request supplemental information be added to the skill (if so, add this to the
existing skill in a new markdown file under a `references` directory within the skill. Add a
section to the main `SKILL.md` that mentions what supplemental information is available)
'@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.',
},
},
{name:'@angular/common'},
{name:'@angular/compiler-cli'},
{name:'@angular/compiler'},
{name:'@angular/core'},
{name:'@angular/elements'},
{name:'@angular/forms'},
{name:'@angular/language-server'},
{name:'@angular/language-service'},
{name:'@angular/localize'},
{
name:'@angular/platform-browser-dynamic',
deprecated:{
version:'>=20.1.0-next.0',
message:
'@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.',
},
},
{name:'@angular/platform-browser'},
{name:'@angular/platform-server'},
{name:'@angular/router'},
{name:'@angular/service-worker'},
{name:'@angular/upgrade'},
],
buildPackages:async()=>{
// The buildTargetPackages function is loaded at runtime as the loading the script
@@ -14,20 +14,20 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:
- Use welcoming and inclusive language
- Respect each other
- Provide and gracefully accept constructive criticism
- Show empathy towards other community members
* Use welcoming and inclusive language
* Respect each other
* Provide and gracefully accept constructive criticism
* Show empathy towards other community members
Examples of unacceptable behavior by participants include:
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
- The use of sexualized language or imagery
- Unwelcome sexual attention or advances
- Other conduct which could reasonably be considered inappropriate in a
* The use of sexualized language or imagery
* Unwelcome sexual attention or advances
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
@@ -69,9 +69,9 @@ members of the project's leadership.
If you are banned you may contest the decision. To do so email conduct@angular.io with the subject line "Repeal Ban for {{your name here}}" and body with the responses to the following:
- Why do you believe you did not violate the Code of Conduct?
- Were other factors involved in this situation the leadership team may have been unaware of?
- Why do you wish to be a part of the Angular community?
* Why do you believe you did not violate the Code of Conduct?
* Were other factors involved in this situation the leadership team may have been unaware of?
* Why do you wish to be a part of the Angular community?
We would love for you to contribute to Angular and help make it even better than it is today!
As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
## <a name="coc"></a> Code of Conduct
Help us keep Angular open and inclusive.
Please read and follow our [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
@@ -32,25 +34,28 @@ To save your and our time, we will systematically close all issues that are requ
If you would like to chat about the question in real-time, you can reach out via [the Angular community Discord server][discord].
## <a name="issue"></a> Found a Bug?
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
You can _request_ a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
If you would like to _implement_ a new feature, please consider the size of the change in order to determine the right steps to proceed:
- For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
- **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker. An issue for your problem might already exist and the discussion might inform you of workarounds readily available.
@@ -69,67 +74,50 @@ Unfortunately, we are not able to investigate / fix bugs without a minimal repro
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
We strongly value open source contribution and pull requests from community contributors. Please note that every pull request is reviewed and merged by an actual person on the team, which does take time and effort. That is time and effort that does take away from other valuable work. With that in mind we have a minimum set of expectations that are required of any community contribution pull request that is opened.
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
- You don't want to duplicate existing efforts.
2. Be sure that an issue or pull request clearly describes the problem you're fixing, or documents the design for the feature you'd like to add. Issues require a _minimal_ reproduction.
3. Discussing the design in an issue upfront helps to ensure that we're ready to accept your work. Pull requests are not the right place to do design work.
- When in doubt, open an issue first before doing any sort of speculative implementation work
4. Ideally the PR should be tied to an issue, but this is not required
5. The change should improve code quality (i.e. addressing a TODO) or should impact / improve a feature
6. Micro optimizations will only be accepted if they are validated by an actual benchmark
7. Do not open pull requests that are addressing feature requests that are not labeled as "help wanted" as they usually need additional design work before we could accept pull requests
8. The change should be well tested
If your pull request does not meet these minimum expectations, we may close your PR. Also, if your PR introduces a breaking change, it's possible the level of churn this breaking change causes may block our ability to move forward with it. We may close your PR in that situation, as well. Otherwise, we're excited to see your contributions and enthusiasm for Angular!
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
1.Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
1.Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
You don't want to duplicate existing efforts.
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
Discussing the design upfront helps to ensure that we're ready to accept your work.
Make sure you author all contributed Git commits with email address associated with your CLA signature.
2. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the [angular/angular](https://github.com/angular/angular/fork) repo.
4. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the [angular/angular](https://github.com/angular/angular/fork) repo.
3. In your forked repository, make your changes in a new git branch:
5. In your forked repository, make your changes in a new git branch:
```shell
git checkout -b my-fix-branch main
```
```shell
git checkout -b my-fix-branch main
```
4. Create your patch, **including appropriate test cases**.
6. Create your patch, **including appropriate test cases**.
5. Follow our [Coding Rules](#rules).
7. Follow our [Coding Rules](#rules).
6. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
7. Commit your changes using a descriptive commit message that follows our [commit message conventions][commit-message-guidelines].
9. Commit your changes using a descriptive commit message that follows our [commit message conventions][commit-message-guidelines].
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
```shell
git commit --all
```
```shell
git commit --all
```
Note: the optional commit `--all` command line option will automatically "add" and "rm" edited files.
Note: the optional commit `--all` command line option will automatically "add" and "rm" edited files.
10. Push your branch to GitHub:
8. Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
```shell
git push origin my-fix-branch
```
9. In GitHub, send a pull request to `angular:main`.
11. In GitHub, send a pull request to `angular:main`.
### Reviewing a Pull Request
@@ -145,15 +133,16 @@ If we ask for changes via code reviews then:
3. Create a fixup commit and push to your GitHub repository (this will update your Pull Request):
```shell
git commit --all --fixup HEAD
git push
```
```shell
git commit --all --fixup HEAD
git push
```
For more info on working with fixup commits see [here](./contributing-docs/using-fixup-commits.md).
For more info on working with fixup commits see [here](./contributing-docs/using-fixup-commits.md).
That's it! Thank you for your contribution!
##### Updating the commit message
A reviewer might often suggest changes to a commit message (for example, to add more context for a change or adhere to our [commit message guidelines][commit-message-guidelines]).
@@ -161,68 +150,69 @@ In order to update the commit message of the last commit on your branch:
1. Check out your branch:
```shell
git checkout my-fix-branch
```
```shell
git checkout my-fix-branch
```
2. Amend the last commit and modify the commit message:
```shell
git commit --amend
```
```shell
git commit --amend
```
3. Push to your GitHub repository:
```shell
git push --force-with-lease
```
```shell
git push --force-with-lease
```
> NOTE:<br />
> If you need to update the commit message of an earlier commit, you can use `git rebase` in interactive mode.
> See the [git docs](https://git-scm.com/docs/git-rebase#_interactive_mode) for more details.
#### After your pull request is merged
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
- Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
```shell
git push origin --delete my-fix-branch
```
```shell
git push origin --delete my-fix-branch
```
- Check out the main branch:
* Check out the main branch:
```shell
git checkout main -f
```
```shell
git checkout main -f
```
- Delete the local branch:
* Delete the local branch:
```shell
git branch -D my-fix-branch
```
```shell
git branch -D my-fix-branch
```
- Update your local `main` with the latest upstream version:
* Update your local `main` with the latest upstream version:
```shell
git pull --ff upstream main
```
```shell
git pull --ff upstream main
```
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
- All features or bug fixes **must be tested** by one or more specs (unit-tests).
- All public API methods **must be documented**.
- We follow [Google's TypeScript Style Guide][ts-style-guide], but wrap all code at **100 characters**.
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
* All public API methods **must be documented**.
* We follow [Google's TypeScript Style Guide][ts-style-guide], but wrap all code at **100 characters**.
An automated formatter is available, see [DEVELOPER.md](contributing-docs/building-and-testing-angular.md#formatting-your-source-code).
An automated formatter is available, see [building-and-testing-angular.md](./contributing-docs/building-and-testing-angular.md#formatting-your-source-code).
We have very precise rules over how our Git commit messages must be formatted:
```
<type>(<scope>): <short summary>
```
@@ -234,18 +224,21 @@ See [Commit Message Guidelines][commit-message-guidelines] for details.
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
- For individuals, we have a [simple click-through form][individual-cla].
- For corporations, we'll need you to
* For individuals, we have a [simple click-through form][individual-cla].
* For corporations, we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
If you have more than one GitHub account, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.