This change aligns the stability of `ComponentFixture` with that of
`ApplicationRef`, preventing confusing differences between the two as
more APIs start using the `PendingTasks` that may not be tracked by
`NgZone`.
BREAKING CHANGE: `ComponentFixture.whenStable` now matches the
`ApplicationRef.isStable` observable. Prior to this change, stability
of the fixture did not include everything that was considered in
`ApplicationRef`. `whenStable` of the fixture will now include unfinished
router navigations and unfinished `HttpClient` requests. This will cause
tests that `await` the `whenStable` promise to time out when there are
incomplete requests. To fix this, remove the `whenStable`,
instead wait for another condition, or ensure `HttpTestingController`
mocks responses for all requests. Try adding `HttpTestingController.verify()`
before your `await fixture.whenStable` to identify the open requests.
Also, make sure your tests wait for the stability promise. We found many
examples of tests that did not, meaning the expectations did not execute
within the test body.
In addition, `ComponentFixture.isStable` would synchronously switch to
true in some scenarios but will now always be asynchronous.
PR Close#54949
This commit will fix the issue of the setting of NavigationExtras.replaceUrl being lost when
returning a urlTree from a CanActivateFn.
Fixes#53503
BREAKING CHANGE: When a a guard returns a `UrlTree` as a redirect, the
redirecting navigation will now use `replaceUrl` if the initial
navigation was also using the `replaceUrl` option. If this is not
desirable, the redirect can configure new `NavigationBehaviorOptions` by
returning a `RedirectCommand` with the desired options instead of `UrlTree`.
PR Close#54042
Previously, `RouterLinkActive` would only add or remove the active classes when
its active state changed. This means that if you accidentally add one of
the active classes to the static class attribute, it won't get removed
until the link becomes active and then deactives (because the class is
added at creation time and never removed until the `RouterLinkActive`
state changes from active to inactive).
fixes#54978
PR Close#54982
The custom flatMap implementation can now be removed as Array contains a
native implementation that is available for all supported Node.js versions.
PR Close#55011
When the `angularOnly` option is disabled, the underlying TypeScript language service
was previously used for all files including `.html` template files. This can result in
incorrect responses including a large amount of invalid diagnostics for a template file.
Checks have now been added to only use the Angular Language service for template files
which can properly handle template files. Additionally, the check for a TypeScript file
name has now been expanded to encompass all current file extension forms.
PR Close#55003
For `FatalDiagnosticError` we are currently hiding the `message` string
field in favor of the actual TS `diagnosticMessage`.
This works as expected, but makes these errors hard to debug in certain
environments (e.g. Jasmine). That is because `null` is the value of
`message` at runtime. We fix this by just overriding the type, like we
originally intended to do.
In addition, we properly render message chains in the `Error#message`
field— so that these errors, when uncaught, are somewhat reasonable and
can be useful.
PR Close#54981
This commit ensures that the new APIs like `input`, `model`, `output`,
or signal-based queries are not accidentally used on fields that have a
problematic visibility/access level that won't work.
For example, queries defined using a private identifier (e.g. `#bla`)
will not be accessible by the Angular runtime and therefore _dont_ work.
This commit ensures:
- `input` is only declared via public and protected fields.
- `output` is only declared via public and protected fields.
- `model` is only declared via public and protected fields.
- signal queries are only declared via public, protected and TS private
fields (`private` works, while `#bla` does not).
Fixes#54863.
PR Close#54981
An initializer API like `input`, `output`, or signal queries may not be
compatible with certain access levels. E.g. queries cannot work with ES
private class fields.
This commit introduces a check for access levels into the initializer
API recognition— enforcing that every initializer API *clearly*
specifies what type of access is allowed.
PR Close#54981
This commit changes the TypeScript reflection host to:
* inspect / process ES private fields. e.g. `#someField` — those are
ignored right now and we would want to check them to issue
diagnostics.
* determine an access level of a class member. E.g. a member may be
public, may be private, may be ES private, or public readonly. This
can then be used in various checks later.
PR Close#54981
Updates the function that parses initializer APIs to check any `Expression`, instead of expecting a class member. This will be useful for the upcoming changes.
PR Close#54981
This commit fixes various issues that seem to cause the 17.3.x patch
to be red for weeks:
- Eslint checking a file for aio/tools that is not part of a tsconfig—
hence an error is being reported.
- Audit-web-app importing some Lighthouse APIs that aren't available
under the given path.
PR Close#55064
Previously, a race condition could cause DevTools to enter a state where it can't detect an application on reload. This was caused by a sequencing issue between the content script connection, the devtools panel connection and an event "backendReady" that lets DevTools know when a particular frame is ready to be inspected.
This commit replaces the previously stored backendReady boolean with a promise, so that the devtools panel can eventually run a callback to connect to a content script when that content script emits it's backendReady message.
PR Close#54805
Passes the attributes of the `ng-content` element to the container that is created for the fallback content so that it can be re-projected into the same slot.
PR Close#54854
Moves the logic that declares a template out into a separate function so that it can be reused in other places like control flow and defer, without having to call directly into the `template` instruction.
PR Close#54854
Adds the ability to specify content that Angular should fall back to if nothing is projected into an `ng-content` slot. For example, if we have the following setup
```
@Component({
selector: 'my-comp',
template: `
<ng-content select="header">Default header</ng-content>
<ng-content select="footer">Default footer</ng-content>
`
})
class MyComp {}
@Component({
template: `
<my-comp>
<footer>New footer</footer>
</my-comp>
`
})
class MyApp {}
```
The instance of `my-comp` in the app will have the default header and the new footer.
**Note:** Angular's content projection happens during creation time. This means that dynamically changing the contents of the slot will not cause the default content to show up, e.g. if a `if` block goes from `true` to `false`.
Fixes#12530.
PR Close#54854
Adds logic to ingest the content of an `ng-content` element in the template type checker. We treat `ng-content` as a `ScopedNode`, because its content is inserted conditionally.
PR Close#54854
This commit adds support for ignoring specific doc entries when
extracting doc entries. This allows us to drop e.g. `InputFunction` from
the API docs, given that the `input` API entry holds all the relevant
information.
`InputFunction` only exists for type purposes in the `.d.ts`.
PR Close#54925
Similar to `input`, `model`, `output`, the query initializer APIs are
also explicitly denoted as such. This allows angular.dev to display them
more readable and compactly.
PR Close#54925
This improves the API documentatino for `output` in angular.dev,
similar to how we improved the API for `input`.
Angular.dev can now show these documentation entries more
readable if annotated explicitly as initializer API.
Note: output API is short enough that we want to include
the types in the code snippet previews.
PR Close#54925
This commit improves the API documentation for `input` after
we added support for initializer APIs in angular.dev docs generation.
Changes:
- Rename `ReadT` to `T`. This conceptually makes it easy to talk about
inputs of type `T` if there is no transform involved. The common case.
- Rename `WriteT` to `TransformT`. This makes it clear that this is the
type that the "transform" needs to handle.
- Improves the "overall" description of the input function so that it
can be shown as a general overview for the API site.
- Improves usage notes to be a little more helpful, yielding more useful
content in the API docs usage notes section.
- Add short JSDoc description for each individual overload.
PR Close#54925
This commit adds support for extracting initializer API functions.
Initialixer API functions are functions conceptually that can are
intended to be used as class member initializers.
Angular started introducing a few of these for the new signal
APIs, like `input`, `model` or signal-based queries.
These APIs are currently confusingly represented in the API docs because
the API extraction:
- does not properly account for call signatures of interfaces
- does not expose information about sub-property objects and call
signatures (e.g. `input.required`)
- the docs rendering syntax highlighting is too bloated and confusing
with all types being included.
This commit adds support for initializer API functions, namely two
variants:
- interface-based initializer APIs. e.g. `export const input:
InputFunction`- which is a pattern for `input` and `input.required`.
- function-based simpler initializer APIs with overloads. e.g.
`contentChildren` has many signatures but doesn't need to be an
interface as there are no sub-property call signatures.
PR Close#54925
When creating the Angular Language Service instance, attempts to read
configuration files are now only attempted if the project is considered
a `Configured` project. Such a project has been analyzed by TypeScript
and one or more configuration files (tsconfig/jsconfig) files have been
found for the project.
PR Close#55035
Based on some internal feedback, these changes add validations to prevent cases where the `@for` loop variable name is the same as one of the built-in context variables, or when one of the context variables is aliased to the same name as the item.
PR Close#55045
This update enhances the encoding handling of request bodies to generate the necessary cache key for transfer cache functionality.
Closes#54956
PR Close#54980
Builds on top of the previous changes to add support for deferred blocks during partial compilation. To do this, the following changes had to be made:
* The metadata passed into `ɵɵngDeclareComponent` has an additional field called `deferBlockDependencies` which has an array of the dependency loading functions for each defer block in the template. During linking, the dependency functions are loaded by matching their template index to the index in the `deferBlockDependencies` array.
* There's a new `ɵɵngDeclareClassMetadataAsync` function that is created for components that have deferred dependencies. It gets transpiled to `setClassMetadataAsync` and works in the same way by capturing a dependency loading function and setting the metadata after the dependencies are resolved. It also has some extra fields for capturing the version which are standard in linker-generated code.
* Deferred import statements are now stripped in partial compilation mode, similar to full compilation.
PR Close#54908
Adds the `ɵɵngDeclareClassMetadataAsync` function that will be produced during partial compilation for component classes that have deferred dependencies. At runtime the dependencies will be resolved before setting the metadata.
PR Close#54908
Updates the type of the resolver function to be any `Expression` since JIT may receive a function reference rather than a `ArrowFunctionExpr`.
PR Close#54908
Switches to tracking the deferred blocks in a flat array in the binder to ensure that their template order is maintained. This will be relevant in the next commits where we'll match deferred blocks by their index.
Note that the current map we have technically guarantees the insertion order in the spec, but the array is a bit more explicit.
PR Close#54908
Updates the logic that detects if a node should be checked for control flow content projection to exit as soon as it detects a second root node, instead of counting the total and then checking if it's more than one.
PR Close#54921
Previously only the first branch of an `if` block was captured for content projection. This was done because of some planned refactors in the future. Since we've decided not to apply those refactors to conditionals, these changes update the compiler to capture each branch individually for content projection purposes.
PR Close#54921
This commit changes the way we use containers to insert conditional content.
Previously if and switch conditional would always use the first content as the
insertion container. This strategy interfered with content projection that
projects entire containers - as the consequence content for _all_ cases would
end up in slot matched by the first container. This could be very surprising
as desicribed in https://github.com/angular/angular/issues/54840
After the change each conditional content is projected into its own container.
This means that content projection can match more than one container and
result in correct display.
Fixes#54840
PR Close#54921
Currently when aliasing a `for` loop variable with `let`, we replace the variable's old name with the new one. Since users have found this to be confusing, these changes switch to a model where the variable is available both under the original name and the new one.
Fixes#52528.
PR Close#54942
Since the PR is always expected to be ready to merge as renovate won't make changes in response to any sort of comment, it should already be marked as merge ready
PR Close#54947
Previously we assumed that if a `for` loop tracking function is in the form of `someMethod($index, $item)`, it will be pure so we didn't pass the parameter to bind the context to it. This appears to be risky, because we don't know if the method is trying to access `this`.
These changes play it safe by always binding method-based tracking functions.
Fixes#53628.
PR Close#54960
This commit adds `declare` to each interface in the `zone-impl` to
prevent renaming of any interface properties by compiler optimizations.
This would otherwise cause issues if multiple applications depend on ZoneJS and
compile the interface properties to different names.
PR Close#54966
This commit refactors the router module to enhance performance by substituting the startsWith method with direct access `[0]` when verifying the value of a single character. This optimization improves efficiency, as direct access retrieves the character's value stored at a specific index in the string, resulting in slightly faster execution.
PR Close#54940
This change updates the approach to the loop in `ApplicationRef.tick`
for allowing state updates in `afterRender` hooks. It is valid to update
state in render hooks and we need to ensure we refresh views that may be
marked for check in these hooks (this can happen simply as a result of
focusing an element). This change ensures that the behavior of `markForCheck`
with respect to this loop does not change while we are actively running
change detection on a view tree.
This approach also has the benefit of preventing a regression for #18917,
where updating state in animation listeners can cause `ExpressionChanged...Error`
This should be allowed - there is nothing wrong with respect to unidirectional
data flow in this case.
There may be other cases in the future where it is valid to update
state. Rather than wrapping the render hooks and the animation flushing
in something which flips a global state flag, the idea here is that
`markForCheck` is safe and valid in all cases whenever change detection
is not actively running.
PR Close#54900
In some cases the hydration mismatch is nested within a component.
As the devTool only reports issues on the component level, we need to mark the component node rather than the actual mismatched node.
PR Close#54671
This commit updates the name of an internal function argument that represents an embedded view injector. Also it introduces a new config option that allows passing an environment injector to be used in the underlying LView. There are no changes to the behavior, just some initial cleanup for upcoming changes.
PR Close#54903
BREAKING CHANGE:
Legacy handling or Node.js URL parsing has been removed from `ServerPlatformLocation`.
The main differences are;
- `pathname` is always suffixed with a `/`.
- `port` is empty when `http:` protocol and port in url is `80`
- `port` is empty when `https:` protocol and port in url is `443`
PR Close#54874
BREAKING CHANGE: deprecated `platformDynamicServer` has been removed. Add an `import @angular/compiler` and replace the usage with `platformServer`
PR Close#54874
I initially tried switching to use public entry points under `zone.js/plugins/*`, however this file is both manually compiled for Saucelabs and also built with Bazel for a number of tests. The Bazel integration doesn't work well with depending on real NPM packages, so importing `zone.js/plugins/*` in that context doesn't really work. Instead we need to depend on the internals and manually call the `patch*` functions.
PR Close#53443
This was a bit complicated, but the typings test (`packages/zone.js/test/typings/...`) was failing due to an unresolved import on `./zone-impl`.
The main cause is that `//packages/zone.js:zone_js_d_ts` was generating the output `zone.d.ts` file by _concatenating_ `zone.d.ts` with `zone.api.extensions.d.ts` and `zone.configurations.api.d.ts`. Now that `zone.d.ts` imports `zone-impl.d.ts`, concatenation is no longer a viable means of bundling this content.
To fix this, I created a new `packages/zone.js/zone.ts` entry point and imported the underlying `zone.ts` file as well as the two extensions. I added `extract_types` to pull the `*.d.ts` files out of the target (because all the JS is bundled separately) and used those files in the final NPM package. This is sufficient to pass the typings test and should be equivalent to what exists today.
PR Close#53443
The `rxjs|electron` regex was causing `import { /* ... */ } from './electron';` to be treated as external and not bundled, which is an issue for the Electron entry point which just happens to be named `electron.ts`. Now only the actual `electron` package should be treated as external, while internal files of any name should not.
I actually tried updating to `^rxjs` as well, however this appears to break some tests and isn't necessary to fix the failing Electron test, so I'm leaving it alone.
PR Close#53443
Not sure why this becomes a problem now. These errors appear to be preexisting. Most likely the file wasn't loaded previously and now it is.
PR Close#53443
As this was, `__symbol__` was being called as a static field initializer, which runs during module evaluation, meaning it happened at import time. However for tests, the Zone prefix is overridden which changes the result of `__symbol__`. This change happens too late to be picked up by `__symbol__` at top-level execution, so instead we defer it until `symbolParentUnresolved` is actually read.
PR Close#53443
This moves timer patching from a top-level side effect into the `patchFakeAsyncTest` function. Top-level statements are evaluated before the Node patches run and have a chance to patch them with the Zone versions of these timers, meaning `FakeAsyncTestZoneSpec` was repatching the native versions between tests. The fix here is to grab the patched versions of these timers during the `patchFakeAsyncTest` function where we can be confident Node patches have already run.
PR Close#53443
This moves the internals of `fake-async-test.ts` outside `patchFakeAsyncTest` and exports them. This way they can be imported without depending on the top-level side effects of loading Zone.
PR Close#53443
For some reason the `_global` name appears to conflict with another `_global` name. Not entirely sure how or why, but the easiest fix seems to be to just give the variable a unique name.
PR Close#53443
While reading this is not a top-level side effect, it does _depend_ on a top-level side effect. Specifically, `node-env-setup.ts` set this value. Now that its side effect is moved into a function, we can't read it as the top-level of `zone-impl.ts` and need to wait until `__symbol__` is actually called outside of top-level scope.
PR Close#53443
While `TaskTrackingZoneSpec` was implicitly global previously, it does not need to be exposed in a `declare global {}` block. This is because classic scripts in TypeScript are only implicitly global within the same compilation. `TaskTrackingZoneSpec` was not exposed in the existing `.d.ts` files shipped with the `zone.js` package. Within google3, this is also a separate compilation and was not accessible. As a result, `TaskTrackingZoneSpec` was always private and we do not need a global to maintain compatibility.
PR Close#53443
While `ProxyZoneSpec` was implicitly global previously, it does not need to be exposed in a `declare global {}` block. This is because classic scripts in TypeScript are only implicitly global within the same compilation. `ProxyZoneSpec` was not exposed in the existing `.d.ts` files shipped with the `zone.js` package. Within google3, this is also a separate compilation and was not accessible. As a result, `ProxyZoneSpec` was always private and we do not need a global to maintain compatibility.
PR Close#53443
Since each patch no longer contains top-level side effects, each bundled entry point needs to import and call its associated patch. For the most part this just means that each entry point imports the associated patch and invokes it at the top-level scope.
Note that many of these entry points did not actually have a dependency on `Zone` and had no guarantee that it was loaded prior to execution. To maintain consistency, the missing dependencies on `Zone` are left as-is. They will use the global instance of `Zone` and if users fail to load it prior to importing a specific patch, then the patch will fail just as it did previously.
PR Close#53443
This drop the top-level side effects in `zone.ts` and allows the initialization to be reused across the various entry points in the package.
PR Close#53443
This particular is slightly different from the others because it does not have a hard dependency on `Zone`. It doesn't actually use `Zone` directly during the patch because the patch just sets a `legacyPatch` global. To maintain consistency, this continues to use global `Zone` and does _not_ accept `Zone` as a parameter. While it's using a global in an inconvenient way, this isn't a problem right now because it doesn't cause or require a dependency on a top-level side effect.
PR Close#53443
This removes top-level side effects from each of these files and drops the dependency on global `Zone`, instead allowing it to be provided to each patch as a parameter.
Most of these are pure mechanical transformations. A couple notable files which were somewhat unique:
* `async-test.ts`, `fake-async-test.ts`, and `wtf.ts` had unique IIFE usage and patch `Zone` itself. This removes the IIFE and exports the function instead.
* `jest.ts` and `jasmine.ts` have a unique `jest` global usage which needs to be declared.
PR Close#53443
These are all the symbols originally under `declare global {}` with the same names. Unfortunatley TypeScript treats a `declare global {}` scope as the parent scope, so we need to import with a different name than the global, meaning everything gets an `_` prefix.
PR Close#53443
This removes a name collision on `Zone` with the interface. Otherwise putting the `interface Zone {}` and `class Zone {}` in the same scope when the IIFE is removed will cause a conflict.
PR Close#53443
This drops global declarations from this file (as they will be limited to `zone.ts`. It also deletes the `/** @internal */` annotation on `AmbientZone` which is no longer necessary since it isn't in the `declare global` and deletes the global Zone declaration which is also unnecessary.
PR Close#53443
This is just a straight copy, no code is altered. The new `zone-impl.ts` file will contain the actual definitions exported directly without any global declarations or top-level side effects. The existing `zone.ts` will remain as an entry point with those globals and side-effects.
PR Close#53443
We are already testing the JIT transforms via integration tests, but
this commit adds dedicated unit tests for the transform behavior for
proper test coverage (planned follow-up).
PR Close#54841
Move the initialization of class field `DelegatingPerfRecorder` into the constructor.
This fixes the error : `TypeError: Cannot read properties of undefined (reading 'eventCount')`
This is blocking the roll-out of public class.
PR Close#54834
This commit updates the logic for preserving file overview comments
to be more reliable and less dependent on previous transforms.
Previously, with the old import manager, we had a utility called
`addImport` that always separated import statements and non-import
statements. This meant that the non-emitted statement from Tsickle
for the synthetic file-overview comments no longer lived at the
beginning of the file.
`addImports` tried to overcome this by adding another new non-emitted
statement *before* all imports. This then was later used by the
transform (or was assumed!) to attach the synthetic file overview
comments if the original tsickle AST Node is no longer at the top.
This logic can be improved, because the import manager shouldn't need to
bother about this fileoverview non-emitted statement, and the logic for
re-attaching the fileoverview comment should be local. This commit fixes
this and makes it a local transform.
PR Close#54819
This commit adds some unit tests verifying the import generation in TCB
files and inline blocks. We don't seem to have any unit tests for these
in general. This commit adds some, verifying some characteristics we
would like to guarantee.
PR Close#54819
To ease review and to allow for both instances to co-exist, `ImportManagerV2`
was introduced. This commit renames it to `ImportManager` now that we
deleted the older one.
PR Close#54819
Enables the incremental type-checking test that we never enabled when we
landed signal inputs. Now that we fixed incremental re-use by re-using
the existing user imports for inline type check blocks, the test is
passing and can be enabled.
PR Close#54819
Updates the type-check block generation code (also for inline type check
blocks) to use the new import manager.
This is now a requirement because the translator utilities from the
reference emit environment expect an import manager that follows the
new contract established via `ImportGenerator<TFile, TExpression>`.
For type check files, we can simply print new imports as we don't expect
existing imports to be updated. That is because type check files do not
have any _original_ source files (or in practice— those are empty).
For type check blocks inline, or constructors, imports _may_ be re-used.
This is great as it helps fixing some incrementality bugs that we were
seeing in the type check code. That is, sometimes the type check block
code may generate imports conditionally for e.g. `TemplateRef`, or
animations. Those then **prevent** incremental re-use if TCB code
switches between those continously. We tried to account for that with
signal inputs by always pre-generating such imports. This fixed the
issue for type-check files, but for inline type check blocks this is
different as we would introduce new imports in user code that would then
be changed back in subsequential edit iterations. See:
https://github.com/angular/angular/pull/53521#pullrequestreview-1778130879.
In practice, the assumption was that we would be fine since user code is
most likely containing imports to `@angular/core` already. That is a
true assumption, but unfortunately it doesn't help with incremental
re-use because TypeScript's structural change detection does not dedupe
and expects 1:1 exact imports from their old source files.
https://github.com/microsoft/TypeScript/pull/56845
To improve incremental re-use for the type check integration, we should
re-use original source file imports when possible. This commit enables
this.
To update imports and execute inline operations, we are now uisng
`magic-string` (which is then bundled) as it simplifies the string
manipulatuons.
PR Close#54819
This commit switches ngtsc's JS and DTS transform to use the new import
manager. This is a drop-in replacement as we've updated the translator
helpers in the previous commit to align with the new API suggested by
the `ImportManagerV2` (to be renamed then).
PR Close#54819
`ImportGenerator` is the abstraction used by the translator functions to
insert imports for `ExternalExpr` in an AST-agnostic way.
This was built specifically for the linker which does not use any of the
complex import managers- but rather re-uses `ngImport` or uses
`ngImport.Bla`.
This commit also switches the linker AST-agnostic generator to follow
the new signatures. This was rather trivial.
PR Close#54819
This commit introduces a new implementation of `ImportManager` that has
numerous benefits:
- It allows efficient re-use of original source file imports.
* either fully re-using original imports if matching
* updating existing import declarations to include new symbols.
- It allows efficient re-use of previous generated imports.
- The manager can be used for schematics and migrations.
The implementation is a rework of the import manager that we originally
built for schematics in Angular Material, but this commit improved it
to be more flexible, more readable, and "correct".
In follow-ups we can use this for schematics/migrations.
PR Close#54819
This commit ensures components in the route config predictably always
get their providers from the hierarchy available to routes rather than
sometimes being dependent on where they are inserted.
fixes#53369
BREAKING CHANGE: Providers available to the routed components always
come from the injector heirarchy of the routes and never inherit from
the `RouterOutlet`. This means that providers available only to the
component that defines the `RouterOutlet` will no longer be available to
route components in any circumstances. This was already the case
whenever routes defined providers, either through lazy loading an
`NgModule` or through explicit `providers` on the route config.
PR Close#54265
This commit updates the logic around `Route.redirectTo` to enable using a
function to create the redirect. This function can return a string,
ands acts the same as previous string redirects, or a `UrlTree`, which
will act as an absolute redirect.
To be useful, the redirect function needs access to the params and data.
Today, developers can access these in their redirect strings, for
example `{path: ':id', redirectTo: '/user/:id'}`. Unfortunately,
developers only have access to params and data on the _current route_
today in the redirect strings. The params and data in the `RedirectFn`
give developers access to anything from the matched parent routes as
well. This is done as the same way as param and data aggregation later
on (https://github.com/angular/angular/blob/897f014785578d87bc655ea6ae9e113653960f50/packages/router/src/router_state.ts#L236-L278).
In order to accomplish this, we inherit params and data while
matching, after the `ActivatedRouteSnapshot` is created for the matched
route rather than waiting until the end.
The `RedirectFunction` does not return the full
`ActivatedRouteSnapshot` interface. Some things are not accurately known
at the route matching phase. For example, resolvers are not run until
later, so any resolved title would not be populated. The same goes for lazy
loaded components. The is also true for all the snapshots up to the
root, so properties that include parents (root, parent, pathFromRoot)
are also excluded. And naturally, the full route matching hasn't yet
happened so firstChild and children are not available either.
fixes#13373resolves#28661 (though not for the redirect string - you would return a
`UrlTree` from the function)
BREAKING CHANGE: This change allows `Route.redirectTo` to be a function
in addition to the previous string. Code which expects `redirectTo` to
only be a string on `Route` objects will need to be adjusted.
PR Close#52606
This commit updates the loop in ApplicationRef.tick to only throw in dev
mode. In addition, it reduces the reruns to 10 from 100 in order to
reduce the impact on production applications that encounter this error.
That is, the loop will bail out much earlier and prevent prolonged
unresponsiveness.
PR Close#54848
Zone event and run coalescing now races `requestAnimationFrame` and
`setTimeout`. There are tradeoffs to both functions and racing the two
gives us the benefits of both. This is explained in more detail in the
jsdoc comment. This change also aligns the timing of zone coalescing
with what will be used for zoneless.
BREAKING CHANGE: The exact timing of change detection execution when
using event or run coalescing with `NgZone` is now the first of either
`setTimeout` or `requestAnimationFrame`. Code which relies on this
timing (usually by accident) will need to be adjusted. If a callback
needs to execute after change detection, we recommend `afterNextRender`
instead of something like `setTimeout`.
fixes#54544fixes#44314fixes#39854 (unverified but seems likely)
PR Close#54578
This is a follow-up to #53718 that applies the same logic to the
`autoDetect` feature of the fixture's host view. This now unifies the
logic between `ApplicationRef` and `ComponentFixture` autodetect.
BREAKING CHANGE: The `ComponentFixture` `autoDetect` feature will no
longer refresh the component's host view when the component is `OnPush`
and not marked dirty. This exposes existing issues in components which
claim to be `OnPush` but do not correctly call `markForCheck` when they
need to be refreshed. If this change causes test failures, the easiest
fix is to change the component to `ChangeDetectionStrategy.Default`.
PR Close#54824
The logic in `isCssClassMatching` is only interested in two areas in the attributes:
implicit attributes and the `AttributeMarker.Classes` area, with the first area only
of interest for projection matching, not directive matching. This commit splits these
two searches to make this more apparent.
PR Close#54800
This commit resolves a regression that was introduced when the compiler switched from
`TemplateDefinitionBuilder` (TDB) to the template pipeline (TP) compiler. The TP compiler
has changed the output of
```html
if (false) { <div class="test"></div> }
```
from
```ts
defineComponent({
consts: [['class', 'test'], [AttributeMarker.Classes, 'test']],
template: function(rf) {
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 2, 0, "div", 0)
}
}
});
```
to
```ts
defineComponent({
consts: [[AttributeMarker.Classes, 'test']],
template: function(rf) {
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 2, 0, "div", 0)
}
}
});
```
The last argument to the `ɵɵtemplate` instruction (0 in both compilation outputs) corresponds with
the index in `consts` of the element's attribute's, and we observe how TP has allocated only a single
attribute array for the `div`, where there used to be two `consts` entries with TDB. Consequently,
the `ɵɵtemplate` instruction is now effectively referencing a different attributes array, where the
distinction between the `"class"` attribute vs. the `AttributeMarker.Classes` distinction affects
the behavior: TP's emit causes the runtime to incorrectly match a directive with `selector: '.foo'` to
be instantiated on the `ɵɵtemplate` instruction as if it corresponds with a structural directive!
Instead of changing TP to align with TDB's emit, this commit updates the runtime instead. This uncovered
an inconsistency in selector matching for class names, where there used to be two paths dealing with
class matching:
1. The first check was commented to be a special-case for class matching, implemented in `isCssClassMatching`.
2. The second path was part of the main selector matching algorithm, where `findAttrIndexInNode` was being used
to find the start position in `tNode.attrs` to match the selector's value against.
The second path only considers `AttributeMarker.Classes` values if matching for content projection, OR of the
`TNode` is not an inline template. The special-case in path 1 however does not make that distinction, so it
would consider the `AttributeMarker.Classes` binding as a selector match, incorrectly causing a directive to
match on the `ɵɵtemplate` itself.
The second path was also buggy for class bindings, as the return value of `classIndexOf` was incorrectly
negated: it considered a matching class attribute as non-matching and vice-versa. This bug was not observable
because of another issue, where the class-handling in part 2 was never relevant because of the special-case
in part 1.
This commit separates path 1 entirely from path 2 and removes the buggy class-matching logic in part 2, as
that is entirely handled by path 1 anyway. `isCssClassMatching` is updated to exclude class bindings from
being matched for inline templates.
Fixes#54798
PR Close#54800
The paths for the security guide were flipped in the original PR. As a result, it looked for a markdown file in the best-practices directory when it should have looked for it in the guide directory instead.
PR Close#54830
Add an internal API to enable and use i18n hydration for testing and development. This helps ensure that we don't accidentally break the current behavior until we are completely ready to roll out i18n support.
PR Close#54784
Currently if an `(output)` listener fails, it will be handled gracefully
by Angular and reported to the `ErrorHandler`.
For programmatic subscriptions with `OutputEmitterRef`, this is not the case.
Instead, as soon as any subscription is failing, all other subsequent
subscription callbacks are not firing anymore.
This commit intends to make this more consistent by gracefully
reporting errors from `OutputEmitterRef#emit` to `ErrorHandler`,
allowing for listener execution to continue.
PR Close#54821
Returning `UrlTree` from a guard was a convenient new feature added to
the `Router`. However, it does not have feature-parity with the old
`router.navigate(...); return false;` pattern. The most common use-case
for this feature is to redirect to a new page _without_ updating the URL
from the initially attempted navigation. For example, rendering a 404
page when the user does not have access privelages to a route.
Fixes#17004Fixes#27148
BREAKING CHANGE: Guards can now return `RedirectCommand` for redirects
in addition to `UrlTree`. Code which expects only `boolean` or `UrlTree`
values in `Route` types will need to be adjusted.
PR Close#45023
Ensures that all of the functions intended to be run in initializers are in an injection context. This is a stop-gap until we have a compiler diagnostic for it.
PR Close#54761
This commits assert that the repeater instruction gets a reference
to a tracking function. This change will allow us to better track
occurences of https://github.com/angular/angular/issues/53628 -
in certain situations a reference to a tracking function might be
undefiened.
We are not fixing the underlying issue here, just getting better
visibility.
PR Close#54814
Speeds up the retrieval of `DestroyRef` in `EventEmitter` because
`try/catch` is expensive if there is no injection context.
We saw a script time regression in Cloud.
The goldens had to be updated because `getInjectImplementation` is now
referenced. `inject` also references the underlying field, but directly.
This is super minimal overhead of a function exposing the internal
field.
PR Close#54748
Moves the logic that creates the defer resolver function into `@angular/compiler` for consistency with the rest of the compilation APIs. Also renames some of the symbols to make it clearer what they're used for.
PR Close#54759
Fixes an issue where we were outputting the reference to non-deferrable dependencies as strings, rather than going through the reference emitter. This caused some issues internally because the reference wasn't maintained in the generated JS.
PR Close#54759
Currently we have the `deferrableDeclToImportDecl`, `deferBlocks`, `deferrableTypes` and `deferBlockDepsEmitMode` fields on the `R3ComponentMetadata` which is incorrect, because the interface is used both for JIT and AOT mode even though the information for those fields is AOT-specific. It will be problematic for partial compilation since the runtime will have a reference to the dependency loading function, but will not be able to provide any of the other information.
These changes make the following refactors:
1. It changes the defer-related information in `R3ComponentMetadata` to include only references to dependency functions which can be provided both in JIT and AOT.
2. Moves the AOT-specific defer analysis into the `ComponentResolutionData`.
3. Moves the construction the defer dependency function into the compilation phase of the `ComponentDecoratorHandler`.
4. Drops support for defer blocks from the `TemplateDefinitionBuilder`. This allows us to clean up some TDB-specific code and shouldn't have an effect on users since the TDB isn't used anymore.
PR Close#54759
This commit updates `ApplicationRef.tick` to use `detectChangesInternal` for root
views rather than go through the `ChangeDetectorRef.detectChanges` API
which refreshes the host view without first looking at whether the view
is `OnPush` and not dirty. The current behavior would hide errors in
`OnPush` components that do not correctly get marked for check and would
break when migrating to zoneless change detection because `markForCheck`
was never called so change detection was never scheduled.
The error would be surprising and blamed on switching to zoneless when in
reality the issue already exists and is a problem with the component not
calling `markForCheck`. However, this error is hidden today because
`ApplicationRef.tick` refresh host bindings unconditionally.
BREAKING CHANGE: `OnPush` views at the root of the application need to
be marked dirty for their host bindings to refresh. Previously, the host
bindings were refreshed for all root views without respecting the
`OnPush` change detection strategy.
PR Close#53718
PR Close#53718
This commit updates HTML sanitization logic to avoid infinite loops in case clobbered elements contain fields like `nextSibling` or `parentNode`. Those fields are used for DOM traversal and this update makes sure that those calls return valid results.
Also this commit fixes an issue when clobbering `nodeName` causes JS exceptions.
PR Close#54425
An i18n message effectively acts as a dynamic template: two elements with contiguous instruction indices won't necessarily be contiguous in the DOM.
For that reason, we need to maintain a mapping from instruction index to a physical DOM node in order to hydrate views with i18n, pointing to where hydration for that view should begin.
PR Close#54750
Updates the instruction generation for two-way bindings to only emit the `twoWayBindingSet` call when writing to template variables. Since template variables are constants, it's only allowed to write to them when they're signals. Non-signal values are flagged during template type checking.
Fixes#54670.
PR Close#54714
We have a diagnostic that reports writes to template variables which worked both for regular event bindings and two-way bindings, however the latter was broken by #54154 because two-way bindings no longer had a `PropertyWrite` AST.
These changes fix the diagnostic and expand it to allow two-way bindings to template variables that are signals.
PR Close#54714
Moves the check which ensures that there are no writes to template variables into the `TemplateSemanticsChecker` to prepare for the upcoming changes.
PR Close#54714
Introduces a new `TemplateSemanticsChecker` that will be used to flag semantic errors in the user's template. Currently we do some of this in the type check block, but the problem is that it doesn't have access to the template type checker which prevents us from properly checking cases like #54670. This pass is also distinct from the extended template checks, because we don't want users to be able to turn the checks off and we want them to run even if `strictTemplates` are disabled.
PR Close#54714
The `runCallbackOnce` closure is declared not to have any parameters itself, so it is
compatible as `queueMicrotask` callback without the extra closure. This reduces the call
stack by a frame and avoids the extra closure allocation.
PR Close#54801
This commit addresses a typing mismatch, where these functions were declared to return whichever
value their callback returned, but this was inaccurate: it's always a test callback function
with `done` argument.
PR Close#54801
The assertion in `packages/core/test/acceptance/after_render_hook_spec.ts:165` was prone to flakes,
where Jasmine could frequently report an error:
```
Error: 'expect' was used when there was no current spec, this could be because an asynchronous test timed out
at Env.expect (node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1945:15)
at expect (node_modules/jasmine-core/lib/jasmine-core/jasmine.js:8267:18)
at file:///packages/core/test/acceptance/after_render_hook_spec.ts:165:12
```
This happens because `wrapTestFn` checks for an exact type of `Promise`, which may have been patched by zone.js
such that the `instanceof` condition is dependent on whether zone.js has patched the `Promise` constructor.
PR Close#54801
Many acceptance tests define goldens for both `TemplateDefinitionBuilder` and Template Pipeline. All such tests have had the TDB golden files removed, and the corresponding expectations adjusted.
PR Close#54757
`TemplateDefinitionBuilder` is the legacy template compiler, and was replaced by Template Pipeline as the default in v17.3.
This PR attempts to delete `TemplateDefinitionBuilder`, `ExpressionConverter`, and various helpers (i18n context, style builder, property visitors, etc).
Consider this a first pass: a lot of code has not yet been deleted (e.g. old TDB-specific test cases), and I'm sure I have missed additional helper code.
PR Close#54757
There is an edge case where synchronous navigations caused in
response to navigation events can result in a previous navigation not
being unsubscribed from. b/328219996
PR Close#54710
This commit ensures that render hooks are rerun when a node is attached
or detached. We do not necessarily need to run change detection but DOM
did change so render hooks should execute.
PR Close#54083
This commit updates the `afterRender` and `afterNextRender` hooks to
notify the scheduler (which subsequently schedules change detection)
when created. This makes the hooks similar to `requestAnimationFrame`,
which requests that the browser schedule a rendering operation. This
reqeust is not conditional. Even if there was nothing to repaint, the
`requestAnimationFrame` callback will execute.
In Angular, this is useful because callers of `afterNextRender` don't
necessarily have any way of knowing whether a change detection is even
scheduled. For example, the anchor scrolling with the Angular Router
needs to wait for rendering to complete before attempting to scroll
because rendering can affect the size of the page. However, if the user
is already on the page that the navigation is targeting, such as
navigating to an anchor on the page, there is nothing new for the Router
to render so a render might not even be scheduled.
Related to https://github.com/angular/angular/issues/53985, which
could use `afterNextRender` instead of `setTimeout` to ensure the
scrolling happens in the same frame as the page rendering, but would not
necessarily work without this change (as described above). Note that the
scrolling _cannot_ use a microtask to ensure scrolling happens in the
same frame because `NgZone` will ensure microtasks flush before
change detection, so it would cause the scroll to happen before rendering.
PR Close#54083
Currently we have the `deferrableDeclToImportDecl`, `deferBlocks`, `deferrableTypes` and `deferBlockDepsEmitMode` fields on the `R3ComponentMetadata` which is incorrect, because the interface is used both for JIT and AOT mode even though the information for those fields is AOT-specific. It will be problematic for partial compilation since the runtime will have a reference to the dependency loading function, but will not be able to provide any of the other information.
These changes make the following refactors:
1. It changes the defer-related information in `R3ComponentMetadata` to include only references to dependency functions which can be provided both in JIT and AOT.
2. Moves the AOT-specific defer analysis into the `ComponentResolutionData`.
3. Moves the construction the defer dependency function into the compilation phase of the `ComponentDecoratorHandler`.
4. Drops support for defer blocks from the `TemplateDefinitionBuilder`. This allows us to clean up some TDB-specific code and shouldn't have an effect on users since the TDB isn't used anymore.
PR Close#54700
This commit updates `ApplicationRef.tick` to use `detectChangesInternal` for root
views rather than go through the `ChangeDetectorRef.detectChanges` API
which refreshes the host view without first looking at whether the view
is `OnPush` and not dirty. The current behavior would hide errors in
`OnPush` components that do not correctly get marked for check and would
break when migrating to zoneless change detection because `markForCheck`
was never called so change detection was never scheduled.
The error would be surprising and blamed on switching to zoneless when in
reality the issue already exists and is a problem with the component not
calling `markForCheck`. However, this error is hidden today because
`ApplicationRef.tick` refresh host bindings unconditionally.
BREAKING CHANGE: `OnPush` views at the root of the application need to
be marked dirty for their host bindings to refresh. Previously, the host
bindings were refreshed for all root views without respecting the
`OnPush` change detection strategy.
PR Close#53718
In order to serialize and hydrate i18n blocks, we need to be able to walk an AST for the translated message. This AST is generated during normal parsing of the message.
PR Close#54724
The following changes help the language service code build in g3:
* `Omit<T>` produces an index signature, so we must access the resulting properties with square bracket (because `noPropertyAccessFromIndexSignature` is on in g3).
* Explicitly export `absoluteFrom` from `packages/compiler-cli/index.ts`, since the `*` re-export is patched out in g3.
* Remove const from a few const enums, since accessing const enums across modules is not compatible with `isolatedModules` (which is on in g3).
PR Close#54726
When a view has the `Dirty` flag and is reattached, we should ensure that it is
reached and refreshed during the next change detection run from above.
In addition, when a view is created and attached, we should ensure that it is reached
and refreshed during change detection. This can happen if the view is
created and attached outside a change run or when it is created and
attached after its insertion view was already checked. In both cases, we
should ensure that the view is reached and refreshed during either the
current change detection or the next one (if change detection is not
already running).
We can achieve this by creating all views with the `Dirty` flag set.
However, this does happen to be a breaking change in some scenarios.
The one identified internally was actually depending on change detection
_not_ running immediately because it relied on an input value that was
set using `ngModel`. Because `ngModel` sets its value in a `Promise`, it
is not available until the _next_ change detection cycle. Ensuring
created views run in the current change change detection will result in
different behavior in this case.
fixes#52928fixes#15634
BREAKING CHANGE: Newly created and views marked for check and reattached
during change detection are now guaranteed to be refreshed in that same
change detection cycle. Previously, if they were attached at a location
in the view tree that was already checked, they would either throw
`ExpressionChangedAfterItHasBeenCheckedError` or not be refreshed until
some future round of change detection. In rare circumstances, this
correction can cause issues. We identified one instance that relied on
the previous behavior by reading a value on initialization which was
queued to be updated in a microtask instead of being available in the
current change detection round. The component only read this value during
initialization and did not read it again after the microtask updated it.
PR Close#54735
When the `ApplicationRef` refreshes attached views, it will continue to
do so while there is still one marked for check after the refresh
completes.
BREAKING CHANGE: When Angular runs change detection, it will continue to
refresh any views attached to `ApplicationRef` that are still marked for
check after one round completes. In rare cases, this can result in infinite
loops when certain patterns continue to mark views for check using
`ChangeDetectorRef.detectChanges`. This will be surfaced as a runtime
error with the `NG0103` code.
PR Close#54734
The current behavior of `autoDetect` in `ComponentFixture` does not
match production very well. It has several flaws that make it an
insufficient change detection mechanism:
* It runs change detection for the component under test _after_ views
attached to the `ApplicationRef`. This can cause real behavior
differences that break in production, because tests can observe view
refreshes in the incorrect order (for example, a dialog refreshing
before the component which opened it).
* Because of the above ordering, render hooks registered during change
detection of the fixture views _will not execute at all_ because
`ApplicationRef.tick` already happen.
* It does not rerun change detection on the view tree if there are more
dirty views to refresh after the render hooks complete.
* It effectively hides/swallows errors from change detection inside the
`onMicrotaskEmpty` subscription by not reporting them to the error
handler. Instead, this error ends up being unhandled in the
subscription and rxjs throws these in a `setTimeout`.
All of the above are problematic but this commit _does not_ fix the
final point. Ideally, we can land this in a future change but this
requires additional internal fixes. In the meantime, we have to juggle
special-case handling of the component fixture views within
`ApplicationRef.tick` using some special events to retain current
behavior and avoid errors from the fixture propagating to the `ErrorHandler`.
BREAKING CHANGE: The `ComponentFixture.autoDetect` feature now executes
change detection for the fixture within `ApplicationRef.tick`. This more
closely matches the behavior of how a component would refresh in
production. The order of component refresh in tests may be slightly
affected as a result, especially when dealing with additional components
attached to the application, such as dialogs. Tests sensitive to this
type of change (such as screenshot tests) may need to be updated.
Concretely, this change means that the component will refresh _before_
additional views attached to `ApplicationRef` (i.e. dialog components).
Prior to this change, the fixture component would refresh _after_ other
views attached to the application.
PR Close#54733
For model signals we introduced some sniffing on the return type of a
`.subscribe` invocation- allowing for subscribe to _just_ return a
callback directly to unsubscribe.
This works in practice, but the positive `tCleanup` indices have more
meaning, especially in the context of `DebugElement`. A positive index
indicates a DOM event- so we need to revert this change. This now
surfaced as we made `EventEmitter` return a function + the subscription
via a proxy that ended up `typeof function` --> and broke some tests
where debug element incorrectly invoked non-dom outputs as dom
listeners. We don't need this change with current unsubscribe function
concept.
PR Close#54650
Currently the `makeProgram` utility from `ngtsc/testing` does not use
the test host by default- optimizing for source file caching.
Additionally, the host can be updated to attempt caching of the `.d.ts`
files from `@angular/core`— whether that's fake core, or the real core-
is irrelevant. We are never caching if these changes between tests, so
correctness is guaranteed.
This commit reduces the type check test times form 80s to just 11
seconds, faster than what it was before with `fake_core`. The ngtsc
tests also run significantly faster. From 40s to 30s
PR Close#54650
The `inject` global augmentation from upgrade tests, leak into
all source files for IDEs, making it easy to run into issues
when actually trying to deal with `inject` from Angular core for DI.
PR Close#54650
Technically `model()` and `output()` already need to be defined in an
injection context- because `OutputRef` requires this.
To improve the error messaging, this commit asserts this as part of the
top-level entry functions for `model()` and `output()`. Without this
change, the error would mention the `_createOutputRef` internal
function.
PR Close#54650
An `EventEmitter` is a construct owned by Angular that should be
used for outputs as of right now.
As we are introducing the new `OutputRef` interface for the new output
function APIs, we also think `EventEmitter` should implement
`OutputRef`— ensuring all "known" outputs follow the same contract.
This commit ensures `EventEmitter` implements an `OutputRef`
Note: An output ref captures the destroy ref from the current injection
context for clean-up purposes. This is also done for `EventEmitter` in a
backwards compatible way:
- not requiring an injection context. EventEmitter may be used
elsewhere.
- not cleaning up subscriptions/completing the emitter when the
directive/component is destroyed. This would be a change in behavior.
Note 2: The dependency on `DestroyRef` causes it to be retained in all
bundling examples because ironically `NgZone` uses `EventEmitter`- not
for outputs. The code is pretty minimal though, so that should be
acceptable.
`EventEmitter` will now always retain `NgZone. This increases the
payload size slightly around 800b for AIO. Note that the other increases
were coming from previous changes. This commit just pushed it over the
threshold.
PR Close#54650
A model signal is technically an output, at runtime and conceptually.
This commit re-uses the shared output ref logic and ensures the
interfaces match.
PR Close#54650
This commit introduces an addition to `output()` and
`outputFromObservable`()` —called `outputToObservable()`.
The helper lives in the RxJS interop package and allows agnostic
programmatic subscriptions to `OutputRef`s by converting the output
to an observable with `.pipe` etc.
The function is ideally used in all places where you subscribe to an
output programmatically. Those outputs in the future, with the new APIs,
may not be actual RxJS constructs, but abstract `OutputRef`'s that
simply expose a `.subscribe` method. The helper allows you to
agnostically convert outputs to RxJS observables that you can safely
interact with.
The observables are also completed automatically, if possible, when the
owning directive/component is destroyed— Something that is not
guaranteed right now.
PR Close#54650
Introduces a second API in addition to the new `output()` function.
The new function `outputFromObservable()` can be used to declare outputs
using the new `OutputRef` API and `output()` API, while using a custom
RxJS observable as data source.
This is something that is currently possible in Angular and we would
like to keep possible- even though we never intended to support custom
observables aside from RxJS-based `EventEmitter`.
The interop bridges the gap and allows you to continue using
`Subject`, `ReplaySubject`, `BehaivorSubjct,` - or cold custom
observables for outputs. You can still trigger logic only when
the output is subscribed- unlike with imperative `emit`s of
`EventEmitter` or the new `OutputEmitterRef`.
A notable difference is that you need two class members where you
previously could access the `Subject` directly. This is an intentional
trade-off we've made to ensure that all new outputs implement the
`OutputRef` interface and we are exposing a minimal API surface to
consumers of components that currently access the output
programmatically.
PR Close#54650
This commit allows us to detect initializer APIs like
`outputFromObservable` that are declared in different modules- not
necessarily `@angular/core`.
PR Close#54650
This commit exposes the new `output()` API with numerous benefits:
- Symmetrical API to `input()`, `model()` etc.
- Fixed types for `EventEmitter.emit`— current `emit` method of
`EventEmitter` is broken and accepts `undefined` via `emit(value?: T)`
- Removal of RxJS specific concepts from outputs. error channels,
completion channels etc. We now have a simple consistent
interface.
- Automatic clean-up of subscribers upon directive/component destory-
when subscribed programmatically.
```ts
@Directive({..})
export class MyDir {
nameChange = output<string>(); // OutputEmitterRef<string>
onClick = output(); // OutputEmitterRef<void>
}
```
Note: RxJS custom observable cases will be handled in future commits via
explicit helpers from the interop.
PR Close#54650
This commit creates the proposed `OutputRef` interface along
with `OutputEmitterRef`:
- `OutputRef` is the consistent interface for all Angular outputs.
- `OutputEmitterRef` is an extension for emitting values. Like
`EventEmitter`.
- subscriptions are cleaned up automatically upon directive/component
destroy.
- emitting is an error when destroyed
- subscribing programmatically is an error when already destroyed.
This commit will also implement the shared output ref runtime construct,
that can be used by `output()`, `outputFromObservable()` and `model()`.
We will manage subscriptions in a simple way, manually, without RxJS.
PR Close#54650
This commit replaces `fake_core` with the real `@angular/core`
output. See previous commit for reasons.
Overall, this commit:
* Replaces references of `fake_core`
* Fixes tests that were testing Angular compiler detection that _would_
already be flagged by type-checking of TS directly. We keep these
tests for now, and add `@ts-ignore` to verify the Angular checks, in
case type checking is disabled in user applications- but it's worth
considering to remove these tests. Follow-up question/non-priority.
* Adds `@ts-ignore` to the tests for `defer` 1P because the property is
marked as `@internal` and now is (correctly) causing failures in the
compiler test environment.
* Fixes a couple of tests with typos, wrong properties etc that
previously weren't detected! A good sign.
PR Close#54650
As part of improving test safety of the compiler, I've noticed that
we have a special pass for detecting external `ModuleWithProviders`
where we detect the module type from an object literal.
This literal is structured like the following: `{ngModule: T}`. The
detection currently takes `T` directly, but in practice it should be
`typeof T` to satisfy the `ModuleWithProviders` type that is accepted
as part of `Component#imports`.
This commit adds support for this, so that we can fix the unit test
in preparation for using the real Angular core types in ngtsc tests.
PR Close#54650
This adds documentation regarding the latest changes to framework merge tools. It specifically covers the requires: TGP label and separate sync for primitives.
PR Close#54664
Previously, the language service relied on deep imports such as `@angular/compiler/render3/...`. This is bad form, because that creates a dependency on the package's internal structure. Additionally, this is not compatible with google3.
In this PR, I replace all the deep imports with shallow imports, in some cases adding the missing symbol to the `compiler.ts` exports.
PR Close#54695
This commit updates TestBed logic to take into account situations when dependencies loaded within `@defer` blocks may import NgModules with providers. For such components, we invoke provider override function, which recursively inspects and applies the necessary changes.
PR Close#54667
In zone-full applications, this is already true because effects are
scheduled inside a microtask and tracked by ZoneJS. When not using
zones, this should stay consistent on principle and for testability
reasons. A general pattern with zoneless testing will be to update state
and `await` some promise (i.e. `fixture.whenStable`, which will be
linked to `ApplicationRef.isStable`).
PR Close#53835
The current behavior of `autoDetect` in `ComponentFixture` does not
match production very well. It has several flaws that make it an
insufficient change detection mechanism:
* It runs change detection for the component under test _after_ views
attached to the `ApplicationRef`. This can cause real behavior
differences that break in production, because tests can observe view
refreshes in the incorrect order (for example, a dialog refreshing
before the component which opened it).
* Because of the above ordering, render hooks registered during change
detection of the fixture views _will not execute at all_ because
`ApplicationRef.tick` already happen.
* It does not rerun change detection on the view tree if there are more
dirty views to refresh after the render hooks complete.
* It effectively hides/swallows errors from change detection inside the
`onMicrotaskEmpty` subscription by not reporting them to the error
handler. Instead, this error ends up being unhandled in the
subscription and rxjs throws these in a `setTimeout`.
All of the above are problematic but this commit _does not_ fix the
final point. Ideally, we can land this in a future change but this
requires additional internal fixes. In the meantime, we have to juggle
special-case handling of the component fixture views within
`ApplicationRef.tick` using some special events to retain current
behavior and avoid errors from the fixture propagating to the `ErrorHandler`.
breaking note for future when isG3 flag condition is removed for v18:
The `ComponentFixture.autoDetect` feature now executes
change detection for the fixture within `ApplicationRef.tick`. This more
closely matches the behavior of how a component would refresh in
production. The order of component refresh in tests may be slightly
affected as a result, especially when dealing with additional components
attached to the application, such as dialogs. Tests sensitive to this
type of change (such as screenshot tests) may need to be updated.
PR Close#54354
One downside of implicit dependency tracking in `effect()`s is that it's easy
to for downstream code to end up running inside the effect context by accident.
For example, if an effect raises an event (e.g. by `next()`ing a `Subject`), the
subscribers to that `Observable` will run inside the effect's reactive context,
and any signals read within the subscriber will end up as dependencies of the
effect. This is why the `untracked` function is useful, to run certain
operations without incidental signal reads ending up tracked.
However, knowing when this is necessary is non-trivial. For example, injecting
a dependency might cause it to be instantiated, which would run the constructor
in the effect context unless the injection operation is untracked.
Therefore, Angular will automatically drop the reactive context within a number
of framework APIs. This commit addresses these use cases:
* creating and destroying views
* creating and destroying DI injectors
* injecting dependencies
* emitting outputs
Fixes#54548
There are likely other APIs which would benefit from this approach, but this
is a start.
PR Close#54614
This refactor makes it easier to update the return types of guards.
Rather than having to track what types guards can return, which may
change with new features over time, `MaybeAsync<GuardResult>` can be
used instead.
PR Close#54580
As a part of #54154, an old parser behavior came up where two-way bindings were parsed by appending `= $event` to the event side. This was problematic, because it allowed some non-writable expressions to be passed into two-way bindings.
These changes introduce a migration that will change the two-way bindings into two separate input/output bindings that represent the old behavior so that in a future version we can throw a parser error for the invalid expressions.
```ts
// Before
@Component({
template: `<input [(ngModel)]="a && b"/>`
})
export class MyComp {}
// After
@Component({
template: `<input [ngModel]="a && b" (ngModelChange)="a && (b = $event)"/>`
})
export class MyComp {}
```
PR Close#54630
Fixes that a query like `viewChild('locator', {read: ElementRef<HTMLElement>})` would throw because we didn't account for expressions with type parameters.
I've also included support for parenthesized expressions and `as` expressions since it's pretty easy to support them.
Fixes#54645.
PR Close#54647
Updated the "Setting up Zone.js" instructions to the latest convention from
how the Angular CLI configures it.
Include adding zone-flats.ts to the tsconfig.app.json file step.
Added src/ to zone-flag.ts in the code example.
PR Close#52409
Add more details around:
- What we consider a breaking change
- What is a deprecation
- How do we guarantee Angular stays stable
- Update invalid links
PR Close#51423
Angular has the `@Attribute` decorator that allows for attributes to be injected from the host node, but we don't have an equivalent for the `inject` function. These changes introduce the new `HostAttributeToken` class that can be used to inject attributes similarly to `@Attribute`. It can be used as follows:
```typescript
import {HostAttributeToken, inject} from '@angular/core';
class MyDir {
someAttr = inject(new HostAttributeToken('some-attr'));
}
```
The new API works similarly to `@Attribute` with one key exception: it will throw a DI error when the attribute doesn't exist, instead of returning `null` like `@Attribute`. We made this change to align its behavior closer to other injection tokens.
PR Close#54604
This commit ensures that any internal render hooks that cause views to
become dirty again first refresh those dirty views before running user
render hooks. This ensures that user render hooks have the most complete
render state possible and stops them from needlessly executing multiple
times. This is important to maintain the goal of the public render
hooks, which is to provide the safest place to place code that depends
on DOM state, especially in ways that may force a browser paint.
PR Close#54224
This adds a helper function to defer application state updates to the
first possible "safe" moment. If application-wide change detection
(ApplicationRef.tick) is currently executing when this function is used,
the callback will execute as soon as all views attached to the
`ApplicationRef` have been refreshed. Refreshing the application views
will happen again before `checkNoChanges` executes.
When a change detection is _not_ running, this state update will execute
in the microtask queue.
This function is necessary as a replacement for current
`Promise.resolve().then(() => stateUpdate())` to be zoneless compatible
while ensuring those state updates are synchronized to the DOM before
the browser repaint. Without this, updates done in `Promise.resolve(...)` would
queue another round of change detection in zoneless applications, and
this change detection could happen in the next browser frame, and cause
noticeable flicker for the user.
Additionally, this function provides a way to perform state updates that
will run on the server as well as in the browser.
Last, current applications using `ngZone: 'noop'` may not be
calling `ApplicationRef.tick` at all so this function provides a
mechanism to ensure the state update still happens by racing
a microtask with `afterNextRender` (which might never execute).
PR Close#54224
Fixes that initializer functions weren't being recognized if they are aliased (e.g. `import {model as alias} from '@angular/core';`).
To do this efficiently, I had to introduce the `ImportedSymbolsTracker` which scans the top-level imports of a file and allows them to be checked quickly, without having to go through the type checker. It will be useful in the future when verifying that that initializer APIs aren't used in unexpected places.
I've also introduced tests specifically for the `tryParseInitializerApiMember` function so that we can test it in isolation instead of going through the various functions that call into it.
PR Close#54609
Currently, when a `@defer` block contains standalone components that import NgModules with providers, those providers are not available to components declared within the same NgModule. The problem is that the standalone injector is not created for the host component (that hosts this `@defer` block), since dependencies become defer-loaded, thus no information is available at host component creation time.
This commit updates the logic to collect all providers from all NgModules used as a dependency for standalone components used within a `@defer` block. When an instance of a defer block is created, a new environment injector instance with those providers is created.
Resolves#52876.
PR Close#52881
This PR enhances the Angular documentation by replacing the placeholder `<component-name>` with the actual `PageNotFoundComponent` in the wildcard route configuration. This update ensures that the documentation accurately reflects the recommended practice for handling page-not-found scenarios. Additionally, it addresses the issue where HTML entities like `<` were being displayed instead of the desired `<` symbol, resulting in clearer and more readable documentation for users.
PR Close#54570
Fixes that initializer functions weren't being recognized if they are aliased (e.g. `import {model as alias} from '@angular/core';`).
To do this efficiently, I had to introduce the `ImportedSymbolsTracker` which scans the top-level imports of a file and allows them to be checked quickly, without having to go through the type checker. It will be useful in the future when verifying that that initializer APIs aren't used in unexpected places.
I've also introduced tests specifically for the `tryParseInitializerApiMember` function so that we can test it in isolation instead of going through the various functions that call into it.
PR Close#54480
The diagnostic for signals that haven't been invoked wasn't working internally, because the path to `@angular/core` is different. These changes resolve the issue and do some general cleanup.
PR Close#54585
Fixes an edge case where a single-line elemnt with a long tag name a closing bracket on a new line was putting the control flow migration into an infinite loop.
Fixes#54587.
PR Close#54588
Template pipeline is now the default template compiler.
A pair of source map tests is failing, related to DI in JIT mode; I will fix and re-enable these during the preview period.
PR Close#54571
ApplicationRef.tick has a loop that will refresh views again that have
an updated signal. This change ensures views marked with the `Dirty`
flag are also considered in this loop, but only inside g3 for now
because this may be considered a breaking change and we need to wait for
v18 to land externally.
PR Close#54572
This commit prevents `AsyncPipe` from calling `markForCheck` when values
are synchronously emit during subscription to an observable. This
prevents subscriptions to `Replay` observables from needlessly walking
up to the root of the view tree during template execution for each
new replay observable in the template.
PR Close#54554
Use no-remote-exec to allow for building and serving to occur locally but still allow remote caching. Because of the number of
files involved in being passed to and from the RBE server, it is actually a bit faster to perform these actions locally.
PR Close#54549
In rare cases people may use an underscore in their component names, which was not accounted for in the formatting portion of the migration.
fixes: #54532
PR Close#54533
This provides some more information on how to release and notably includes commands for zipping extension code and source code, which can otherwise be tricky to get exactly right.
PR Close#54525
This is based on an internal issue report.
An earlier change introduced a diagnostic to report cases where a symbol is in the `deferredImports` array, but is used eagerly. The check worked by looking through the deferred blocks in a scope, resolving the scope for each and checking if the element is within the scope. The problem is that resolving the scope won't work across scoped node boundaries. For example, if there's a control flow statement around the block or within the block but around the deferred dependency, it won't be able to resolve the scope since it isn't a direct child, e.g.
```
@if (true) {
@defer {
<deferred-dep/>
}
}
```
To fix this the case where the deferred block is inside a scoped node, I've changed the `R3BoundTarget.deferBlocks` to be a `Map` holding both the deferred block and its corresponding scope. Then to resolve the case where the dependency is within a scoped node inside the deferred block, I've added a depth-first traversal through the scopes within the deferred block.
PR Close#54499
We have a couple of cases now (#53753 and #54414) where we're forced to redefine enums as object literals. These literals aren't rendered in the best way in the docs so these changes introduce a new `object-literal-as-enum` tag that we can use to mark them so they're treated for documentation purposes.
PR Close#54487
This change allows template binding "inert" attribute with the following syntax: [inert]="isInert"
Fixes#51879
fixup! fix(compiler): adding the inert property to the "SCHEMA" array
revert: "fixup! fix(compiler): adding the inert property to the "SCHEMA" array"
This reverts commit b637b7ce646e8bab2f585339028a84018e8ea982.
This commit is being reverted because the inert property is safe as a boolean attribute
PR Close#53148
This commit addresses a problem with PR #53695 that introduced support for default imports,
where the actual dynamic import used in the defer loading function continued to use the
symbol name, instead of `.default` for the dynamic import. This issue went unnoticed in the
testcase because a proper instance was being generated for the `ɵsetClassMetadataAsync` function,
but not the generated dependency loader function.
Fixes#54491
PR Close#54495
Prior to this fix an incorrect view instance (a dynamically created component
one instead of the root view) was passed to the content query function. Having
incorrect view instance meant that a component instance could not be found.
This is a pre-existing bug, introduction of signal-based queries just surfaced it.
Fixes#54450
PR Close#54457
The documentation on angular.dev mentions build-angular:browser as default
application builder. This is not correct. Recent applications are setup
with build-angular:application by default.
PR Close#54386
In the Angular DevTools Chrome DevTools page:
- Angular DevTools is able to ask the background script to list each frame that has been registered on a page.
- Angular Devtools is able to ask the background script to "enable" the connection on a particular frame. This enables the messaging between the content script <-> background script <-> devtools page
- Implements detection of non unique urls on the inspected page
Limitations:
- The `inspectedWindow.eval` API is only able to target frames by frameURL. This means some features that integrate with Chrome DevTools like inspect element and open source will not be available when inspecting frames that do not have a unique url on the page.
PR Close#53934
Modifies the messaging layer of devtools to allow for switching communication between frames on a page. When served as a browser extension.
Design:
- When a page renders, DevTools installs a content script onto it through it's manifest file. The all_frames option is used here to install this script onto every frame in a page.
- When Angular is detected, the content script will install a backend script into it's frame.
- Each content script / backend script pairing is kept track of in the background script. This pairing represents an angular devtools context in a particular frame.
- Angular DevTools is able to ask the background script to list each frame that has been registered on a page.
- Angular Devtools is able to ask the background script to "enable" the connection on a particular frame. This enables the messaging between the content script <-> background script <-> devtools page
Limitations:
- The `inspectedWindow.eval` API is only able to target frames by frameURL. This means some features that integrate with Chrome DevTools like inspect element and open source will not be available when inspecting frames that do not have a unique url on the page.
PR Close#53934
When the linker is running using an unpublished version of angular, locally built, the version will be `0.0.0`.
When encountering this situation, the range that for the linker map support is considered to be `*.*.*` allowing
for the linker to work at build time with packages built with versioned angular.
Most notably this allows for us to properly use the linker in building our documentation site with the locally
built version of angular.
PR Close#54439
The version detection condition for signal two-way bindings used an OR
instead of an AND, resulting in every `.0` patch version being considered
as supporting two-way bindings to signals.
This commit fixes the logic and adds additional parentheses to ensure the
meaning of the condition is more clear. Long term, we should switch to
semver version parsing instead.
PR Close#54443
In order to allow both signals and non-signals in two-way bindings, we have to pass the expression through `ɵunwrapWritableSignal`. The problem is that the language service uses a bundled compiler that is fairly new, but it may be compiling an older version of Angular that doesn't expose `ɵunwrapWritableSignal` (see https://github.com/angular/vscode-ng-language-service/issues/2001).
These changes add a `_angularCoreVersion` flag to the compiler which the language service can use to pass the parsed Angular version to the compiler which can then decide whether to emit the function.
PR Close#54423
Currently all triggers are set up to show the placeholder block on the server, except for `on immediate` which is basically a noop. These changes update `on immediate` to match the rest of the triggers.
Fixes#54385.
PR Close#54394
Getting the typing for `ɵunwrapWritableSignal` just right was tricky so these changes add some tests to ensure that we don't regress.
Also reworks the type tester a bit to make it easier to find where to add new test files.
PR Close#54387
This commit updates the implementation of the `customElements` patch and also
patches FACE callbacks (`formAssociatedCallback`, `formDisabledCallback`, `formResetCallback`
and `formStateRestoreCallback`). This now allows invoking those callbacks in the same zone
where the custom element has been defined.
PR Close#50686
Assure that the same readonly array corresponding to the children query results
is returned for cases where a query is marked as dirty but there were no actual
changes to the content of the results array (this can happen if a view is added
and removed thus marking queries as dirty but not influencing final results).
Fixes#54376
PR Close#54392
Creates a "fast mode" for building the adev site, currently only disabling prerender during fast build.
This is intended to be used for local development.
PR Close#54364
The newly introduced signal queries would error if no match exists, due to an
invalid read within the query internals.
This commit addresses the crash by allowing there to be no matches.
PR Close#54353
Currently we have two fake copies of `@angular/core` in the compiler tests which can be out of sync and cause inconsistent tests. These changes reuse a single copy instead.
PR Close#54344
This updates some tests to use the public imports from `@angular/core` now that they are available,
and cleans up useless imports and inaccurate names.
PR Close#54334
In some situations, calling `markForCheck` can result in an infinite
loop in seemingly valid scenarios. When a transplanted view is inserted
before its declaration, it gets refreshed in the retry loop of
`detectChanges`. At this point, the `Dirty` flag has been cleared from
all parents. Calling `markForCheck` marks the insertion tree up to the
root `Dirty`. If the declaration is checked again as a result (i.e.
because it has default change detection) and is reachable because its
parent was marked `Dirty`, this can cause an infinite loop. The
declaration is refreshed again, so the insertion is marked for refresh
(again). We enter an infinite loop if the insertion tree always calls
`markForCheck` for some reason (i.e. `{{createReplayObservable() | async}}`).
While the case above does fall into an infinite loop, it also truly is a
problem in the application. While it's not an infinite synchronous loop,
the declaration and insertion are infinitely dirty and will be refreshed
on every change detection round.
Usually `markForCheck` does not have this problem because the `Dirty`
flag is not cleared until the very end of change detection. However, if
the view did not already have the `Dirty` flag set, it is never cleared
because we never entered view refresh. One solution to this problem
could be to clear the `Dirty` flag even after skipping view refresh but
traversing to children.
PR Close#54329
The `subscribe` methods on `ModelSignal` and `OutputEmitter` were marked as `@internal` which will break when the TCB needs to reference them. These changes make them `@deprecated` temporarily so we can address the properly later.
PR Close#54342
The new `model()` signal introduces a `ModelSignal` type that needs to be handled by the interpolatedSignalNotInvoked diagnostic to catch issues like:
```
<div>{{ myModel }}</div>
```
PR Close#54338
Add an image loader for Netlify Image CDN. It is slightly different in implementation from existing loaders, because it allows absolute URLs
Fixes#54303
PR Close#54311
The import of `module` can conflict with the native global variable called `module` and can break some internal tests. These switch to only importing the function we need.
PR Close#54333
Adds usages of signal-based queries into the signal integration test to
verify queries can be used in production, and testing environments as
expected (i.e. the transform works as expected).
PR Close#54314
This helps with the Angular CLI currently swallowing fatal diagnostic
errors in ways that are extremely difficult to debug due to workers
executing Angular compiler logic.
The worker logic, via piscina, is currently not forwarding such Angular
errors because those don't extend `Error.`
https://github.com/piscinajs/piscina/blob/a7042ea27d129f3cad75c422f5aa92f0663854ee/src/worker.ts#L175
Even with access to these errors by manually forwarding errors, via
patching of the Angular CLI, there is no stack trace due to us not using
`Error` as base class for fatal diagnostic errors. This commit improves
this for future debugging and also better reporting of such errors to
our users- if we would accidentally leak one.
PR Close#54309
An identical addition to: 760b1f3d0b.
This commit expands the `try/catch`-es:
- to properly NOT throw and just convert the diagnostic.
- to be in place for all top-level instances. Notably, this logic cannot
reside in the template type checker directly as otherwise we would
risk multiple duplicate diagnostics.
PR Close#54309
Fixes that `ɵunwrapWritableSignal` inferring getter functions as not matching the interface of `WritableSignal` instead of preserving them.
PR Close#54252
In a previous commit the TCB was changed to cast the assignment to an input in order to widen its type to allow `WritableSignal`. This ended up breaking existing inputs whose setter has a wider type than its getter. These changes switch to unwrapping the value on the binding side.
PR Close#54252
Reworks the TCB for two-way bindings to make them simpler and to avoid regressions for two-way bindings to generic inputs. The new TCB looks as follows:
```
var _t1: Dir;
var _t2 = _t1.input;
(_t1 as typeof _t2 | WritableSignal<typeof _t2>) = expression;
```
PR Close#54252
Adds support for model inputs in the framework. `model()` returns a writable signal that implicitly defines a input/output pair that can be used either in two-way bindings to keep two values in sync or by binding individually to the input and output. When the value of the `model` changes, it will emit an event with the current value.
Furthermore, these changes expand two-way bindings to accept `WritableSignal`. This will make it easier to transition existing code to signals in a backwards-compatible way.
Example:
```ts
@Directive({
selector: 'counter',
standalone: true,
host: {
'(click)': 'increment()',
}
})
export class Counter {
value = model(0);
increment(): void {
this.value.update(current => current + 1);
}
}
@Component({
template: `<counter [(value)]="count"/> The current count is: {{count()}}`,
})
class App {
count = signal(0);
}
```
PR Close#54252
This commit improves IDE completion of the `read` option for
signal-based queries.
Currently, TS only matches the first overload when starting out with
defining a query. TS doesn't build up the combination of possible
options from the second overload- so in practice users will only see
IDE completions for the `descendants` option.
This is not a problem for view queries as the only option is `read`, so
TS will always match the overload with the `read` option.
```
class X {
query = contentChild('', {^^ <--
here we should completion for `read` an `descendants`
}
```
PR Close#54280
Currently the error is a generic error "exportAs must be a string ...". This commit makes the error more specific to local compilation and adds some action items.
PR Close#54230
Currently the error is a generic error "selector must be a string ...". This commit makes the error more specific to local compilation and adds some action items.
PR Close#54230
Currently the error is a generic error "selector must be a string ...". This commit makes the error more specific to local compilation and adds some action items.
PR Close#54230
Currently the correct error message is shown only if @Component.styles is an array with some unresolved element. This change supports the new case of string type for the @Component.styles field.
PR Close#54230
A helper `validateLocalCompilationUnresolvedConst` is added to encapsulate a common pattern which leads to the error `LOCAL_COMPILATION_UNRESOLVED_CONST`.
PR Close#54230
The trailing error message comes from tracing the chain of DymaicValue which leads to a mostly useless error that highlights the same symbol as the original message and emits the error message "Unknown reference". This error message is removed in the favour of the original message which suffices.
PR Close#54230
A single error code is created to unify the common error pattern in local compilation mode where an imported const cannot be resolved, but needs to be resolved. This mainly happens for Angular decorator fields such as @Component.template.
The error messages are also upgraded to be more centered around this unifying theme.
PR Close#54230
Currently, when two components are named `TestComponent`, and both would
use e.g. control flow. Templates would be generated by the compiler and
those would conflict at runtime because the names for the template
functions are not ensured to be unique.
This seems like a more general problem that could be tackled in the
future in the template pipeline by always using the `ConstantPool`, but
for now, we should be good already, given us ensuring the `baseName`'s are
always unique.
PR Close#54273
This commit updates the implementation of the zone.js `fs` patch to
restore the implementation of `realpath.native` and patches it as a macrotask,
along with other functions of the `fs` package. This is the only nested function
that must be patched.
Closes: #45546
PR Close#54208
The `read` option for queries can rely on lexical variables inside the
class. These constructs are fine from a technical perspective in
TypeScript, but in practice, when the component/directive definition is
being created, the read value is extracted into the definition,
**outside** of the class. This breaks `this` references.
To fix this, we are restricting the `read` option to literal values.
Similar to `descendants`. Literal references are in practice constructs
like:
- `read: bla.X`
- `read: X`
where `bla` or `X` is never a `ThisKeywoord`- hence fixing the issue
and also simplifying the patterns for easier single file compilation.
PR Close#54257
This commit adds a JIT transform for signal-based queries, so that
queries are working as expected in JIT environments like `ng test` where
decorator metadata is needed as a prerequisite for the component
definition creation.
This is similar to the JIT transforms for signal inputs etc.
PR Close#54257
Extracts common JIT transform helper into the transform API, so that
those helpers can be re-used for output, model, queries and inputs.
PR Close#54257
Adding debug information for failing firebase deploy, hoping
to yield information about the missing resource. The next
multi-site seems to be failing, but is available.
PR Close#54275
The compileNgModuleFactory dont need to be in the application_ref file (in fact
the whole logic has little to do with ApplicationRef and it is not even called
from the application_ref). Performing this move to avoid circular dependencies
when the new query as signals authoring functions are exported.
PR Close#54103
This commit changes the approach to the reactive node representing query
results: instead of creating a custom node type we can use a computed -
the main change to get there is representing dirty change notification as
a signal (a counter updated every time a query changes its dirty status).
This change is dictated by simplification (we can avoid creation of a custom
signal type) as well as fixes to the multiple issues not covered by the
initial implementation:
- assuring referential stability of results (ex.: the same array instance
returned from child queries until results change);
- per-view results collection to avoid a situation where accessing query
results during view creation would return partial / inconsistent results;
- proper refresh of query results for both live and non-connected consumers.
All the above cases are covered by the additional tests in this commit.
PR Close#54103
This commit adds tests for content queries and fixes the arguments
order in the contentQuerySignal instruction, thus fixing a bug
discovered while adding tests.
PR Close#54103
This commits converts the hand-written tests into their usual,
compiled form. We can perform this change now since the compiler
bits of the queries-as-signal story landed.
PR Close#54103
This commit updates the logic of defer blocks to create an internal pending task to indicate that an application is not yet stable. This change would be helpful for zoneless applications.
PR Close#54239
Updates the acceptance authoring test compiler targets to support
multiple spec files. This will be useful for output, model, inputs
and queries.
PR Close#54253
Adds `output()` to the signal inputs integration test to verify
full integration with the Angular CLI. In the future we may
consider renaming the test to something less specific to signal inputs,
but for now this serves the purpose and `output()` is a closely related
part to signal-based inputs.
it doesn't warrant creating another new integration test, as those are
quite expensive to maintain and run.
PR Close#54217
The `listener` instruction currently always assumes RxJS subscribables,
and verifies this via `isSubscribable`. The type narrowing is not
ignored and the type remains `any` given the `ngDevMode` check.
This commit improves type safety, and actually switches to a dedicated
interface for "output subscribable" values. This is needed because
`Subscribable` from `RxJS` is typed to expect an observer in object
literal form- which is not correct and doesn't apply to `EventEmitter`
and matches the form of `.subscribe` we are using in the `listener`
instruction.
PR Close#54217
Similar to `input()`, initializer-based `output()`'s need to be
transformed in JIT to be annotated with an `@Output()` decorator.
This is necessary so that Angular can statically collect all defined
outputs without instantiating the class (which would not be possible
upon directive definition computation).
This commit introduces a transform next to the input transform that
automatically runs with the Angular CLI and `ng test`.
PR Close#54217
Adds type check diagnostic tests for the `output()` API. This
is necessary because we are maintaining a separate emitter
for `output()` as with the current design (still discussed - but this is
a starting foundation).
Note: `OutputEmitter` currently does not publicly expose `.subscribe`,
while the testing infrastructure exposes it for now. That is because we
are still discussing this before making changes in the TCB to account
for the case where `.subscribe` might be `@internal` ultimately.
PR Close#54217
Generalizes the type check table scenario testing infrastructure
so that it can also be used for testing outputs in a table-scheme
without a lot of TS code repetition.
PR Close#54217
Adds an ngtsc diagnostic and compilation output test for `output()`. The
test will verify certain recognition restrictions and ensures that
diagnostics are raised, in addition to proper full compilation output
being generated (aside from the compliance tests verifying output more
closely).
PR Close#54217
Adds compliance output tests for `output()` to verify that
we are emitting proper full compilation output, as well as proper
partial compilation output that can be linked to match the full output.
PR Close#54217
This commit introduces the `output()` function and corresponding
runtime code.
In practice, `output()` will defer to `EventEmitter` as outlined in the
RFC, but we are considering limiting the type to a minimal version that
is not coupled with RxJS, less complex, and also has better type safety
around emitting of values.
E.g. currently `EventEmitter.emit` can always be called without
any value, even though the output may be typed to always pass around
values of type `T`. This could cause subtle and confusing bugs.
PR Close#54217
As we are introducing the new `output()` function as an inituive
alternative to `@Output()` that matches with signal-based inputs,
this commit prepares the compiler to detect such initializer-based
outputs.
PR Close#54217
The deps tracker which is responsible to track orphan components does not work for classes mutated by custom decorator. Some work needed to make this happen (tracked in b/320536434). As a result, with option `forbidOrphanComponents` being true the deps tracker will falsely report any component as orphan if it or its NgModule have custom/duplicate decorators. So it is unsafe to use this option in the presence of custom/duplicate decorator and we disable it until it is made compatible. Note that applying custom/duplicate decorators to `@Injectable` classes is ok since these classes never make it into the deps tracker. So we excempt them.
PR Close#54139
Custom/duplicate decorators break the deps tracker in local mode. But deps tracker only deals with non-injectable classes. So applying custom/duplicate decorators to `@Injectable` only classes does not disturb deps tracker and local compilation in general. There are also ~ 100 such cases in g3 which cannot be cleaned up.
PR Close#54139
For cases like this:
```
@Component({...})
@Component({...})
export class SomeComp {
}
```
The `DecoratorHandler.detect` apparantly matches only one of the `@Component` decorator, leaving the other undetected which will be transformed by TS decorator helper and that breaks local compilation runtimes. But the error message only mentioned "custom" decorator, while in this case it is a "duplicate Angular" decorator. The respective error message is updated thus.
PR Close#54139
Consider the following very quirky Angular template, which has both an i18n attribute binding and a property binding to `in`:
```
<cmp [in]="foo" in="bar" i18n-in />
```
What would you expect the above template to do? `TemplateDefinitionBuilder` will emit the following Ivy instructions:
```
// Element constant attributes
consts: () => {
__i18nMsg__('bar', [], {}, {})
return [["in", i18n_0, __AttributeMarker.I18n__, "in"]];
}
// ...
function MyComponent_Template(rf, ctx) {
if (rf & 1) {
// Create mode
i0.ɵɵelement(0, "cmp", 0);
}
}
```
This makes some sense -- we create a single element, and attach an i18n message to the `in` attribute. But is this actually correct? Notice that the property binding is completely missing!
Indeed, Template Pipeline actually produces this code:
```
// Element constant attributes
consts: () => {
__i18nMsg__('bar', [], {}, {})
return [["in", i18n_0, __AttributeMarker.I18n__, "in"]];
}
// ...
function MyComponent_Template(rf, ctx) {
if (rf & 1) {
// Create mode
i0.ɵɵelement(0, "cmp", 0);
} else if (rf & 2) {
// Update mode
i0.ɵɵproperty("in", ctx.foo);
}
}
```
Aha! There's the property binding! Arguably, this is a bug in `TemplateDefinitionBuilder`, but after some discussion on Slack, we have decided to ban this practice in a future Angular version.
For now, we allow Template Pipeline to have slightly different output, but print an error to warn the user of the issue.
PR Close#54063
This test ensures that the `ExpressionChanged...` error does not happen
when signals are updated in a view that is attached to `ApplicationRef`
but was already checked. This was fixed in 432afd1ef4
which actually consequently fixes it for regular `markForCheck` as well.
PR Close#54206
* Renames the `input_signals` directory to `signals` so it can be reused for other tests.
* Reworks the build file to allow multiple test files.
PR Close#54213
Instead of maintaining individual transforms for `input`, `output`,
`model` etc. we are grouping them directly and the first one matching,
will execute.
This reduces needed traversal through AST and also makes it a little
more clean to write new initializer API metadata transforms.
Note: The Angular JIT transform is now also moving from `tooling.ts`
directly into `/transformers` for more local placement of transformer
logic.
PR Close#54200
Fixes that `@defer` blocks weren't recognizing default imports and generating the proper code for them. Default symbols need to be accessed through the `default` property in the `import` statement, rather than by their name.
PR Close#53695
One of the earlier commits separated one-way and two-way bindings which ended up breaking some internal targets, because it changed the assignment order. These changes bring back the old order.
PR Close#54154
In one of the earlier commits, the logic that appends `=$event` before parsing two-way bindings was removed and some validation was added to prevent unassignable expressions from being used. This ended up being problematic, because previously the parser was incorrectly allowing some invalid expressions which users came to depend on. For example, it transformed `[(value)]="a && a.b"` to `a && (a.b = $event)`.
These changes add some special cases for the common breakages that came up during the TGP.
PR Close#54154
Updates the template definition builder to emit the new format for the listener side of two-way bindings.
```js
// Before
listener("ngModelChange", function($event) {
return ctx.name = $event;
});
// After
ɵɵtwoWayListener("ngModelChange", function($event) {
ɵɵtwoWayBindingSet(ctx.name, $event) || (ctx.name = $event);
return $event;
});
```
PR Close#54154
Currently the listener side two-way listeners are parsed by appending `=$event` to the raw expression. This is problematic, because:
1. It can interfere with other expressions (see #37809).
2. It can lead to confusing error messages because users will see code that they didn't write.
3. It doesn't allow us to further manipulate the expression.
These changes remove the logic that appends `=$event` to resolve the issue. There's also some new logic that checks the expression after it has been parsed to ensure that the result is an assignable expression.
Subsequent commits will update the code that emits the expression to add back the `$event` assignment where it's needed.
PR Close#54154
Adds the following new instructions:
* `twoWayBindingSet` - used to assign values inside of the listener side of a two-way binding. Currently a noop, but will come into play later.
* `twoWayListener` - used to bind a two-way listener. Currently calls directly into `listener`, but it may be useful in the future.
PR Close#54154
Currently all the members of `_ParseAST` are public, even though they're all used only within the class. This change marks them as private so that it's explicit which ones are intended to be used outside the class.
PR Close#54154
Reworks the compiler so that it generates a `twoWayProperty` instruction, instead of `property`, for the property side of a two-way binding. Currently the new instruction passes through to `property`, but it'll have some two-way-binding-specific logic in subsequent PRs.
PR Close#54154
It was always the intent to have `afterRender` hooks allow updating
state, as long as those state updates specifically mark views for
(re)check. This commit delivers that behavior. Developers can now use
`afterRender` hooks to perform further updates within the same change
detection cycle rather than needing to defer this work to another round
(i.e. `queueMicrotask(() => <<updateState>>)`). This is an important
change to support migrating from the `queueMicrotask`-style deferred
updates, which are not entirely compatible with zoneless or event `NgZone` run
coalescing.
When using a microtask to update state after a render, it
doesn't work with coalescing because the render may not have happened
yet (coalescing and zoneless use `requestAnimationFrame` while the
default for `NgZone` is effectively a microtask-based change detection
scheduler). Second, when using a `microtask` _during_ change detection to defer
updates to the next cycle, this can cause updates to be split across
multiple frames with run coalescing and with zoneless (again, because of
`requestAnimationFrame`/`macrotask` change detection scheduling).
PR Close#54074
This change updates the `checkNoChanges` pass to only run once after
both view refresh and `afterRender` hooks execute rather than both
before and after the hooks. The original motivation was to specifically
ensure that the application was in a "clean state" before running the
`afterRender` hooks and ensure that `afterRender` hooks don't "fix"
`ExpressionChanged...` errors. This, however, adds to the complexity and
cost of running change detection in dev mode. Instead, the
`checkNoChanges` pass runs once we have done all render-related work and
want to ensure that the application state has been synced to the DOM
(without additional changes).
PR Close#54074
Errors during change detection are terminal and we do not generally
attempt to continue processing or recover after one occurs. This helps clean
up the `tick` implementation with respect to running `afterRender` hooks.
PR Close#54074
ISO 8601 defines
* Monday as the first day of the week.
* week 01 is the week with the first Thursday
Therefore:
Sunday Dec 31st 2023 is the last day of the last week of the year : W52 2023.
PR Close#53879
This commit updates the implementation of the `fetch` patch and additionally
patches `Response` methods which return promises. These are `arrayBuffer`, `blob`,
`formData`, `json` and `text`. This fixes the issue when zone becomes stable too early
before all of the `fetch` tasks complete. Given the following code:
```ts
appRef.isStable.subscribe(console.log);
fetch(...).then(response => response.json()).then(console.log);
```
The `isStable` observer would log `false, true, false, true`. This was happening because
`json()` was returning a native promise (and not a `ZoneAwarePromise`). But calling `then`
on the native promise returns a `ZoneAwarePromise` which notifies Angular about the task
being scheduled and forces to re-calculate the `isStable` state.
Issue: #50327
PR Close#50653
This commit updates the signature of the `ZoneGlobalConfigurations` interface and adds
missing `__Zone_ignore_on_properties` property, which may be setup to ignore specific `on`
properties from being patched.
PR Close#50737
`isNavigationCancelingError` & `isRedirectingNavigationCancelingError` had duplicate implementations. This commit also cleans-up those functions.
PR Close#53762
This commit adds hydration informations to the devtools.
* List of hydrated/hydrated components
* Shows hydration overlays
* Shows hydration errors for NG0500, 501 & 502
PR Close#53910
At the moment the extra import generation in local compilation mode fails if these extra imports produce a cycle. To handle this, the cycle handling strategy is updated for local compilation, and following the behaviour in the full compilation mode, the compiler does not generate extra import if it leads to cycle and instead leave things to the runtime.
PR Close#53543
With option `generateExtraImportsInLocalMode` set, in local mode the compiler generates extra imports for each component local dependencies. Here local dependencies means all component's dependencies within the same compilation unit.
To achieve this, the compiler performs a "local version" of its regular static analysis to find each component's deps, and these deps are used to generate extra side effect imports.
PR Close#53543
In this commit the resolve method for components is run fully when the option `generateExtraImportsInLocalMode` is set. This is because we need local component depedencies in order to generate extra imports causing by them. This requires cutting some resolve phase logics that are unnecessary in local mode, such as diagnostics.
PR Close#53543
When option `generateExtraImportsInLocalMode` is set, we need to compute component local depednecies in order to generate extra imports related to them. At the same time running the register phase in general is harmless in local compilation. So we run it anyway.
PR Close#53543
With option `generateExtraImportsInLocalMode` set in local compilation mode, the compiler generates extra side effect imports using this rule: any external module from which an identifier is imported into an NgModule will be added as side effect import to every file in the compilation unit. To illustrate this better assume the compilation unit has source files `a.ts` and `b.ts`, and:
```
// a.ts
import {SomeExternalStuff} from 'path/to/some_where';
import {SomeExternalStuff2} from 'path/to/some_where2';
...
@NgModule({imports: [SomeExternalStuff]})
```
then the extra import `import "path/to/some_where"` will be added to both `a.js` and `b.js`. Note that this is not the case for `import "path/to/some_where2"` though, since the symbol `SomeExternalStuff2` is not imported into any NgModule.
The math behind this mechanism is, in local compilation mode we cannot resolve component external dependencies fully. For example if a component in `a.ts` uses an external component defined in an external file `some_external_comp.ts` then we can generate the import to this file in `a.js`. Instead, we want to generate an import to a file that "gurantees" that `a.js` is placed after `some_external_comp.js` in the bundle. Now since the component in `some_external_comp.ts` is used in `a.ts`, then there must be a chain of imports starting from the NgModule that declares the component in `a.ts` to the component in `some_external_comp.ts`. This chain means some file in the same compilation unit as `a.ts` should import some external NgModule which includes `some_external_comp.ts` in its transitive closure and import it to some NgModule. So by adding this import to `a.js` we ensure that the bundling will have the right order.
PR Close#53543
As the first step, the import manager's `generateSideEffectImport` method is implemented to enable it to store info for side effect imports. Next, the helper `addImports` is modified to be able to generate correct statement for side effect imports.
These changes will be tested in the subsequent commits when these tools are used to generate an actual extra import for the generated file.
PR Close#53543
This commit includes a skeleton of how the tool `LocalCompilationExtraImportsTracker` is used in the overall compilation workflow end-to-end.
First of all, a new option `generateExtraImportsInLocalMode` is added, whose presence will make `LocalCompilationExtraImportsTracker` part of the compilation process. When this option is set an instance of `LocalCompilationExtraImportsTracker` is created within the NgCompiler. Then it is passed to the Ivy transformer and plumbed all the way down and the extra imports registered in it are added to the `ImportManager` instances before the imports are added from `ImportManager` to the generated file. This required adding a new method `generateSideEffectImport` to the `ImportManager`, which is an empty method and will be implemented in the subsequent commits.
This commit expected to make no change in the compilation behavior as the methods are not implemented yet.
PR Close#53543
The tracker is responsible for registering the extra imports during the analysis and resolve compiler phases, and later to be used by the transformer to get a list of extra imports to be generated for each source file.
This commit only contains the API, and the actual implementation for each method will be done in subsequent commits where an application of that method is available and so tests can be written for the implementation.
PR Close#53543
This commit updates the router integration tests to cover both the
classic History and the new Navigation API. There is more work to be
done here, but this commit works to prove the efficacy of the
`FakeNavigation` implementation.
PR Close#53799
When the zoneless scheduler is provided, we want to update the behavior
of `ComponentFixture` to address common issues and painpoints in testing.
Developers should never have to call `detectChanges` on a fixture
manually. Instead of calling `detectChanges` after performing an
action that updates state and requies a template refresh, developers
should wait for change detection to run because the update needs to also have
notified the scheduler. If this was not the case, the component would
not work correctly in the application. Calling `detectChanges` to force
an update could hide real bugs.
This commit also updates the zoneless tests to uses `ComponentFixture`
instead of manually attaching to the `ApplicationRef` and rewriting a
lot of the helpers (`getDebugNode`, `isStable` as a value, `whenStable` as a
Promise).
PR Close#54024
Clarify the range of TypeScript versions supported in Angular v15 and v16 upgrade guides. The previous documentation's phrasing led to potential misunderstandings, as it suggested broader compatibility than actually supported. This change prevents errors by explicitly stating the maximum TypeScript version for each Angular version, ensuring developers have clear guidance during upgrades.
PR Close#54131
Adds some logic to skip over `TestBed.configureTestingModule` calls where the `declarations` aren't initialized to an array. We can't migrate these cases, because test migrations don't have access to the Angular compiler. Previously the migration would throw a runtime error.
PR Close#54122
At the moment local compilation mode does not support custom decorators, and it leads to unhandled errors. In this change a compile time diagnostic is produced in local mode for custom decorators. This is a temporary solution since there are few custom decorators are in use in g3. Custom decorators will be eventually supported in local mode.
PR Close#53983
I've been working on framework parts and compiler since pre-Ivy, and
helped with Ivy, runtime and compiler. Adding myself as a reviewer to
ease future work and to help with review load.
PR Close#54053
This enables us to show overloads of methods in the API overview. This
is useful for e.g. showing the various signatures of the signal input
function, or for signal-based queris.
There seems to be some issues with the length of the `InputFunction`
overloads. There is some line wrapping that doesn't make it _super_
readable but this is an unrelated problem to this change, but rather
a question of UI / API representation in the angular.io site.
PR Close#54053
clang-format seems to have problems with the call signature for
`input.required`. This commit works around the formatting issues that
obfuscate the signature. Users will actually see similar output when
they are looking for the `input` function definition of `@angular/core`.
PR Close#54053
This adds initial support for extracting and rendering call and construct
signatures of classes, like within the new `InputFunction` for signal
inputs.
For now, signatures are a rare occasion and represented as class member
entries. In the future we might consider exposing this via its own entry
type, and field on the class/interface entry.
PR Close#54053
This fixes the definitions for signal-based inputs in the language
service and type checking symbol builder.
Signal inputs emit a slightly different output. The output works well
for comppletion and was designed to affect language service minimally.
Turns out there is a small adjustment needed for the definition symbols.
PR Close#54053
This commit separates `InputSignal` for input signals with transforms.
The reason being that most of the time, signal inputs are not using
transforms and the generics are rather confusing.
Especially for users with inferred types displayed in their IDEs, the
input signal types are seemingly complex, even if no transform is used.
For this reason, we are introducing a new type called
`InputSignalWithTransform`. This type will be used for inputs with
transforms, while non-transform inputs just use `InputSignal`.
A notable fact is that `InputSignal` extends `InputSignalWithTransform`,
with the "identity transform". i.e. there is no transform. This allows
us to share the code for input signals. In practice, we don't expect
users to pass around `InputSignal`'s anyway.
PR Close#54053
Fix case of not wanted internal properties displayed in the documentation by adding if blocks in the concerned templates. So if the option is marked as internal the template won't create an entry in the documentation table for the concerned property of method
Fixes#52018
PR Close#52020
docs: testing-components-basics.md and components-basics.md links to css selector documentation are dead
As MDN's documentation link to the "css selector" topic is dead, this commit makes the angular documentation use the new valid link.
PR Close#53586
The "Providing HttpClient through dependency injection" documentation now shows that in case of a standalone boostraped app, the provideHttpClient is to include in the app.config.ts file.
Also updated the http setup server communication example to align the new doc (adev) with the old one (aio).
PR Close#52806
Follow-up to #54002 that:
* Remove the `toString` implementation from the `primitives`.
* Guards the `toString` with `ngDevMode` and prints out the value.
PR Close#54079
Since signals are function, currently stringifying them reveals the implementation of the function. This can lead to confusion since it contains internal implementation details. These changes add static `toString` function to address the issue.
**Note:** it's tempting to have `toString` output the actual value of the signal, but that would encourage users not to call the function which will be problematic in the long run. That's why these changes are using a static string instead.
PR Close#54002
Currently, when using `provideAnimationsAsync`, Angular uses `AnimationRenderer`
as the renderer. When the root view is removed, the `AnimationRenderer` defers the actual
work to the `TransitionAnimationEngine` to do this, and the `TransitionAnimationEngine`
doesn't actually remove the DOM node, but just calls `markElementAsRemoved()`.
The actual DOM node is not removed until `TransitionAnimationEngine` "flushes".
Unfortunately, though, that "flush" will never happen, since the root view is being
destroyed and there will be no more flushes.
This commit adds `flush()` call when the root view is being destroyed.
PR Close#53033
During the template parsing stage two-way bindings are split up into a property and event binding. All the downstream code treats these binding the same as their one-way equivalents. For some future work we'll have to distinguish between the two so these changes update the `BoundElementProperty.type` and `ParsedEvent.type` to include a `TwoWay` type. All existing call-sites have been updated to treat `TwoWay` the same as `Property`/`Regular`, but more specialized logic will be added in the future.
PR Close#54065
Previously, defer deps fns names were only prefixed with the component name, meaning that distinct deps fns in the same component would produce a name collision. Now, we take into account the entire template function name when naming inner deps fns.
PR Close#54060
This refactoring expands the QueryList such that we can add onDirty
callback to be invoked when a given query gets marked as dirty during
view insertion / removal. This mechanism is needed for signal-based
queries.
PR Close#54017
This is a refactor commit that moves more query construction / refresh
logic from the body of instructions into dedicated functions. This is
in preparation for the signal-based query instructions.
PR Close#54017
In some bundling scenarios, there may be local references to `ngDevMode` that need to be kept in sync with the global variable. This becomes hard to impossible if the global is reassigned. This allows setting the global to an empty object instead of `true` and preserve identity during `initNgDevMode`.
PR Close#53862
The Template Pipeline is a brand new backend for the Angular compiler, replacing `TemplateDefinitionBuilder`. It generates the Ivy instructions corresponding to an input template (or host binding). The Template Pipeline has an all-new design based on an intermediate representation compiled over many phases, which will allow us to experiment with compiler changes more easily in the future.
With this commit, the template pipeline can now be enabled in any project via the `useTemplatePipeline` TSConfig option. However, it is still disabled by default.
PR Close#54057
In #53591, Andrew added local compliation support for defer blocks. However, this requires the ability to emit pre-generated static defer deps functions. We now also support that feature in Template Pipeline.
PR Close#54043
Similar to signal-based inputs, we support signal-based queries in JIT
by expecting a decorator to be added. This is a consequence of the
design, given that JIT requires query declaration information before
the class is initialized- but ironically there is no way to collect this
information without instantiating the class.
A JIT transform in the Angular CLI will automatically generate these
decorators for testing.
PR Close#54019
This commit introduces three additional diagnostics for queries:
- If a query (either using decorator or signal-based) is declared on a
static class member, a diagnostic is raised.
- If a signal-based query is mixed with a query decorator, a diagnostic
is raised. Similar to signal inputs.
- If a singal-based query is also declared in the directive/component
class decorator metadata, a diagnostic is raised.
PR Close#54019
Due to some refactorings, we were only checking the function name
and whether it originates from an import. We should also verify the
module. This seems like logic we lost in the refactorings.
PR Close#54019
Collapses multiple sibling query advance statements into single
query advance invocations. This will help reducing generated code
for directives/components with many queries.
PR Close#54019
Currently the ZoneJS typing tests executes outside of Bazel, as a legacy
artifact of the monorepo merging (as it seems - not ideal at all).
Looks like this test relies on its own node modules, that were NOT
locked using a yarn lock file. This commit adds one, and specifically
locks it to a `@types/node` version that does not include the most
recent patch release (which seemingly introduced a breaking change)
that causes issues with TypeScript's lib checking.
Whenever we perform lock file maintenance in the future, we have the
following options:
- Consider disabling lib checking via `skipLibCheck` for this test. This
may be acceptable.
- Continue locking the node version,
- Waiting for chokidar to comply with the new signature
- Waiting for the breaking change to be rolled back.
Culprit change:
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68300
PR Close#54048
While `Array.at` is technically supported in all browsers we officially
support, the change was needlessly breaking without any real benefit.
PR Close#54021
This changes include mentioning the experimental application builder migration and changes to the `outputPath` and `optimization` option.
PR Close#53949
Previously, if an ICU was inside a nested i18n root, it would use the nested root to calculate whether it should be applied. Now, we use the root i18n block.
PR Close#54026
This commit adds compliance tests to ensure that the generated output of
signal-based queries matches our expectation.
Note: collapsing query advance instructions is not implemented yet.
PR Close#53978
This commit ensures that libraries can use signal-based queries, and the
partial compilation output will capture their metadata.
The linker is updated to support parsing this.
Two notes:
1. Older linker versions are not capable of parsing this, so the minimum
version for signal-based queries is adjusted when such are used.
2. We only emit `isSignal` metadata for queries when signal queries are
used. This enables libraries to continue supporting older linker
versions, if signal-based queries are not used.
PR Close#53978
Adds a compiler integration test for recognizing signal-based queries,
and emitting the expected output. Concrete output will be verified via
the compliance tests.
PR Close#53978
Currently, Angular tries to recognize string locators/predicates for
queries at compile time, and attempts to split multi-selector predicates
into an array as generated output. This is a a performance optimization.
In practice, this works most of the time because the compiler can detect
string locactors/predicates through static analysis.
Though, there are cases where it's not possible. That is when advanced
constructs are used, identifier references etc. that ultimately evaluate
to a string. Currently this breaks with queries and also surfaces now
with signal-based queries.
PR Close#53978
This commit uses the initializer API recognition that we built for
signal-based inputs, and teaches the compiler to recognize class members
that refer to `viewChild`, `viewChildren`, `contentChild` or
`contentChildren`. Those will declare signal-based view or content queries.
PR Close#53978
This commit introduces the compiler output generation for signal-based
queries. Signal-based queries will have new creation-mode instructions
and update instructions to advance the current query indices in the
global shared context.
An output like the following is the expected output for signal-based
queries:
```
i0.ɵɵdefineComponent({
viewQuery: function App_Query(rf, ctx) {
if (rf & 1) {
i0.ɵɵviewQuery(ctx.d, _c0, 5);
i0.ɵɵviewQuerySignal(ctx.ds1, _c0, 5);
i0.ɵɵviewQuerySignal(ctx.ds2, _c0, 5);
}
if (rf & 2) {
let _t;
// only change-detected queries need explicit refresh
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.d = _t.first);
// we bump up current query index by 2 positions since there are 2 signal-based queries
i0.ɵɵqueryAdvance(2);
}
…
},
…
});
```
Note: For now, the collapsing of multiple advance instructions is not
implemented. This will be a follow-up.
Note 2: A couple of query helpers are now in their own file. This makes
it easier to focus on query-specific compiler code. The new function is
called `createQueryCreateCall`, which is a modified variant of the
existing function that previously only generated query parameters.
PR Close#53978
The new `input` API is recognized using class member initializers.
We want to support similar APIs for queries, using e.g. `viewChild`
or `viewChild.required`.
This commit extracts the input recognition API and makes it reusable,
so that the same logic can be used to detect queries on a class member.
Additional changes:
- replacing `coreModule` with the simpler `isCore` parameter. This is
more readable.
- support for detecting a list of API names on a single class member.
This allows us to detect possible query functions on the same class
member without having to check X times. We simply check for the
initializer API pattern and check if one API function name matches.
PR Close#53978
At the moment local compilation breaks for host directives because the current logic relies on global static analysis. This change creates a local version by cutting the diagnostics and copying the directive identifier as it is to the generated code without attempting to statically resolve it.
PR Close#53877
At the moment when unified host is selected (through option `_useHostForImportGeneration`) the compiler always generates alias reexports. Such reexports are mainly generated to satisfy strict dependency condition for generated files. Such condition is no longer the case for G3. At the same time, these alias reexports make it impossible to mix locally compiled targets with globally compiled targets. More precisely, a globally compiled target may not be able to consume a locally compiled target as its dependency since the former may import from the alias reexports which do not exist in the latter due to local compilation mode. So, to make global-local compilation interop possible, it is required to be able to turn off alias reexport generation.
PR Close#53937
Node removal is immediate and does not require change detection to run
when animations are not provided. This refactor makes the animation
engine notify the scheduler rather than doing it on all node removals.
PR Close#53857
The devtools now support signals.
Writable signals of primitives are editable.
Object Signal and other non-writable signals (like computed) are not editable.
Co-authored-by: Tomasz Ducin <tomasz.ducin@gmail.com>
PR Close#53269
This commit adds extra logic to produce a diagnostic in case `@Component.deferredImports` contain types from imports that also bring eager symbols. This would result in retaining a regular import and generating a dynamic import, which would not allow to defer-load dependencies.
PR Close#53899
The new type testing infrastructure was introduced for the input-as-signals
authoring functions. This commit modifies this infrastructure to make it more
generic and support queries-as-signals.
PR Close#53829
This commit update the logic to enable `register` and `resolve` phases for local compilation. Those phases will be useful for local compilation in certain cases (will be used in followup PRs).
PR Close#53901
These docs are out of date with how we currently build devtools in dev mode and as a browser extension. This commit brings these docs up to date.
PR Close#53948
This commit splits the query implementation and instructions
into a separate files. This is a pattern frequently used by
other functional areas of the framework and is a preparation for
introducing queries-as-signals where we are going to see more
instructions delegating to the same core functionality.
PR Close#53922
Currently when the extended type check fails due to an import reference
that cannot be generated, the fatal diagnostic is not caught and
not properly exposed as a `ts.Diagnostic` that can be gracefully
handled. This is inconsistent to non-extended type checking diagnostics.
This is problematic because Angular CLI applications currently fail in
obscure ways because:
- the CLI does not expect `getDiagnosticsForFile` to actually throw
runtime errors.
- the CLI does not seem to properly print these errors given the
parallel workers and build excection, and those errors are
especially hard to debug because there is no `stack` for
`FatalDiagnosticError`'s.
Example: `MyDir` is not exported and the type check block cannot reference it.
PR Close#53896
Prior to this commit, `TestBed` would require tests call `flushEffects`
or `fixture.detectChanges` in order to execute effects. In general, we
want to discourage authoring tests like this because it makes the timing
of change detection and effects differ from what happens in the
application. Instead, developers should perform actions and `await` (or
`flush`/`tick` when using `fakeAsync`) some `Promise` so that Angular
can react to the changes in the same way that it does in the
application.
Note that this still _allows_ developers to flush effects synchronously
with `flushEffects` and `detectChanges` but also enables the <action>,
`await` pattern described above.
PR Close#53843
This commit updates the logic of the `TemplateDefinitionBuilder` to support local compilation and generate a single dependency function for all explicitly deferred deps within a component.
PR Close#53591
This commit updates the `DeferredSymbolTracker` class to take info account the `onlyExplicitDeferDependencyImports` flag. The `DeferredSymbolTracker` class also exposes a new API to register import declarations as explicitly deferred, which will be used in followup commits.
PR Close#53591
This commit updates typechecker to store full Pipe metadata in internal data strctures, so that this information is available to more places in the code, which will be updated in a followup commit.
PR Close#53591
This commit updates a few places to extract the logic into a separate functions which will be reused in a few places in followup commits.
PR Close#53591
Enables signal inputs for existing Zone based components.
This is a next step we are taking to bring signal inputs earlier to the Angular community.
The goal is to enable early access for the ecosystem to signal inputs, while we are continuing
development of full signal components as outlined in the RFC. This will allow the ecosystem
to start integrating signals more deeply, prepare for future migrations, and improves code quality
and DX for existing components (especially for OnPush).
Based on our work on full signal components, we've gathered more information and learned
new things. We've improved the API by introducing a way to intuitively declare required inputs,
as well as improved the API around initial values. We even support non-primitive initial values
as the first argument to the `input` function now.
```ts
@Directive({..})
export class MyDir {
firstName = input<string>(); // string|undefined
lastName = input.required<string>(); // string
age = input(0); // number
```
PR Close#53872
This allows us to ensure signal inputs and a potential JIT transform
remain single file compilation compatible. The consequences are that
options need to be statically analyzable more strictly, compared to
loosened restrictions with static interpretation where e.g. `alias`
can be defined through a shared variable.
PR Close#53872
Adds infrastructure to run signal input tests with JIT (using the
transform) and AOT. Acceptance tests for signal inputs will run with
both variants. In the future we can consider expanding this
infrastructure for all of our acceptance tests, but that's a different
story.
PR Close#53808
Improves the recognition of the `input`/`input.required` functions to
not depend on external module resolution. This is useful for local
compilation and for transforms operating on a single file/ isolated
module.
PR Close#53808
Currently when someone declares a signal or non-signal input on a static
class member, the compiler will not yield any diagnostic. We can detect
these mistakes and report a diagnostic to help our users.
PR Close#53808
This commit addds two diagnostics for two scenarios where signal inputs
are declared incorrectly:
- a signal input is also annotated with `@Input` in the TypeScript
sources.
- a signal input is also declared in the `inputs` option of
`@Directive/`@Component`.
PR Close#53808
Given that the TCB output changes with signal inputs, and one of our
important considerations was auto-completion, we need some unit tests
that verify and guarantee proper completion with signal inputs being
bound in templates. This commit adds these.
PR Close#53808
This commit adds a transform for supporting input signals in JIT
environments. The transform will be wired up for Angular CLI
applications automatically. An integration test verifies that this fixes
unit testing with signal inputs.
The transform basically will take the signal input metadata and
transform it into `@Input` decorators that can provide static
information to the Angular JIT runtime when the directive/component
definition is compiled.
PR Close#53808
This commit does two things:
- exposes `addImports` so that it can be used by transforms that we are
adding to the compiler. e.g. the signal input to `@Input` transform.
- `updates `addImports` to support/use the transform context factory.
This will allow us to write proper transforms using `addImports`. Also
leverages this in the Ivy JS/DTS transforms.
PR Close#53808
Moves the signal input class member extraction logic into the dedicated
input function file. This makes the code for signal inputs more
self-contained.
This commit then re-exposes the function as part of `ngtsc/annotations`
so that it can be used later for a transform that will take the signal
input metadata and translate it into a `@Input` decorator. This allows
us to remove code duplication and guarantees consistency/correctness
PR Close#53808
We recently landed a commit to introduce support for generic type
checking of signal inputs. For that we had to implement logic that
will generate imports for inline type constructors. This required
changes to the context logic and `TypeCtorOp` file-level op.
This commit ensures that everything is working as expected, specifically
in cases where an inline type ctor is generated and imports would be
needed to unwrap the class members for `InputSignal`.
PR Close#53808
This commit creates a small http server Angular application playground
for playing with signal inputs. This is useful for development and also
validates some of the common input patterns.
PR Close#53808
Whenever a required input is accessed too early in a
directive/component, the signal input will throw an error.
This is necessary so that we can support required inputs
with intuitive typings that do not include `undefined` for
the short period of time where Angular is creating the component and
then assigning inputs later (Angular currently has no way of setting
inputs as part of the class creation when `new Dir()` happens)
PR Close#53808
Adds signal input compliance tests, ensuring linking works as expected,
partial output is generated properly, types are inferred properly, and
that the full, or linked output matches our expected runtime structure.
PR Close#53808
As we introduced the new partial output for signal inputs, we also need
to update the linker code to be able to parse this. This commit adds
this functionality.
In the follow-up commit, compliance tests for linking, partial output,
and full compilations are added.
PR Close#53808
As part of testing we did accidentally use `bitwiseAnd` for the input
flags, given we started without an extra flag for `HasTransform`.
This commit teaches the compiler to support emitting bitwise OR
and uses it when combining input flags, fully re-enabling transforms
for signal components after the new flag mechanism was introduced in
previous commits.
PR Close#53808
This commit changes the `HasTransform` flag to be only concerned with
decorator inputs. This allows us to automatically detect signal input
transforms without reliance on the flag, resulting in less complexity in
the compiler (as outlined in the design doc) and various other places,
while it also allows us to simplify JIT support for signal inputs
because there would be no need to capture the "hasTransform" state in
the decorator so that JIT can generate the according input flags.
`isSignal` will still persist as an input flag to allow for monomorphic
and highly efficient distinguishing at runtime, whether an input is
signal based or not. JIT transform will also need to propagate this
information to the runtime somehow.
PR Close#53808
We are adding internal support for declaring signal inputs via the
`@Input` decorator. This is needed for JIT unit testing, or JIT
applications.
In JIT, Angular is not able to recognize signal inputs due to the
lack of static reflection metadata. Decorators attach their information
on the class- without it needing to be instantiated. This allows Angular
to know inputs when preparing/generating the directive definition. With
signal inputs this is not possible- so we need a way to tell Angular
about inputs for JIT applications. We've decided that this is not
something users should have to deal with, so a transform will be added
in a follow-up that will automatically derive/and add the decorators
for signal inputs when requested in JIT environments.
PR Close#53808
In some cases, the input files for a partial output generation
compliance tests may be invalid and lead to compilation errors.
The golden partial would be silently generated with the remaining
test cases. Instead of hiding errors, we will now print these and
cause the script to fail properly.
Note that the error logging is pretty minimalistic, but it's sufficient.
PR Close#53808
The linker AST is abstracted to be agnostic of the underlying
implementation AST. i.e. TS AST or Babel AST.
This abstraction also intends to provide some type-safety-ness to
parsing of various partial declarations. This commit improves type
safety further by fixing that `AstValue'`s were not checked for
assignability of `T`- potentially hiding issues/unaccounted values.
Additionally, we fix that `getObject()` does not properly narrow
union types to actual object literals. This happend because e.g. arrays
are of type `object`. We can improve type safety here. Using `Record`
did not help as an array would still assign to that.
PR Close#53808
This commit moves the implementation of the change detection scheduler
used for testing to angular/core along with a (private export) provider function.
Note: Naming of the provider function is absolutely not final (and not
public API). I would prefer one that did not mention "zones"
but the easiest thing for now is to have a "Zone" and "Zoneless" naming
scheme.
PR Close#53579
This commit removes the testability features that are internal only.
This simplifies the implementation of testability which will need
updates to support zoneless. Those updates will be easier to manage if
the Testability implementation is simpler.
While protractor is indeed officially EOL, we will still need to do some
updates to support teams migrating to zoneless that have protractor
tests.
As far as protractor's own use of `whenStable`, it does not read the
internal only methods either:
https://github.com/angular/protractor/blob/master/lib/clientsidescripts.js
Anything else depending on these values are not following the defined public API
contract.
PR Close#53767
Make Zone.js compatible with moduleDetection:force by turning files that
are currently incompatible from scripts into modules using an empty
export statement.
PR Close#53445
This commit updates the router integration tests to cover both the
classic History and the new Navigation API. There is more work to be
done here, but this commit works to prove the efficacy of the
`FakeNavigation` implementation.
PR Close#53799
We generate `advance` instructions before most update instructions and the majority of `advance` calls are advancing by one. We can save some bytes for the most common case by omitting the parameter for `advance(1)` altogether.
PR Close#53845
This PR provides strict type definition for the window.ng object used
for both console debugging and devtools. `GlobalDevModeUtils` now
gathers all type information about all methods exposed on window.ng.
PR Close#53439
This addresses the offset issue caused when a switch case was empty with no spaces or children being affected by the markers that were added, but not accounted for in offset. The markers are not needed for empty content and can be safely removed in this case.
fixes: #53779
PR Close#53839
This commit ensures that change detection runs when an `LView` is
removed. Change detection is required because DOM nodes aren't actually
removed until the animation engine flushes and this doesn't happen until
the end of `detectChangesInternal` (`rendererFactory.end`).
PR Close#53812
The `afterRender` hooks currently run after `ApplicationRef.tick` but
also run after any call to `ChangeDetectorRef.detectChanges`. This is
problematic because code which uses `afterRender` cannot expect the
component it's registered from to be rendered when the callback
executes. If there is a call to `ChangeDetectorRef.detectChanges` before
the global change detection, that will cause the hooks to run earlier
than expected.
This behavior is somewhat of a blocker for the zoneless project. There
is plenty of application code that do things like `setTimeout(() =>
doSomethingThatExpectsComponentToBeRendered())`, `NgZone.onStable(() =>
...)` or `ApplicationRef.onStable...`. `ApplicationRef.onStable` is a
should likely work similarly, but all of these are really wanting an API
that is `afterRender` with the requirement that the hook runs after the
global render, not an individual CDRef instance.
This change updates the `afterRender` hooks to only run when
`ApplicationRef.tick` happens.
fixes#52429fixes#53232
PR Close#52455
This is a follow up to https://github.com/angular/angular/commit/5c1d4410298e20cb03d7a1ddf7931538b6a181b4
which added the `info` property to navigation requests. `RouterLink` now
supports passing that transient navigation info to the navigation
request.
This info object can be anything and doesn't have to be serializable.
One use-case might be for passing the element that was clicked. This
might be useful for something like view transitions. In the "animating
with javascript" example from the blog (https://stackblitz.com/edit/stackblitz-starters-cklnkm)
those links could have done this instead of needing to create a separate
directive that tracks clicks.
PR Close#53784
This commit removes a hack that deletes `Event` from the global context
when using domino. Instead, it sets the global event to domino's
implementation of `Event`.
PR Close#53659
Instead of computing the bit input flags at compile-time and inling
the final bit flag number, we will use the `InputFlags` enum directly.
This is a little more code in the compiler side, but will allow us to
have better debuggable development code, and also prevents problems
where runtime flag bitmasks differ from the compiler flag bitmasks.
This is in practice a noop for optimized applications as the enum values
would be inlined anyway. This matches existing compiler emit for e.g.
change detection strategy, or view encapsulation enums.
PR Close#53571
The linker compliance tests were disabled with a Babel update and
nobody realized for quite a while, via
https://github.com/angular/angular/pull/49914.
As we've came across this lost coverage, which also is quite
impactful as all libraries depend on linked output- I've took initiative
to debug the root cause as there was no follow-up.
https://github.com/angular/angular/issues/51647.
It turned out to be a highly complex issue that is non-trivial to fix,
but at least we should try to resurrect the significant portion of test
coverage by still running the linker tests- avoiding regressions, or
unexpected issues (like with defer being developed). We can work on
re-enabling and fixing source-maps separately.
Tracked via https://github.com/angular/angular/issues/51647.
PR Close#53571
The linker compliance tests did not run for a while. There were a couple
of new tests that were not passing as this wasn't flagged on CI. This commit fixes this.
Fortunately there was no problematic code that did indicate issues with linking.
In the follow-up commit, we fix the compliance test infrastructure to
re-enable linker testing..
One clear issue is still that the defer blocks are not handled properly
in linked output- hence making defer not actually "lazy" for compiled
libraries. This needs to be handled separately by the framework team.
PR Close#53571
This commit adds a final test for input signals, integrating all major
parts:
* type-checking
* compiler detection
* compiler emit
* API signature tests
PR Close#53571
Adds tests that allow us to ensure that the `input` API works as
expected and that resulting return types match our expectations- without
silently regressing in the future, or missing potential edge-cases.
Testing signatures is hard because of covariance and contravariance,
especially when it comes to the different semantics of `ReadT` and
`WriteT` of input signals. We enable reliable testing by validating the
`d.ts` of the "fake directive class". This ensures clear results,
compared to relying on e.g. type assertions that might
accidentally/silently pass due to covariance/contravariance or
biavariance in the type system.
PR Close#53571
Consider a snippet like:
```
const x = directiveDef.inputs || EMPTY_OBJ
```
this currently results in `x` being inferred as just `{}`- ending up
turning of potential future assignment checks. This surfaced in the
`DirectiveDefinition` -> `DirectiveDef` conversion.
Note: This has the effect that assigning `EMPTY_OBJ` to a field of
anything would _always_ pass. It's questionable if this rather impacts
type-safety in a more negative way. There seem to be trade-offs in both
ways... Maybe worth considering just using `{}` directly as fallbacks in
some places, and treating this as an unique symbol?!
https://www.typescriptlang.org/play?#code/MYewdgzgLgBAHgLhmApgNxQJxgXhgbwF8YBDCZdLAbgCgbRJYAHJfGmDmAGxC6SkwBXFABoahAD6CwAExQAzAJaoZuZIK5dS5EmACeteuGgxBapjAkT4VIA
PR Close#53571
This commit introduces a new enum for capturing additional metadata
about inputs. Called `InputFlags`. These will be built up at compile
time and then propagated into the runtime logic, in a way that does
not require additional lookup dictionaries data structures, or
additional memory allocations for "common inputs" that do not have any flags.
The flags will incorporate information on whether an input is signal
based. This can then be used to avoid megamorphic accesses when such
input is set- as we'd not need to check the input field value. This also
avoids cases where an input signal may be used as initial value for an
input (as we'd not incorrectly detect the input as a signal input then).
The new metadata emit will be useful for incorporating additional
metadata for inputs, such as whether they are required etc (although
required inputs are a build-time only construct right now- but this is a
good illustration of why input flags can be useful). An alternative
could have been to have an additional boolean entry for signal inputs,
but allocating a number with more flexible input flags seems more future
proof and more reasonable andreadable.
More information on the megamorphic access when updating an input
signal
https://docs.google.com/document/d/1FpnFruviKb6BFTQfMAP2AMEqEB0FI7z-3mT_qm7lzX8/edit.
PR Close#53571
Currently when a base class defines an input with a transform, derived
classes re-defining the input via `@Input`, or `inputs: [<..>]`, end up
inherting the transform due to a bug in the inherit definitions feature.
This commit fixes this. We verified in the Google codebase that this is
an unlikely occurrence and it's trivial to fix on user side by removing
the re-declaration/override, or explictly adding the necessary
transform.
Conceptually, the behavior was quite inconsistent as everything else of
inputs was overridden as expected. i.e. alias, required state etc. The
exception were input transforms. This commit fixes this.
PR Close#53571
At this point, we have the following pieces in place:
* the input signature is implemented
* the compiler properly parses and recognizes signal inputs
* the compiler supports type-checking of signal inputs
* input signal metadata is passed to partial output
This commit adds a naive runtime solution to distinguishing between
signal inputs and decorator inputs when the `property` instruction
invokes. This is not ideal and non-performant as we introduce additional
megamorphic reads for every property instruction invocation, or if we'd
use `instanceof`, introducing a hard dependency on `InputSignal` and
risking potentially slower detection.
This code exists purely for testing, to enable playing with input
signals in the playground. In a future commit, we will pass around the
input signal metadata at runtime and can perform highly optimized checks
to distinguish between signal or non-signal inputs- when assigning
values.
More information: https://docs.google.com/document/d/1FpnFruviKb6BFTQfMAP2AMEqEB0FI7z-3mT_qm7lzX8/edit#heading=h.oloxympe902x
PR Close#53571
This commit introduces the runtime `InputSignal` implementation.
Input initializers using `input` or `input.required` will result in
an instance of `InputSignal` to be created.
An input signal extends the signal primtive, with a couple of small
differences:
- it's a readonly signal. There is no public `set` or `update`.
- equality is non-configurable. As per CD semantics, the value is
guaranteed to be different when the `property` instruction attempts
to update an input signal.
- we support a `transform` function, that allows transforming input
values. The transform is called whenever the input is set. An
alternative could have been to follow computed-semantics and call the
transform upon accessing, if dirty.
In the future, we might change this to extend the computed reactive
node, so that we can support computed inputs that do not rely on
continious bound value assignments. See signal based components RFC.
PR Close#53571
For the implementation of input signals, we want to extend the signal
primitive. The basic methods exposed here are not suitable as we'd like
to store additional metadata on the reactive node, and also have a
custom getter (for required inputs and throwing).
To enable this, one small piece was missing. This commit exposes it and
also improves type safety, now that `SignalNode` is typed properly after
the previous commit.
PR Close#53571
The `SignalNode` interface, describing the reactive node for a `Signal`,
seemingly exposes the `SIGNAL` symbol as a class member. This is not
true as the `SIGNAL` reactive node only exists on the getter function,
as a way to retrieve the signal underlying reactive node.
This commit fixes this, enabling improved type-safety later, in a
follow-up commit where `SIGNAL_NODE` can now be typed to match the
`SignalNode` interface (unlike now where it's typed as just `object`).
PR Close#53571
This commit adds additional type-check transform tests for signal
inputs. These tests verify some of the problems with covariance,
contravariance and bivariance that we were suspecting to be problematic
if we would assign `InputSignal`'s directly to the type constructors.
PR Close#53571
This flag is not actually read anywhere. It doesn't even have any effect
on the traversal algorithm because embedded views are always refreshed
in `Global` traversal mode during the refresh of their parent views.
PR Close#53715
The `ComponentFixture` code needlessly dances around the `ngZone` being
`null` when the `ComponentFixtureNoNgZone` option is set. Instead, it
can use the `NoopNgZone` to get the same effect without needing to have
checks all over the place for its presence.
PR Close#53670
In #52931, Kristiyan fixed a TemplateDefinitionBuilder bug in which derived alias variables in for loops (`$even`, `$first`, etc) were referring to the wrong level of nested `@for` block. (These variables are unique because they become inlined expressions, and are not "real" context variables.) He fixed this by appending level information to the generated alias name.
Template Pipeline actually suffered from the same bug. We fix it in a very similar way -- in particular, whenever these derived context variables are used, we make them depend on versions of `$index` and `$count` that have been suffixed with the xref of the enclosing repeater.
I have added a few more pipeline goldens, because we are not quite as clever as TDB about only generating the duplicate suffixed index and count variables when inside nested loops. This is fine, since in the long run, we want to refactor it more fundamentally.
I have also added a TODO to fix this more rigorously. In particular, it would be nice if we had proper support for shadowed variables, as well as unlimited levels of variables depending on one another.
PR Close#53662
Template pipeline previously mangled CSS property names like
`--camelCase` when used in host style bindings. Note: It still *does*
mangle these names in static style attrs, both in host bindings and on
elements. This is clearly wrong, but is consistent with what TDB does
today.
PR Close#53665
Currently compiling input transform in local mode breaks, since compiler does static analysis for the transform function, and this cannot be done in local mode if the function is imported from another compilation unit. In this fix the static analysis is ditched in local mode.
PR Close#53645
Fixes that the `BrowserViewportScroller` was throwing an error during server-side rendering because it was accessing `window` directly. Also removes some assertions that aren't necessary anymore.
Fixes#53682.
PR Close#53683
The diagnostic was catching the following case:
```ts
name = signal('Angular');
```
but not the following ones:
```ts
name = signal('Angular').asReadonly();
name = computed(() => 'Angular');
name!: Signal<string>
```
This was not catched in the tests because the type of `Signal` is different than the one actually used in core.
It turns out the real type forces the diagnostic to check both the `symbol.tsType.symbol` and the `symbol.tsType.aliasSymbol`.
PR Close#53585
It's possible for attributes to have a namespace, we need to handle this
possiblity for both attribute instructions and attributes extracted to
the consts array.
PR Close#53646
`effect` was expecting an `ErrorHandler` in its constructor which can lead to a circular DI error if an effect is used inside a custom `ErrorHandler`. These changes inject the `ErrorHandler` only when reporting errors.
Fixes#52680.
PR Close#53713
Use of the `SpyLocation` is problematic because it prevents location
APIs from reaching the platform level (`PlatformLocation`) and
`PathLocationStrategy`. This makes it difficult to test interactions
with those providers, including the ability to use the `Navigation` API,
which will live at the platform level.
PR Close#53640
In order to provide a reasonable experience for Angular without Zones,
we need a mechanism to run change detection when we receive a change
notification. There are several existing APIs today that serve as the
change notification: `ChangeDetectorRef.markForCheck`, signal updates,
event listeners (since they mark the view dirty), and attaching a view to
either the `ApplicationRef` or `ChangeDetectorRef`. These operations
are now paired with a notification to the change detection scheduler.
The concrete implementation for this scheduler is still being designed.
However, this gives us a starting point to partner with teams to
experiment with what that might look like.
PR Close#53499
The way we were handling ICU placeholders was not compatible with using
interpolations on attributes of elements inside the ICU. This change
refactors the handling of ICU placeholders and unifies the way
expression and tag placeholders work inside ICUs.
The new approach modifies the ingest logic to add the placeholder on to
the TextOp rather than the TextInterpolationOp. This is because, in
ICUs, we may need multiple i18n expressions created from the
interpolation expressions to roll up into the same placeholder. ICUs
essentially do the interpolation at compile time, combining the static
strings with special placeholder strings that represent the expression
values.
PR Close#53643
Consider a case when an explicit `this` read is inside a template with a context that also provides the variable name being read:
```
<ng-template let-a>{{this.a}}</ng-template>
```
Clearly, `this.a` should refer to the class property `a`. However, in today's Angular, `this.a` will refer to `let-a` on the template context.
Amazingly, both TemplateDefinitionBuilder and the Typecheck block have the same bug, and are consistent with each other! This is because `ImplicitReceiver` extends `ThisReceiver` in the parser AST, which is an insane gotcha.
In this commit, I patch the template pipeline to emulate this behavior as well.
To actually fix this nastiness, we have to:
- Update `ingest.ts` in the Template Pipeline (see the corresponding comment)
- Check `type_check_block.ts` in the Typecheck block code (see the corresponding comment)
- Turn off legacy TemplateDefinitionBuilder
- Fix g3, and release in a major version
PR Close#53594
`ng-content` elements, and thus their corresponding projection instructions, can have many attributes on them. Some of these attributes may result in special behavior. For example, `ngProjectAs` and `i18n-foo` both result in special const collection, into the approprate BindingKind slot in the const array. Additionally, `i18n-foo` needs to recieve all the additional i18n attribute processing.
We solve this by subjecting `ng-content` attributes to all the same pipeline logic that applies to attributes on elements, and then allow the element const collection phase to collect them.
PR Close#53594
For regular templates, any listener will have its name const collected into the bindings section of the element consts.
In contrast, host bindings omit listener names from their hostAttrs. This is a strange and inconsistent behavior, so we hide it behind a compatiblity mode flag.
PR Close#53594
We has some special behavior for naming identifiers in Template Pipline, for the sake of compatibility with TDB's source maps tests. However, this has the potential to cause a variable name collision in a particular special case (when the identifier is `ctx`). We add a special check for this, and also tuck all the backwards-compatible naming code inside a compatibility block.
PR Close#53594
This commit updates the `ApplicationRef.isStable` implementation to use
a single `Observable` to manage the state. This simplifies the mental
model quite a bit and removes the need for rx operators like
`distinctUntilChanged` and `combineLatest`.
PR Close#53576
The formatting that would preserve attribute indents completely missed attributes that start on new lines rather than the same line as the opening element.
PR Close#53636
In cases where CommonModule was unsafe to remove but other imports were present, the symbol check would be skipped. This should run for all the possibly removed symbols for safety.
PR Close#53637
When an application does not use zones, it does not need a default value
for the zone stableness token. This will allow zoneless applications to
tree-shake a lot of rxjs operators out of `ApplicationRef`.
Note that at the moment, `provideZoneChangeDetection` is included in all
applications as well as the `TestBed` environment. It is not currently
possible to remove the zone stable code as a result. This will be
possible only when we make zones an opt-in rather than opt-out.
PR Close#53505
Adds the tentatively planned release weeks for 17.1-18.0 - please note
that these might change (and 17.3 might or might not be released).
PR Close#53549
The InitialRenderPendingTasks currently attempts to only contribute to
ApplicationRef stableness one time to support SSR. This isn't actually
how the switchMap works in reality. This commit updates
the isStable observable to be more clear that it's always a combination
of the zone stableness and pending tasks.
In addition, this commit renames the service to just be PendingTasks
because it doesn't directly relate to rendering. While the purpose is
to track things that might cause rendering to happen, we don't know if the
tasks will affect rendering at all.
PR Close#53534
During formatting, attribute indentation is changed, and that can affect internationalized strings. This fix detects if an attribute value string is left open and skips formatting on those lines.
PR Close#53625
It's possible for the user to create a host attrbiute binding with a
name that makes it _look_ like a class binding `{['class.foo']: ''}`, we
were previously treating these as actual class property bindings. This
change fixes the logic so that only true property bindings cam be
converted to class property bindings.
Note: A user who added an attribute like the above almost certainly
intended to create an actual class property binding. It would be nice if
we could add a diagnostic to warn them about this.
PR Close#53626
Further refine the template pipeline's behavior w.r.t. duplicate values
in the consts array to better align its behavior with TDB. In particular
this means allowing duplicate values for classes and styles.
PR Close#53596
Adds a test for handling of duplicate bindings. Fow now we replicate the
TDB behavior in template pipeline, which is: For style and class text
attributes, only keep the last one. For all other text attributes, add
all of the values to the consts array.
PR Close#53596
The for loop tracking function doesn't allow references to local template variables, aside from `$index` and the item which are passed in as parameters. We enforce this by rewriting all variable references to the components scope.
The problem is that the logic that rewrites the references first walks the view tree and then checks if the variable is `$index` or the item. This is problematic in nested for loops, because it'll find the `$index` of the parent.
These changes resolve the issue by checking for `$index` and the item first.
Fixes#53600.
PR Close#53604
Core bundles were retaining the `Version` class and `VERSION` constant, because we stamp out the current version in the DOM. This shouldn't be necessary, because any usage of `0.0.0-PLACEHOLDER` will be replaced with the current version at build time. These changes remove the reference so it can be tree shaken away.
PR Close#53598
Changes template pipeline to be less aggressive in const collecting
attrs, to match the behavior of template definition builder. There is
nothing wrong with the more aggressive const collection, and in fact it
would be good to re-enable it later, but for now this makes it easier to
transition from TDB to template pipeline.
Also adds a test to verify that sensitive iframe attributes are properly
validated.
PR Close#53580
The version of rxjs used to build the repository has been updated to v7.
This required only minimal changes to the code. Most of which were type
related only due to more strict types in v7. The behavior in those cases
was left intact. The most common type related change was to handle the
possibility of `undefined` with `toPromise` which was always possible with
v6 but the types did not reflect the runtime behavior. The one change that
was not type related was to provide a parameter value to the `defaultIfEmpty`
operator. It no longer defaults to a value of `null` if no default is provided.
To provide the same behavior the value of `null` is now passed to the operator.
PR Close#53500
fetch support AbortSignal, zone.js schedules a macroTask when fetch()
```
fetch(..., {signal: abortSignal});
```
we should also be able to cancel fetch with `zoneTask.cancel` call.
So this commit create an internal AbortSignal to handle
`zoneTask.cancel()` call and also delegate the `options.signal` from the
user code.
PR Close#49595
Close#49591
```
const ac = new AbortController();
addEventListener(eventName, handler, {signal: ac.signal);`
ac.abort();
```
Currently `zone.js` doesn't support the `signal` option, this PR allows
the user to use AbortContoller to remove the event listener.
PR Close#49595
This addresses the case where modules are being used and declared in the same file as the component. It is unclear whether its safe to remove the common module in this case, so best to leave it.
PR Close#53575
TemplateDefinitionBuilder is apparently more careful about when it attempts to split namespaces in attribute values. However, we are doing this on style attributes, which might start with a single `:`. Rather than refactor our logic to only try to split namespaces in some cases, we can just add an option to make namespace splitting fail gracefully. We only use this option for attributes, not elements.
Note also: the compiled code for this, while "correct" is absolutely insane. Maybe we should consider fixing this, as a matter of principle.
PR Close#53574
Some elements may have multiple bindings with the same name. We should accept and emit them all, as long as they have different kinds.
Co-authored-by: Miles Malerba <mmalerba@users.noreply.github.com>
PR Close#53574
The template pipeline was previously not reserving a variable slot for the result of the `deferWhen` instruction, which caused the `defer when` feature to crash at runtime.
PR Close#53574
When an element is self-closing, it will cause an `element` instruction to be emitted (instead of `elementStart`/`elementEnd`). In that case, we should use map whole source span for the instruction, not just the starting span.
PR Close#53574
The template pipeline was producing slightly different names than TemplateDefinitionBuilder for defer deps functions. I have added a workaround in the name of backwards compatibility, to avoid suffixing the const pool function names.
PR Close#53574
Previously when we found an ICU that was the only translatable content
in its i18n block, we assigned the block's i18n context to the ICU.
However, we neglected to set the contextKind to inidcate that the
context was associated with an ICU. As of this change we now set the
correct contextKind.
This change also refactors the context creation to explicitly separate
creation of contexts for attributes, root i18n blocks, child i18n
blocks, and ICUs. This allows us to more easily ensure that contexts are
shared appropriately between i18n blocks and ICUs.
Finally, this change also refactors the i18n message extraction pahse to
simplify how contexts are converted to i18n messages. This
simplification should make it easier to merge i18n contexts and i18n
messages into a single op in a future refactor.
PR Close#53557
When a view has the `Dirty` flag and is reattached, we should ensure that it is
reached and refreshed during the next change detection run from above.
In addition, when a view is created and attached, we should ensure that it is reached
and refreshed during change detection. This can happen if the view is
created and attached outside a change run or when it is created and
attached after its insertion view was already checked. In both cases, we
should ensure that the view is reached and refreshed during either the
current change detection or the next one (if change detection is not
already running).
We can achieve this by creating all views with the `Dirty` flag set.
However, this does happen to be a breaking change in some scenarios.
The one identified internally was actually depending on change detection
_not_ running immediately because it relied on an input value that was
set using `ngModel`. Because `ngModel` sets its value in a `Promise`, it
is not available until the _next_ change detection cycle. Ensuring
created views run in the current change change detection will result in
different behavior in this case.
Making option the default is the solution to #52928. That will have to
wait for a major version.
PR Close#53022
Whenever an input of a directive changes, the semantic symbol should
reflect this change for the type check API. This is important because
signal inputs require special output in the type checking blocks- hence
we need to ensure that such type checking blocks are re-generated
properly.
Test verify that incremental type-checking builds work as expected now.
PR Close#53521
Whenever a signal input is captured in a type check block, we will
insert an import. This will change the import graph so that the full
TypeScript program cannot be structurally re-used.
We can fix this trivially by ensuring the import graph remains stable,
by always generating an import to e.g. `@angular/core`. This fixes the
issue nicely for type-check block files. A test verifies this.
For inline code, such as TCB inline or the type constructors inline,
this fix is not applicable because we would change user-input source files,
adding new edges that would not exist for subsequent builds- causing the
program to be not re-used completely. One idea was to rely on the
existing edge that can be assumed to exist for directive code files.
This is true technically, but in practice TS does not deduplicate
imports- so our new namespace import when referencing our symbols will
invalidate the re-use. We will address this in a follow-up. There are a
couple of options, such as working with the TS team, updating the
existing edge, or inlining our helpers as well.
PR Close#53521
This commit adds the last remaining piece for signal input
type-checking. Bound values to signal inputs are already checked
properly at this point, but inference of generic directive/component
types through their inputs is not implemented.
This commit fixes this. To achieve this, there are a couple of potential
solutions. The generics of a directive are inferred based on input
value expressions using a so-called type constructor. The constructor
looks something like this:
```
const _ctor = <T>(v: Pick<Dir<T>, 'input1', 'input2'>) => Dir<T>;
_ctor({input1: expr1, input2: expr2});
```
This works very well for non-signal inputs where the class member is
directly holding the input values. For signal inputs, this does NOT
work because the class member will actually hold the `InputSignal`
instance. There are a couple of solutions to this:
1. Calling `_ctor` with an `InputSignal<typeof value>`
2. Converting the `_ctor` input signal fields to their write types
(unwrapping the input signals).
We've decided to go with the second option as TypeScript is very
sensitive with assignments and its checks. i.e. co-variance,
contravariance or bivariance. Semantically it makes more sense to unwrap
the input signal "write type" directly and "assign to it". This is safer
and conceptually also easier to follow. A type constructor continues to
only receive the "expresison values". This simplifies code as well.
It's worth noting that the unwrapping as per option 2 also comes at a
cost. We need to be able to generate imports in type constructors. This
was not possible until the previous commit because inline type constructors
did not have an associated type-check block `Environment` and we were
missing access to expression translation and correct import generation.
Overall, solution 2 is now implemented as works as expected. This commit
adds additional unit tests to ensure this.
PR Close#53521
For signal inputs we are looking at generating additional code inside
type constructors. This code is planned to reference an external type
from `@angular/core` to unwrap `InputSignal`'s class fields.
The existing `Environment` class contains helpers for emitting such
references / and translating them from the output AST. We extract
this logic into a superclass for only emitting references. A similar
type already existed to avoid circular dependencies- but now we have
actual use-cases to populate this as a base class.
This allows us to create more-suitable minimal emit environments
when we e.g. generate type constructors inline- which are not
part of any type check block. The existing `Environment` class is scoped
to type check blocks and therefore was not suitable.
PR Close#53521
Signal inputs do not need coercion members for their transforms. That is
because the `InputSignal` type- which is accessible in the class member-
already holds the type of potential "write values". This eliminates the
need for coercion members which were simply used to somehow capture this
write type (especially when libraries are consumed and only `.d.ts` is
available).
We can simplify this, and also significantlky loosen restrictions
of transform functions- given that we can fully rely on TypeScript for
inferring the type. There is no requirement in being able to
"transplant" the type into different places- hence also allowing
supporting transform functions with generics, or overloads.
In a follow-up commit, once more parts are place, there will be some
compliance tests to ensure these new "loosend restrictions".
PR Close#53521
This commit ensures that the type-check diagnostic testing
infrastructure is prepared to validate signal inputs. i.e. providing the
necessary "mocks" in the fake "d.ts" of `@angular/core`.
The commit then sets up a Golang-style table driven testing environment
that allows us to validate/verify signal input type-checking in a
readable way.
With this infrastructure set up, this commit defines an initial set
of unit tests for type checking of input signals.
PR Close#53521
This commit introduces the initial type-checking for signal inputs.
To enable type-checking od signal inputs, there are a couple of tricks
needed. It's not trivial as it would look like at first glance.
Initial attempts could have been to generate additional statements in
type-checking blocks for signal inputs to simply call a method like
`InputSignal#applyNewValue`. This would seem natural, as it would match
what will happen at runtime, but this would break the language-service
auto completion in a highly subtle way. Consider the case where multiple
directives match the same input. Consider the directives have some
overlap in accepted input values, but they also have distinct diverging
values, like:
```ts
class DirA {
value = input<'apple'|'shared'>();
}
class DirB {
value = input<'orange'|'shared'>();
}
```
In such cases, auto completion for the binding expression should suggest
the following values: `apple`, `shared`, `orange` and `undefined`.
The language service achieves this by getting completions in the
type-check block where the user expression would live. This BREAKS if
we'd have multiple places where the expression from the user is used.
Two different places, or more, surface additional problems with
diagnostic collection. Previously diagnostics would surface the union
type of allowed values, but with multiple places, we'd have to work with
potentially 1+ diagnostics. This is non-ideal.
Another important consideration is test coverage. It might sound
problematic to consider the existing test infrastructure as relevant,
but in practice, we have thousands of diagnostic type check block tests
that would greatly benefit if the general emit structure would still
match conceptually. This is another bonus argument on why changing the
way inputs are applied is probably an option we should consider as a
last resort.
Ultimately, there is a good solution where we unwrap directive signal
inputs, based on metadata, and access a brand type field on the
`InputSignal`. This ensures auto-completion continues to work as is, and
also the structure of type check blocks doesn't change conceptually. In
future commits we also need to handle type-inference for generic signal
inputs.
Note: Another alternative considered, in terms of using metadata or not.
We could have type helpers to unwrap signal inputs using type helpers
like: `T extends InputSignal<any, WriteT> ? WriteT : T`. This would
allow us to drop the input signal metadata dependency, but in reality,
this has a few issues:
- users might have `@Input`'s passing around `InputSignal`'s. This is
unlikely, but shows that the solution would not be fully correct.
- we need the metadata regardless, as we plan on accessing it at runtime
as well, to distinguish between signal inputs and normal inputs when
applying new values. This was not clear when this option was
considered initially.
PR Close#53521
This commit captures the metadata on whether an input is signal based or
not, in the `.d.ts` of directives and components. This exposes this
information to consumers of the directives. This is needed because
libraries may use signal inputs, and we need to know whether bound
inputs to this library are signal-based or not- so that we can generate
proper type-checking code (account for `InputSignal` or not).
Additionally, this commit introduces a new structure for the partial
compilation output of directive inputs. With the current emit, inputs
are captured in a data structure that is equivalent to the internal data
structure passed to `defineDirective` (the full compilation output).
This worked fine as we only captured a few strings, but in ends up
being a bad practice because partial compilation output should NOT
capture internal data structures that might be specific to a certian
Angular core version. Instead, we introduce a new "future proof"
structure that:
- can hold additional metadata in backwards-compatible ways, like
`isSignal` or `isRequired`.
- can be parsed trivially using the `AstHost` for the linker, instead of
having to unwrap/parse an array structure.
The new structure is only emitted when we discover that some inputs are
signal based (or ultimately end up configuring input flags). This is
done for backwards compatibility, so that libraries without signal
inputs remain compatible with older linker versions. In the future,
this might be the only emit.
Compliance tests for this follow in future commits, when the linker
portion is also in place. This commit specialices on the code
generation. With the linker, and compliance test infrastructure fixed
(that is broken right now), we can test the full integration.
PR Close#53521
When working on integrating a new metadata field for inputs, I realized
there are quite a lot of duplications of interfaces. Turns out, the
facade input map type can be replaced in favor of just
`R3DirectiveInput`- even improving type safety-ness of e.g. the wrapped
node expressions of transform functions.
PR Close#53521
This commit defines the initial metadata for inputs passed around in
the compiler-cli. Inputs will now capture additional metadata on whether
they are signal-based or not. This is stored on a per-input basis as
a Zone component may contain both, signal inputs or `@Input` inputs.
The metadata is later used for type-checking, for partial output
generation, or full compilation output generation.
PR Close#53521
This commit introduces a function for declaring inputs in
components. The function is called `input`. It comes in two flavors:
- `input` for optional inputs with initial values
- `input.required` for required inputs
Inputs are declared as class members, like with `@Input`- except that
the class field will no longer hold the input value directly. Angular
takes control over the input field and exposes the input value as a
signal. The runtime implementation will follow in future commits.
This commit simply introduces:
- initial compiler detection to recognize such inputs in classes
- the initial signature of `input` and `input.required`.
Note: the defer size test is flawed and there is no minification- hence
this commit also needs to incorporate the new dependency graph changes.
PR Close#53521
The behavior of `ApplicationRef.isStable` changed in 16.1 due to
https://github.com/angular/angular/commit/28c68f709cdc930e12bac51a266e7bf790656034.
This change added a `share` to the `isStable` observable, which prevents
additional subscribers from getting a value until a new one emits. One
solution to the problem would be `shareReplay(1)`. However, that would
increase the bundle size since we do not use `shareReplay` elsewhere.
Instead, we don't even really need to share the observable.
The `Observable` available in `ApplicationRef.isStable` before the above commit
was the zone stable observable, without a `share`. The new behavior adds
only an additional observable to the stream, `hasPendingTasks` (a `BehaviorSubject`).
The observables in this stream are not expensive to subscribe to. The
only one with side effects is the `isStable` (because it subscribes to
onStable), but that one already has the `share` operator on it.
Omitting the `share` in `ApplicationRef` also means that applications on `zoneless` will not
have to pay the cost of the operator when we make zones optional because
the zone stable observable is the only place we use it.
PR Close#53541
Internationalization is whitespace sensitive. This change updates the formatting code to process for i18n attributes and prevent reformatting those sections of the template.
PR Close#53538
Using http://a as the base URL returns / instead of the actual base path when using the file:// protocol. Using document.baseURI addresses this.
Fixes#53546
PR Close#53547
This commit updates the name of the 'performance.mark'
counter used to track feature usage. It now matches
the name agreed upon by W3C for this use case:
https://github.com/w3c/user-timing/pull/108
PR Close#53542
This fix handles the common case where an ngswitch might have invalid syntax post migration. This is likely due to using elements other than case or default underneath the ngswitchcase. This will fail out of the migration for that file when these cases are detected with a useful console message.
fixes: #53234
PR Close#53530
In the case that a template has some sort of structural issue prior to migrating, like a tag that is not properly closed resulting in invalid HTML post migration, this will attempt to parse the html after migrating and revert to the original structure. An error during migration will be reported out instead.
PR Close#53530
`o.WrappedNodeExpr` can show up in some cases, when a host binding's value is inside a TS expression.
It's an open question whether we will need to support all of the TS expression types as a result.
PR Close#53478
For some reason, the parser reuses the same field to store the animation phase and the event target. We were incorrectly interpreting the presence of any value on that field as an animation phase, leading us to incorrectly emit synthetic listener instructions for listeners on events with targets. This bug is now fixes.
PR Close#53478
`$any` should be interpreted as a cast, not as a context read of a variable called `$any`. This already worked in template compilations, but the relevant phase was not enabled for host bindings.
PR Close#53478
Fixes that the compiler was throwing an error if an ambient type is used inside of an input `transform` function. The problem was that the reference emitter was trying to write a reference to the ambient type's source file which isn't necessary.
Fixes#51424.
PR Close#51474
Prior to this commit when a route is not matched and the application was running in production mode an `[Error]: NG04002` was logged in the console. This however, is not actionable when the application is running on the server where there can be multiple pages being rendered at the same time.
Now we change this to also log the route example: `[Error]: NG04002: 'products/Jeep'`.
Closes#53522
PR Close#53523
The ops for the implicit variables in `@for` loops (e.g. `$index`) are marked as being mandatory which means that they're generated even if they aren't used. These changes make them optional so they're only added when necessary.
PR Close#53515
Adds support for sanitizing host bindings. Since the tag name of the
element the host binding is being set on isn't always known, we have to
consider multiple possible security contexts.
This commit also adds additional tests to help verify correct behavior
of the sanitization logic for different edge cases.
PR Close#53513
The formatting logic would eliminate all newlines in updated template code. This adds start and end markers for tracking when the formatter is in a block of template code that changed or not. It should leave behind any newlines that are outside of a migrated section.
fixes: #53494
PR Close#53508
When migrating a component and the associated external template, if errors occur, the component should not remove the common module imports. This fix should allow the application to still build in that instance.
PR Close#53502
The `nodejs-websocket` package has been replace with the `ws` package.
Both provide `WebSocket` server support and both of zero transitive
dependencies. However, the `ws` package has ~78 million weekly downloads
and was last updated this week (as of the writing of this commit) while
the `nodejs-websocket` package has ~7,600 weekly downloads and was last
update 5 years ago. The `ws` package is also already a transitive dependency
of the repository which allows for a reduction in the total dependency count
for the repository.
PR Close#53482
Previously we generated an intermediate expression which was later
converted into a symbol import expression for the sanitizer function.
This commit simplifies the behavior by just generating the symbol import
from the beginning
PR Close#53473
Use the DomElementSchemaRegistry to determine the correct security
context for static attributes, and pass it along during ingestion. Then
during the resolve sanitizers phase, use the security context to
determine if a trusted value function is needed
PR Close#53473
The changes Observable (impl: EventEmitter) on the QueryList is initalized
lazy - it is created only if someone calls a geter to get a hand on its
instance. But the destroy method was calling this getter thus creating
a new Observable even if no one subscribed to it.
This commit changes the destroy logic to skip creation of an EventEmitter
if it wasn't initialized.
PR Close#53498
The `graceful-fs` package itself is unused within the repository code
and can be removed. The resolution workaround is no longer required
for any direct or transitive dependency based on the issue referenced
via #28213.
PR Close#53487
Two TypeScript type definition packages are currently unused within the
repository and can be removed. These were most likely leftover from previous
usage of the related packages.
Packages removed:
* `@types/uuid`
* `@types/cli-progress`
PR Close#53475
The `base64-js` package was only used in tests that were run only on
Node.js. On Node.js, `Buffer` is available which can natively perform
base64 conversion. By using `Buffer in these Node.js only tests, the
`base64-js` package can be removed from the repository.
PR Close#53464
Consider the case:
```
<button *ngIf="true" [@anim]="field"></button>
```
Only the inner `button` should recieve a `property` instruction for the animation binding. We were previously emitting one for the implicit `ng-template` as well, and collecting it into the consts for the `ng-template`. Both of these issues are now fixed.
PR Close#53457
The behavior of explicit bindings on `ng-template`s was untested, and we differed from `TemplateDefinitionBuilder` significantly. We now have much more similar behavior, although not 100% identical.
For example, consider this templarte:
```
<ng-template l="l1" [p]="p1" [attr.a]="a1" [class.c]="c1"></ng-template>
```
It's not clear what a class binding on an `ng-template` would actually do. Nonetheless, it's well-defined behavior in TemplateDefinitionBuilder, which emits `property` instructions for all three bindings, and people actually do this in google3.
Note that some of these bindings don't really make much sense, but we have to support them for compatibility purposes.
See comments for an in-depth explanation of all the logic.
Also, add a test to exercise the problematic case.
PR Close#53457
It turns out that `BindingFlags.BindingTargetsTemplate` is actally a redundant property! It will be true in either of the following cases:
1. The template is a normal non-structural `ng-template`. We already know this from `TemplateKind`.
2. The binding came from `templateAttrs` (instead of `attrs`). We have this information in `BindingFlags.IsStructuralTemplateAttribute`.
Therefore, I can just eliminate `BindingFlags.BindingTargetsTemplate`. There's no reason to keep `BindingFlags` around for a single value, so I convert `BindingFlags.IsStructuralTemplateAttribute` to a boolean parameter (with the eventual goal of eliminating it entirely).
Additionally, because element binding ingestion now calls `ir.createBindingOp` inline, it was difficult to compare it to template binding ingestion, which uses the `createTemplateBinding` helper. I have changed the parameter order of `createTemplateBinding` to closely mimic `ir.createBindingOp`. This will both make the code easier to read, and allow me to easily replace one with the other in the future.
Lastly: the template binding ingestion function is the site of much of the binding ingestion complexity. Add an explanatory function comment.
PR Close#53457
Previously, we had `ingestBindings` and `ingestBinding`, which required tons of cases to support both elements and templates.
Now, we have two separate functions, `ingestElementBindings` and `ingestTemplateBindings`.
Thanks to the previous refactoring work, `ingestBinding` is now extremely compact. In fact, it's so compact that, in the elements case, it can just be inlined! Therefore, element binding ingestion is now quite easy to read.
The template case continues to be pretty gnarly, although I have already removed some code. In subsequent commits, we will simplify it even further.
PR Close#53457
Currently Template Pipeline's ingest phase is very complex, especially when it comes to ingesting bindings.
In this commit, we make some superficial simplifications, in preparation for a larger refactoring. For example, we pull out common code such as `convertAstWithInterpolation` and the `i18n.Message` checks. This enormously shrinks the main binding ingestion functions.
In addition, we reorder the binding kind and flags code above `ingestBindings`, so that `ingestBindings` and `ingestBinding` can be viewed together.
PR Close#53457
The Template Pipeline has had a number of tricky bugs involving bindings on structural elements.
Consider this template:
```
<div *ngIf="true" [class.bar]="field"></div>
```
We were incorrectly emitting `ɵɵclassProp` on *both* the template's view, and the inner view. The solution is to just emit an extracted attribute on the enclosing template, so it still shows up in the const array, but does not affect the update block.
We will refactor binding ingestion soon, but this commit improves our correctness before any big refactor.
PR Close#53457
The `multimatch` package was only used in the saucelabs test bundling
script to filter out spec files that should be ignored during saucelabs
testing. This functionality can be replaced with `fast-glob` package's
`ignore` option. This removes the need for the `multimatch` package within
the repository.
PR Close#53463
In the original `Promise` impelmentation, zone.js follow the spec from
https://promisesaplus.com/#point-51.
```
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
p1 === p2; // false
```
in this case, `p2` should be the same status with `p1` but they are
still different instances.
And for some edge case.
```
class MyPromise extends Promise {
constructor(sub) {
super((res) => res(null));
this.sub = sub;
}
then(onFufilled, onRejected) {
this.sub.then(onFufilled, onRejected);
}
}
const p1 = new Promise(setTimeout(res), 100);
const myP = new MyPromise(p1);
const r = await myP;
r === 1; // false
```
So in the above code, `myP` is not the same instance with `p1`,
and since `myP` is resolved in constructor, so `await myP` will
just pass without waiting for `p1`.
And in the current `tc39` spec here https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-promise-resolve
`Promise.resolve(subP)` should return `subP`.
```
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
p1 === p2; // true
```
So the above `MyPromise` can wait for the `p1` correctly.
PR Close#53423
This change replaces the implementation of the multi-map used to store
detached views while reconciling lists. The new implementation optimizes
memory allocation for such map and avoid arrays allocation when there are
no duplicated keys.
PR Close#52245
The repository currently has two globbing packages. To minimize the number of packages in
the framework repository, the uses of the `glob` package are being converted
to `fast-glob` which is used by the tooling repository. The change is mostly mechanical
and in this change the build and test scripts are converted.
PR Close#53397
These patches are no longer necessary with the current state of the
type packages and the code within the repository. The types are now
included in the already required babel.d.ts file for the relevant
babel packages (currently: `@babel/core` and `@babel/generator`).
PR Close#53441
The `@babel/core` package provides the functionality of multiple other babel packages
without the need to directly depend or import the other babel packages. Since the
`@babel/core` package is already used and imported in the locations that previously
used the other babel packages, an overall reduction in both imports and dependencies
is possible. Six babel related packages were able to be removed from the root `package.json`
and one (also present in the aforementioned six) was removed as a dependency from the
`@angular/localize` package. Unfortunately, the functionality used from the `@babel/generator`
package is not provided by `@babel/core` and is still present. Further refactoring may
allow its removal as well in the future.
The following packages were removed:
* @babel/parser
* @babel/template
* @babel/traverse
* @babel/types
* @types/babel__template
* @types/babel__traverse
PR Close#53441
Phases that walk through the views by following template and repeater
ops need to remember to check the empty view as well for repeaters. This
commit adds fixes for phases that were missing it, or comments
explaining why its not handled.
PR Close#53440
@for does not use actual TemplateOps, but instead has a similar
RepeaterCreateOp. This commit adds support for this op to the relevant
i18n phases.
PR Close#53440
When using ternaries or other expressions in bound if / else cases, it is possible that line breaks could end up affecting template replacement.
fixes: #53428
PR Close#53435
This separates application and platform code into even more files. This now removes
the ciruclar dependency between scheduling and application ref.
PR Close#53371
To support the development of component specific HMR capabilities, the build/serve
tooling may need to directly process styles to match the view encapsulation
expectations of individual components. To allow for this scenario and to avoid tooling
to need to re-implement the emulated encapsulation logic, an private API is now
available in the `@angular/compiler` package named `encapsulateStyle` that converts
a stylesheet content string to an encapsulated form. This function is not considered
part of the public API nor does it have any of its respective support or versioning guarantees.
PR Close#53363
This test actually passes, template pipeline just orders the translated
messages and consts array differently. Since the order isn't important,
we just fork off an alternate golden file for template pipeline.
PR Close#53459
I discovered this failure while looking at presubmit results. We appear to still have ordering issues, when more update ops are present.
PR Close#53405
While running a g3 presubmit, I discovered two related novel failure modes:
1. Simple case: this new test uses an `ngFor` structural directive, which binds a context variable. That variable is immediately used in an attribute binding. It looks like we generate an extra attribute instruction, which might result in an invalid property read at runtime.
2. Complex case: this is another attribute binding, this time on a structural element, inside of an `ng-template`. Not sure what's going on here.
PR Close#53405
Previously, binding ops only knew whether they applied to a structural template (and even this was actually very misleading!).
Now, binding ops have full information about what kind of template they apply to, if any (e.g. plain template, structural template, etc). Additionally, each binding knows whether it `IsStructuralTemplateAttribute`, which is a property of the binding rather than the template target.
In the future, we should refactor this to unify the various flags that can describe binding types, as well as the flags that describe template targets, into a single and comprehensive field on binding ops.
PR Close#53405
Previously, we created i18n contexts for i18n attributes in ingest. This turned out to be the wrong approach, because we don't always want to produce i18n messages for all i18n attributes! In fact, several kinds of i18n attributes on elements with structural directives should not produce their own messages.
This commit also contains related refactors to fix one such structural directives test.
PR Close#53405
When a binding is present on an element with a structural directive, that binding is parsed onto *both* the synthetic `ng-template`, as well as the inner element. However, we do not want to create different i18n messages for both bindings; we only want to generate a new i18n message for the inner, "real" element.
PR Close#53405
Listener instructions should not be inside the i18n block. In order to avoid this, we ingest bindings on an element before starting the i18n block.
We previously missed this case because almost all bindings result in *update* instructions, which don't need to be ordered relative to i18nStart/i18nEnd create instructions. However, listeners are the only kind of binding that gets ingested into the create block.
PR Close#53405
Previously, our i18n slot moving process was buggy. Specifically, it was not resilient to cases in which a create op consumed a slot, but no update ops depended on that slot.
The new algorithm fixes this issue, and is also easier to understand.
PR Close#53405
The PR https://github.com/angular/angular/pull/52465 introduced short-circuit for
the signal equality invocation - with the reasoning that the equality function
should never return false for arguments with the same references. In practice it
turned out that it is rather surprising and the subsequent PR
https://github.com/angular/angular/pull/52532 added a warning when the short-circuit
was taking priority over the equality function.
Still, the presence of the short-circuit prevents people from mutating objects in
place and based on https://github.com/angular/angular/issues/52735 this is a common
and desired scenario. This change removes the short-circuit altogether and thus
fixes the mentioned issue.
We do recognize that removing short-circuit exposes developers to the potentially
surprising logic where mutated in-place change won't be propagated throug the
reactivity graph (due to the deault equality function). But we assume that this might
be less surprising / more desirable as compared to the short-circuit logic.
Fixes#52735
PR Close#53446
This change fixes and issue where the expectation was that change
detection always goes through `detectChangesInView`. In reality,
`detectChangesInternal` directly calls `refreshView`
and refreshes a view directly without checking if it was dirty (to my discontent).
This update changes the implementation of `detectChangesInternal` to
actually be "detect changes" not "force refresh of root view and detect
changes". In addition, it adds the refresh flag to APIs that were
previously calling `detectChangesInternal` so we get the same behavior
as before (host view is forced to refresh).
Note that the use of `RefreshView` instead of `Dirty` is _intentional_
here. The `RefreshView` flag is cleared before refreshing the view while
the `Dirty` flag is cleared at the very end. Using the `Dirty` flag
could have consequences because it is a more long-lasting change to the
view flags. Because `detectChangesInView` will immediately clear the
`RefreshView` flag, this change is much more limited and does not
result in a different set of flags during the view refresh.
PR Close#53021
The component fixture dependencies have to be passed in manually. This
is a bit annoying to manage as we expand which dependencies are needed.
Instead, we can run the constructor in the TestBed injection context and
move the dependencies into the component fixture code, as is done with
other constructors in Angular.
PR Close#53400
These patches are no longer necessary with the current state of the
type packages and the code within the repository. The types are now
included in the already required babel.d.ts file for the relevant
babel packages (currently: `@babel/core` and `@babel/generator`).
PR Close#53374
The `@babel/core` package provides the functionality of multiple other babel packages
without the need to directly depend or import the other babel packages. Since the
`@babel/core` package is already used and imported in the locations that previously
used the other babel packages, an overall reduction in both imports and dependencies
is possible. Six babel related packages were able to be removed from the root `package.json`
and one (also present in the aforementioned six) was removed as a dependency from the
`@angular/localize` package. Unfortunately, the functionality used from the `@babel/generator`
package is not provided by `@babel/core` and is still present. Further refactoring may
allow its removal as well in the future.
The following packages were removed:
* @babel/parser
* @babel/template
* @babel/traverse
* @babel/types
* @types/babel__template
* @types/babel__traverse
PR Close#53374
This commit adds a property to the navigation options to allow
developers to provide transient navigation info that is available for
the duration of the navigation. This information can be retrieved at any
time with `Router.getCurrentNavigation()!.extras.info`. Previously,
developers were forced to either create a service to hold information
like this or put it on the `state` object, which gets persisted to the
session history.
This feature was partially motivated by the [Navigation API](https://github.com/WICG/navigation-api#example-using-info)
and would be something we would want/need to have feature parity if/when the
Router supports managing navigations with that instead of `History`.
PR Close#53303
I18n expressions logically have both a target and an owner:
- For i18n text expressions, the owner is the i18nStart instruction. The target is initially the same, but later moves to be the last slot consumer in the i18n block.
- For i18n attribute expressions, the owner is the I18nAttributes config instruction, whereas the target is the ElementCreate that hosts the attribute.
This refactor makes the code clearer in quite a few plases.
Additionally, we now perform a lot of the i18n processing earlier. For example, re-targeting and re-ordering of i18n expressions happens *before* apply instructions are generated. As a result, the re-ordering logic is a lot simpler.
These changes also have consequences on i18n const collection, along with a couple other minor changes.
PR Close#53376
Using more unique characters makes it easier to parse placeholders that may contain JS logic, making it more flexible.
fixes: #53386fixes: #53385fixes: #53384
PR Close#53394
These changes add an option to the `extendedDiagnostics` field that allows the check from #53190 to be disabled. This is a follow-up based on a recent discussion.
PR Close#53311
If a template is passed in as an input, the ng-template will not exist in the same component template. This will leave a template placeholder behind. This fix ensures that template placeholder gets turned into a template outlet.
fixes: #53361
PR Close#53368
When there are ng-templates nested inside other ng-templates, the replacement and removal of the templates gets disrupted. Re-processing the templates in the file along the way resolves this issue.
fixes: #53362
PR Close#53368
Add support for i18n attributes:
- Generate i18n contexts from i18n attributes, and extract the eventual messages into the constant pool.
- Emit I18nAttributes config instructions when needed.
- Use the generated i18n variable in the appropriate places, including extracted attribute instructions, as well as I18nAttributes config arrays.
PR Close#53341
Enabling `strict` is part of an effort to improve the quality of the devtools code base.
One of the direct side effect is to enable `noImplicitAny`, `strictPropertyInitialization` and `strictBindCallApply`.
This commit also replaces `fullTemplateTypeCheck` with `stringTemplates`.
PR Close#53340
With the deprecation of the configurable errorHandler in the Router, there is a missing
use-case to prevent the navigation promise from rejecting on an error. This rejection
results in unhandled promise rejections. This commit allows developers to instruct
the router to instead resolve the navigation promise with 'false', which matches
the behavior of other failed navigations.
Resolving the Promise would be the ideal default behavior. It is rare
that any code handles the navigation Promise at all and even more rare
that the Promise rejection is caught. Updating the default value for
this option should be considered for an upcoming major version.
fixes#48902
PR Close#48910
Currently we generate the following TCB for a `@for` loop:
```ts
// @for (item of items; track item) {...}
for (const item of this.items) {
var _t1 = item;
// Do things with `_t1`
}
```
This is problematic if the item name is the same as a global variable (e.g. `document`), because when the TCB has references to that variable (e.g. `document.createElement`), it'll find the loop initializer instead of the global variable.
These changes fix the issue by generating the following instead:
```ts
for (const _t1 of this.items) {
// Do things with `_t1`
}
```
Fixes#53293.
PR Close#53319
In certain cases Angular hydration logic can not rely on the order in which elements are present in a template (for example, in content-projection use-cases) and there is a need to serialize a path from one node to another, so that hydration can locate an element on a page. The logic attempts to use an immediate parent element as an anchor and compute the path from it. If it fails - the path is computed starting from the <body> (this is a fallback).
This commit updates the logic to walk up the parents tree if an immediate parent (from a template) is disconnected from the DOM. This helps to shorten the lookup path and make it more stable.
PR Close#53317
In some injectors, there are LOTS of providers, making it slightly inconvenient to search for a certain one. This commit introduces a search-by-token for providers of a specific injector.
PR Close#53313
Currently, the link to an error guide is only included into an error message in dev mode. This change makes the `Find more at https://angular.io/errors/NG0XYZ` appear in the error message even in prod mode. Note: the rest of the error message is still tree-shaken away in prod mode (as it happens today).
PR Close#53324
This setting was added to prevent comment duplication, since the TS AST printer includes prior line comments as part of a given line with no way to really avoid that.
However in component imports, it is not safe to remove comments as they could be load bearing for some.
PR Close#53350
This commit fixes a memory leak where signal consumers would not be cleaned up for
descendant views when a view is destroyed, because the cleanup logic was only invoked
for the view that is itself being destroyed.
PR Close#53351
Previously we recorded separate param values for a strucural directive
and the element tag it goes on. We then later attempted to combine those
into a single value. However in some cases this merging logic matched
the directive with the wrong tag.
This change implements an alternate approach where we match the
directive to its element tag from the start, while we're traversing the
ops. This should be a more robust solution.
PR Close#53327
We previously failed to populate the attributes property on projection
ops, this commit populates it and later strips out the "select"
attribute.
PR Close#53327
Previously we failed to reset the sub-template index counter when we
exited a root block. This caused following sibling blocks to start
counting at the wrong index.
PR Close#53327
It is possible for ICUs to be nested inside other ICUs. This change
adjusts our ingestion logic to create extra interpolation ops for the
nested ICUs during ingestion.
PR Close#53300
We previously had an assertion that every placeholder in the i18n AST
had a corresponding param in the output. However, there are some cases
such as interpolations nested inside ICUs where this assertion is not
true. This change simply removes the asserion.
PR Close#53300
ICUs may share a placeholder, and in that case they need special
post-processing. This change adds logic to cover this possibility. In
particular, we set the param to a special placeholder value and then
pass an array containing the sub-message variables as a post-processing
param.
PR Close#53300
When we re-assign the slot dependencies for the i18nExprs, we should
move them down below the other ops that target their same slot. This
keeps the behavior consistent with TDB
PR Close#53300
This commit fixes an issue where swapping hydrated views was not possible in the new control flow repeater. The problem was caused by the fact that an internal representation of a view had no indication that hydration is completed and further detaching/attaching should work in a regular (non-hydration) mode. This commit adds a logic that resets a pointer to a dehydrated content and we use this as an indication that the view is swtiched to a regular mode.
Resolves#53163.
PR Close#53274
When the AOT compiler creates a delegated host for a provided TypeScript CompilerHost,
it delegates functionality back to the original via a series of internal method delegations.
However, unlike other members of the CompilerHost, `jsDocParsingMode` is not a method
and cannot be delegated in this way. Attempting to call bind on the property will result
in a runtime error. Instead, `jsDocParsingMode` is now delegated via get/set accessors.
Additionally, the override of `getSourceFile` now has an updated type signature to reflect
the additional of the `jsDocParsingMode` option for the method.
This is a followup to #53126 which updates the other DelegatingCompilerHost.
PR Close#53292
Prior to this fix, the expectation that anytime then was used, else would always be present. That is not a valid assumption.
fixes: #53287
PR Close#53297
i18n template removal expected no other attributes to be present, but if a bound ngIf is present with aliases and i18n, that is more than what was expected. Now it should safely remove them appropriately.
fixes: #53289
PR Close#53299
This commit fixes an issue with hydration, which happens when a content is projected in a certain way, leaving host elements non-projected, but the child content projected.
The fix is to detect such situations and add extra annotations to help runtime logic locate those elements at the right locations.
Resolves#53276.
PR Close#53304
This commit fixes an issue where having an expression with nullish coalescing in styling host bindings leads to JS errors due to the fact that a declaration for a temporary variable was not included into the generated code.
Resolves#53295.
PR Close#53305
Added 2 tiny improvements:
- instead of "Symbol()", "Symbol(DESCRIPTION)" is displayed
- ECMAScript Maps are distinguished
Additionally:
- PropTypes has been moved to a separate file
- Simple unit tests covering each PropType except for PropType.Unknown
PR Close#53167
This commit adds new sections to the devtools aio page for the new DI debugging features in Angular DevTools:
1. Directive dependency inspection
2. Injector hierarchy visualization
PR Close#52290
The examples of how to provide the http fetch, cookie/header name and disabling XSRF protection now show the app.config.ts file instead of the main.ts file since the cli boostrap application with this architecture.
PR Close#52848
The regexp for then and else did not ignore alphanumeric characters prior to the then and else. So if a string contained then, for example Authentication, it would incorrectly match as a then clause.
fixes: #53252
PR Close#53257
This commit updates the logic to handle hydration of multiple nodes projected in a single slot. Currently, in case component nodes are content-projected and their order is changed during the projection, hydration can not find the correct element. With this fix, extra annotation info would be included for such nodes and hydration logic at runtime will use it to locate the right element.
Resolves#53246.
PR Close#53270
When ng-templates are removed, an extra space was being added when it was unnecessary. This resulted in malformed html if there was no space afterwards.
fixes: #53248
PR Close#53255
This should address cases when using ng-containers with ngSwitchCase / ngSwitchDefault
and migrating them safely when they are empty.
fixes: #53235
PR Close#53237
As part of this fix, I realized that child i18n blocks don't need their
own context. Instead, we can just add their params directly to the
context for their root block, and forgo the step of merging the contexts.
PR Close#53209
Fixes a bug in the sub-template index logic that caused it to reuse
indices that had already been assigned to more deeply nested templates
PR Close#53209
Structural directives inside an i18n block previously resulted in a
"list" param value (represented as "[...|...]"). This commit adds a
special case to the template pipeline to collapse the list into a single
compound value like TemplateDefinitionBuilder does.
PR Close#53209
ICU sub-messages should be recorded as belonging to the message for the
root i18n block they are part of. This ensures that they still get
emitted even if they are nested in a child template.
PR Close#53209
This commit updates the logic to preserve previous value of cached TView before applying overrides. This helps ensure that the next tests that uses the same component has correct provider info.
PR Close#52918
This addresses an issue where multiple ng-templates are present with i18n attributes. The offsets would be incorrectly accounted for when being replaced with an ng-container.
fixes: #53149
PR Close#53212
Common module removal would not happen when a component used a templateUrl due to the checks being in separate files. This change passes the removal analysis back to the original source file to safely remove CommonModule.
PR Close#53076
This is a follow-up to the fix from #52414. It adds a diagnostic that will tell users when a control flow is preventing its direct descendants from being projected into a specific component slot.
PR Close#53190
The control flow projection diagnostic will mention `ng-container` as a workaround for projection multiple nodes. These changes add a couple of tests to ensure that the approach works.
PR Close#53190
These changes expose the `ngContentSelectors` and `preserveWhitespaces` metadata to the TCB so they can be used in the next commit to implement a new diagnostic.
PR Close#53190
When doing directive matching in the compiler, we need to be able to create a selector from an AST node. We already have the utility, but these changes simplify the public API and expose it so it can be used in `compiler-cli`.
PR Close#53190
This commit updates the platform-server tests to use the new application builder, with this change we also have to remove the sizechecks since esbuild will do code motion and split the code into multiple chunks example `chunk-QUKLKPSE.js`.
PR Close#53205
When the AOT compiler creates a delegated host for a provided TypeScript CompilerHost,
it delegates functionality back to the original via a series of internal method delegations.
However, unlike other members of the CompilerHost, `jsDocParsingMode` is not a method
and cannot be delegated in this way. Attempting to call bind on the property will result
in a runtime error. Instead, `jsDocParsingMode` is now delegated via get/set accessors.
Additionally, the override of `getSourceFile` now has an updated type signature to reflect
the additional of the `jsDocParsingMode` option for the method.
PR Close#53126
Currently the way we extract the pathname of a URL is by creating an anchor node, assigning the URL to its `href` and reading the `pathname`. This is inefficient and it triggers an internal security check that doesn't allow the `href` attribute to be set which ends up blocking https://github.com/angular/components/pull/28155.
These changes switch to using the browser's built-in URL parsing instead.
PR Close#53097
Adds support for inheriting host directives from the parent class. This is consistent with how we inherit other features like host bindings.
Fixes#51203.
PR Close#52992
Related to #52928 but `updateAncestorTraversalFlagsOnAttach` is called
on view insertion and _should_ have made that work for views dirty from
signals but it wasn't updated to read the `dirty` flag when we changed
it from sharing the `RefreshView` flag.
For #52928, we've traditionally worked under the assumption that this is working
as expected. The created view is `CheckAlways`. There is a question of whether we
should automatically mark things for check when the attached view has
the `Dirty` flag and/or has the `FirstLViewPass` flag set (or other
flags that indicate it definitely needs to be prefreshed).
PR Close#53001
When blocks were initially implemented, they were represented as containers in the i18n AST. This is problematic, because block affect the structure of the message.
These changes introduce a new `BlockPlaceholder` AST node and integrate it into the i18n pipeline. With the new node blocks are represented with the `START_BLOCK_<name>` and `CLOSE_BLOCK_<name>` placeholders.
PR Close#52958
This commit adds an `error` listener to image elements and removes both
`load` and `error` listeners once the image loads or fails to load. The `load`
listener would never have been removed if the image failed to load.
PR Close#52990
This commit updates the implementation of the `ImagePerformanceWarning` and
runs the image scan even if the page has already been loaded. The `window.load`
event would never fire if the page has already been loaded; that's why we're
checking for the document's ready state.
PR Close#52991
This separates out the NgSwitch migration pass from the NgSwitchCase / Default pass, which makes nested switch migrations work.
fixes: #53009
PR Close#53010
With if then else use cases, we now properly account for the length
of the original element's contents when tracking new offsets.
fixes: #52927
PR Close#53006
Currently in the angular.dev documentation, afterNextRender function
take directly the phase as a second parameter which is not correct.
According to the api of this hook, the second parameter is an object
which contains the phase. This PR update the part of the documentation
PR Close#53025
This commit cleans up the `loadingPromise` when no `dependenciesFn` is defined,
as it's already cleaned up after the resolution of `Promise.allSettled`. This
occurs with `prefetch on` triggers, such as when `triggerResourceLoading` is called
from `ɵɵdeferPrefetchOnImmediate`, where there are no dependencies to load. The
`loadingPromise` should still be cleaned up because it typically involves the
`ZoneAwarePromise`, which isn't properly garbage collected when referenced elsewhere
(in this case, it would be referenced from the `tView` data).
PR Close#53031
This is a follow-up to the fix from #52414. It adds a diagnostic that will tell users when a control flow is preventing its direct descendants from being projected into a specific component slot.
PR Close#52726
The control flow projection diagnostic will mention `ng-container` as a workaround for projection multiple nodes. These changes add a couple of tests to ensure that the approach works.
PR Close#52726
These changes expose the `ngContentSelectors` and `preserveWhitespaces` metadata to the TCB so they can be used in the next commit to implement a new diagnostic.
PR Close#52726
When doing directive matching in the compiler, we need to be able to create a selector from an AST node. We already have the utility, but these changes simplify the public API and expose it so it can be used in `compiler-cli`.
PR Close#52726
This commit removes the `load` event listener once it has fired within the
`ImagePerformanceWarning`. The `load` event listener prevents the zone stuff from
being garbage collected in development mode when debugging microfrontend applications
that may be destroyed multiple times.
PR Close#52512
The `$first`, `$last`, `$even` and `$odd` variables in `@for` loops aren't defined on the template context of the loop, but are computed based on `$index` and `$count` (e.g. `$first` is defined as `$index === 0`). We do this calculation by looking up `$index` and `$count` when one of the variables is used.
The problem is that all `@for` loop variables are available implicitly which means that when a nested loop tries to rewrite a reference to an outer loop computed variable, it finds its own `$index` and `$count` first and it doesn't look up the ones on the parent at all. This means that the calculated values will be incorrect at runtime.
These changes work around the issue by defining nested-level-specific variable names that can be used for lookups (e.g. `$index` at level `2` will also be available as `ɵ$index_2`). This isn't the most elegant solution, however the `TemplatDefitinionBuilder` wasn't set up to handle shadowed variables like this and it doesn't make sense to refactor it given the upcoming template pipeline.
Fixes#52917.
PR Close#52931
Reworks the `repeater` instruction to go through `advance`, instead of passing in the index directly. This ensures that lifecycle hooks run at the right time and that we don't throw "changed after checked" errors when we shouldn't be.
Fixes#52885.
PR Close#52935
Currently, when a component is overriden using `TestBed.overrideComponent`, Angular retains calculated scope for that component (a set of components and directives used within a component). This may cause stale information to be used in tests in some cases. This commit updates the logic to reset overridden component scope, so it gets re-computed during the next invocation.
Resolves#52817.
PR Close#52916
- the example when taken from docs into projects didn't work
- getDeferBlocks has to be used with async
- improved description of default state (placeholder)
- improved assertion of <large-component /> as when generated by schematics
PR Close#52874
The call signature of detectChangesInternal requires parameters that can all be
found directly on lView. This commit removes those paramters and instead
grabs them in the function implementation.
PR Close#52866
There are cases where the application's default behavior is 'reload' and
a certain navigation might want to override this to be `ignore` instead.
This commit allows `onSameUrlNavigation` in the `router.navigateByUrl`
to be `ignore` where it was previously restricted to only `reload`.
PR Close#52265
These tests ensure signals can be read in a template after embedded
views are created in the middle of template execution of an update pass.
The embedded view templates are executed in create mode in the middle of
the component template being executed in update mode. This behavior was
found to not work correctly in past implementations of the reactive
template consumers.
PR Close#52495
This should fix the issue where if the same ng-template is used with multiple if / else statements, it replaces all usages properly.
fixes: #52854
PR Close#52863
Previously we had logic for a special case where a root injector in standalone apps would skip the import paths calculation step for the `getEnvironmentInjectorProviders` function.
This commit intends to fix this for two other cases, namely:
- When an injector is created by a route (via the `providers` field and lazy loading).
- When an injector is manually created and attached to the injector tree
It does this by assuming that any environment injector it cannot find a provider imports container for was created without one, and simply returns the raw provider records without the import paths calculation.
PR Close#52774
This fixes a bug where if you have multiple tsconfig files, the migration would not find anything to migrate at the passed in path.
fixes: #52787
PR Close#52796
This update removes imports from component decorators and at the top of the files. It only removes standalone imports though. It does not remove CommonModule if that is the only import.
PR Close#52763
Previously, some versions of Angular 16.1.x that had 3/4 of the new DI debug APIs would enter a code path that required them to have access to the 4th.
Now DevTools checks for the existence of all 4 explicitly before going down this code path.
PR Close#52791
In some cases ICU expression placeholders may have trailing spaces that
need to be trimmed when matching the placeholder to its corresponding
text binding.
PR Close#52698
We were previously counting the i18n expression index and deciding when
to apply i18n expressions based on the i18n context. These should be
done based on the i18n block instead.
PR Close#52698
The previous commit added support for interpolated text in ICUs, but it
made the assumption that the interpolation would be a single variable
read expression.
To properly support all kinds of interpolation expressions, this commit
refactors how ICUs are ingested to allow us to re-use the same logic we
use for bound text outside of ICUs.
To accomplish this, the `IcuOp` creation op has been removed in favor of
a pair of ops: `IcuStartOp` and `IcuEndOp`, that mark the beginning and
end of the ICU. Now, instead of inserting an `IcuUpdateOp` in the update
IR, we call `ingestBoundText` and use the presence of the surrounding
`IcuStartOp` and `IcuEndOp` to match the interpolation with the ICU.
PR Close#52698
Previously ICUs were assumed to only generate a single i18n expression
per ICU. However, it is possible for ICUs to contain text interpolations
which requires additional expressions. This commit adds support for
multiple expressions per ICU.
PR Close#52698
ICUs that contain element tags need extra parameters for the i18n
message. These are in addition to the element slot params that are
already added to the parent i18n block's params. In this commit we add a
new phase to fill in these placeholders.
PR Close#52698
Previously the template pipeline sorted i18n message params before
adding the sub-message placeholders. Now its sorts after all
placeholders are added.
Both the template pipeline and TemplateDefinitionBuilder previously
failed to sort the post-processing params. They both now sort these as
well. This is safe to change in TemplateDefinitionBuilder, as it does
not change anything about the functionality, it simply ensures that
params map in the output has the keys ordered in a way that can be
easily reproduced in the template pipeline.
PR Close#52698
Updates the repo to support TypeScript 5.3 and resolve any issues. Fixes include:
* Updating usages of TS compiler APIs to match their new signatures.
* In TS 5.3 negative numbers are represented as `PrefixUnaryExpression` instead of `NumericExpression`. These changes update all usages to account for it since passing a negative number into the old APIs results in a runtime error.
PR Close#52572
This cleans up a bit of code to make maintenance easier. It also adds comments for all the exported methods so they are clear to anyone in the future.
PR Close#52755
This implementation does most, but not all, of the things the native
Navigation API does. Also adds a spec that tests all the currently
supported behaviors.
PR Close#52363
When a component contains `@defer` blocks, Angular compiler generates the code to apply component metadata (from the `@Component` decorator) after resolving all dynamic dependencies. Currently, this function is invoked eagerly at runtime, which causes dynamic imports to be kicked off earlier than expected. With the change in this commit, Angular will start resolving async metadata when it becomes necessary during testing.
PR Close#52708
Fixes that all implicit variables in `@for` loops were inferred to be numbers, even though most are actually boolean.
Note that I also had to work around a weird TypeScript behavior in `tsDeclareVariable` where usually we declare variables in the following format:
```
var _t1: <type> = null!;
```
This works in most cases, but if the type is a `boolean`, TypeScript infers the variable as `never`, instead of `boolean`. I've worked around it by adding an `as boolean` to the initializer.
Fixes#52730.
PR Close#52732
This change fixes a bug in the new list reconcilation algorithm
that could lead to an infinite loop in certain situations.
More specifically, it adjusts the internal MultiMap implementation
such that an entry returned from the .get call is the same entry
(for an identical key) removed by the .delete call.
The existing logic of the MultiMap was leading to a situation where
one view was requested and attached to LContainer, but a very different
view was removed from the MultiMap. This was leaving an attached LView
in a collection that was supposed to hold only detached views.
Closes#52524
PR Close#52697
Add the deprecated-api-item class on decorator-overview option code if deprecated. Add deprecated label on decorator-overview short description if deprecated. Add Add deprecated label on decorator option table header if option is deprecated.
PR Close#52041
When using `withFetch`, the `PRIMARY_HTTP_BACKEND` token is set.
The InMemory Backend services will also set that token.
This means that providers order will matter and the latest on the list will be the one instantiated
PR Close#52425
Adds the private `_enableBlockSyntax` flag that can be used by the language service to disable blocks on apps that aren't on Angular v17.
PR Close#52683
Fixes that the hamburger icon was too small, because the top nav is using the wrong kind of button. Switching it to the right one would require more refactoring so I went with the simpler approach for now.
PR Close#52689
`RootViewRef<T>` extends `ViewRef<T>` and overrides 3 methods with behavior
that is identical to `ViewRef<T>`. This commit removes `RootViewRef<T>`
because it is not needed.
PR Close#52430
* Node 16 support is dropped per angular/angular-cli#25675
* TS 5.2 is supported per #51334
* TS 5.1 and lower support is dropped by #51792
PR Close#51443
Rather than migrate all in one pass, this now migrates in a separate pass per control flow item plus one for templates at the end. This resolves issues with multiple control flow items on a single element as well as making sure ng-templates are fully migrated before being moved to new locations.
fixes: #52518fixes: #52516fixes: #52513
PR Close#52592
Now that two-way bindings work correctly with implicit receivers, we can fix the corresponing source map tests. The main issue was that we were not properly mapping `elementEnd` for elements with no closing tag (self-closing elements).
PR Close#52479
Some two-way bindings tests were not working properly, because we could not ingest the implicit receiver required to write to the `ngModelChanges` property. Now, we properly resolve that implicit receiver to the root component context.
Also, add some tests, both for the simple case, and the case where the listener is inside a nested view.
PR Close#52479
Some `defer` blocks have external dependencies on other components or directives. These dependencies need to be extracted into deps functions, which either return local deps, or use a dynamic import for non-local deps. Template Pipeline can now generate these functions.
PR Close#52479
When an `ng-template` has local refs, such as `<ng-template #foo>`, we must emit a `ɵɵtemplateRefExtractor` argument to the template creation functino. The template pipeline now supports this.
PR Close#52479
`TemplateDefinitionBuilder` is somewhat unreliable about extracting constant attributes (e.g. `[attr.foo]="'one'"`). It never extracts const non-string expressions, and usually, but not always, extracts const string expressions. Template pipeline consistently extracts const strings, and we add new goldens for a couple such cases.
PR Close#52479
Some defer triggers, such as `hover`, expect a local reference as an argument. For example, `@defer (on hover(target))` waits until the user hovers over the target.
However, these defer conditions also have a nullary form, in which the trigger is implicitly the first element in the placeholder block. We now support that case in template pipeline.
PR Close#52479
We already supported `defer on` conditions, which become instructions in the create mode block.
Now, we also support `defer when` conditions, where are very similar, with the notable difference that they go in the update block (because a user-supplied condition must be re-evaluated on each update.)
PR Close#52479
Previously we supported ICUs where the ICU itself represetned the entire
translated message. This change allows ICUs to act as a sub-message
inside other translated messages.
PR Close#52503
Previously we assumed that all i18n messages that are eventually
extracted into the consts array would be generated based on an i18n
block. However, it is also possible to have messages generated directly
from ICUs. This change introduces an i18n context op, so that we can
consistently extract i18n messages from the context op in all cases.
PR Close#52503
This addresses an edge case where an ng-template name matches an opening element name, preventing the template from being removed.
fixes#52523
PR Close#52529
Discovered this while validating #52414 against Angular Material. We were projecting `<ng-template>` nodes at the root of `@if` and `@for` with the `ng-template` tag name which enables directive matching and applies the directive to the control flow node.
These changes fix the issue by never passing along the `ng-template` tag name.
PR Close#52515
This is something that came up when running the script against the Components repo. The `ngFor` syntax can be delimited either by semicolons or by commas, but the migration only accounted for commas.
PR Close#52525
Previously transformInjectorResolutionPathsIntoTree returned an array, now it returns a tree node so we update the test cases to reflect that.
PR Close#52489
Previously only the trackpad could be used to navigate this view.
Now we can zoom and pan around using our mouse wheel and scroll.
Additionally, this commit fixes many issues related to the visualization of the injector graph visualization, allowing it to be more compact without impacting legibility and minimizing edge collisions in larger graphs.
PR Close#52489
Our algorithm for discovering the injector graph of an application involves calculating resolution paths for each angular node on a page, and then using those paths to construct the underlying tree.
Along the we way we perform many expensive computations that are candidates for optimization through caching. This commit implements this caching, resulting in a substantial increase in performance for large applications.
PR Close#52489
Implements a feature allowing users to visualize multiproviders as one row in the providers table.
Also enables the user to log to console any provider in the table. This log includes information about the provider selected, the injector it was configured in, and also calls `Injector.get(Token)` to determine the value the provider evaluates to in it's injector.
PR Close#52489
Previously this was the only page that used the inspector, so we automatically changed the tab out of convenience.
Now, the injector tree tab also does uses the inspector for some functionality, so we disable this behaviour.
PR Close#52489
Previously, LViews were used here to be consistent with other debug APIs. Using LViews for tracking injector providers does not work because providers only get configured once per TNode type.
Now we use the TNode as the key to track element injector providers, allowing the injector for each item rendered in a list (`ngFor` or `@for`) to be targeted with debug APIs for inspecting providers
PR Close#52436
Before this commit, zone.js wraps the uncaught promise rejection error
to a new Error object includes more information such as Zone stack
traces. This feature is provided from the very beginning of Zone.js,
but this feature becomes very annoying and make the user difficult to
debug.
So this commit disable this wrapping behavior by default, and user can
enable this feature back by setting
`DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION` to `false`.
PR Close#52492
Fixes that the control flow migration wasn't migrating an `*ngIf` with an `else` condition that doesn't have spaces before the `else`.
Fixes#52502.
PR Close#52504
While `performance.mark` is available on all supported browsers and node.js version this API is not available in JSDOM which is used by Jest and Cloudflare worker.
PR Close#52505
While `performance.mark` is available on all supported browsers and node.js version this API is not available in JSDOM which is used by Jest and Cloudflare worker.
This commit, updates the usage to a safer variant.
PR Close#52505
Re-add the `@developerPreview` flags to `effect()`. While we don't expect
the `effect` API itself to change, we may change how other FW APIs interact
with `effect`s. Also, add a missing export for one of those effect APIs.
PR Close#52490
Producers represent values which can deliver change notifications.
When a producer value is changed, a change notification is propagated through the graph,
notifying live consumers which depend on the producer of the potential update.
Note here that this is a _potential_ update.
A producer may not have actually "changed" based on its equality function. With
this commit, before refreshing a view that is only marked for refresh
because its consumer is dirty, we poll producers for change to see if
they really have. If not, we can skip the refresh. The example test in this commit
shows that a `computed` which depends on a `signal` that is updated but
produces a value that is the same as before will _not_ cause the
component's template to refresh.
fixes#51797
PR Close#52476
This commit updates the reactive consumer used for `LView`s to be shared
between a component and its embedded views. This allows us to use the
consumer flag directly for a dirty indicator rather than needing to
find a component view for updating its flags.
In the future, this will also allow us to effectively poll producers to see if
they really changed before refreshing a view.
PR Close#52476
The significance of the combination of #51854 and #52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.
fixes#50320
PR Close#52476
This change updates the new build system migration guide with additional
information regarding the steps needed to convert an existing SSR project
to use the new integrated SSR capabilities.
PR Close#52485
This commit wraps the `load` event listener with `runOutsideAngular` to avoid
running unnecessary change detections on asynchronous tasks spawned within the
scope of the `ImagePerformanceWarning` functionality. This was previously causing
extra change detection cycles in development mode and interfering with debugging.
PR Close#52482
TypeScript JsDoc parsing, by default, treats occurences of Angular decorators (e.g. `@Component`) in JsDoc comments as JsDoc tags. This commit escapes these decorator strings by copying the raw JS doc onto a dummy symbol in a new SourceFile to make TypeScript re-parse the comment.
PR Close#52481
Adds build rules for "artificially" generating `DocEntry` collections for block and element APIs. The two rules are very similar, but _just_ different enough that it's worth having two separate implementations.
PR Close#52480
This adds a target to generate a manifest of all public api symbols. The majority of inputs are generated from the extraction rules, but API entries that don't have a TypeScript source symbol (elements and blocks) are defined in hand-written json collections.
PR Close#52472
This change skips signal equality calls on set / update when the
two values (current and the new one) are referentially identical.
The assumption is that equality function implementation should
never return false for 2 values that are the same (according to
the Object.is logic).
PR Close#52465
Eliminate all the remaining `cpl` names, and use `job` instead, which is the predominant convention.
Also, replace `.views.values()` with `.unit` in a few places, and perform the corresponding rename.
PR Close#52464
In this cleanup commit:
1. Add explanatory comments to all phases that were previously missing them.
2. Rename all phases, to eliminate the "phase" prefix, and directly describe their functions.
PR Close#52464
This commit removes the `finish` listener from the Animation object once
the animation is finished, effectively resolving a memory leak. Previously,
the `finish` listener captured `this`, which prevented `this` from being garbage collected.
PR Close#51136
`application` builder is preferred over `browser` builder. This updates all the examples I could find to use `application` builder. A couple notes of fixes that needed to happen:
1. The testing example was broken because it relied on `~` imports in CSS files, which is a Webpack-specific features. However I don't think we need those custom styles at all, so I just removed the import altogether.
2. A few tests seemed to be affected and needed to be cleaned up.
PR Close#52361
When an effect is created in a component constructor, it might read signals
which are derived from component inputs. These signals may be unreliable or
(in the case of the proposed input signals) may throw if accessed before the
component is first change detected (which is what makes required inputs
available).
Depending on the scenario involved, the effect may or may not run before
this initialization takes place, which isn't a great developer experience.
In particular, effects created during CD (e.g. via control flow) work fine,
as do effects created in bootstrap thanks to the sync CD it performs. When
an effect is created through dynamic component creation outside of CD though
(such as on router navigations), it runs before the component is first CD'd,
causing the issue.
In fact, in the signal components RFC we described how effects would wait
until ngOnInit for their first execution for exactly this reason, but this
behavior was never implemented as it was thought our effect scheduling
design made it unnecessary. This is true of the regular execution of effects
but the above scenario shows that *creation* of the effect is still
vulnerable. Thus, this logic is needed.
This commit makes effects sensitive to their creation context, by injecting
`ChangeDetectorRef` optionally. An effect created with an injector that's
tied to a component will wait until that component is initialized before
initially being scheduled. TestBed effect flushing is also adjusted to
account for the additional interaction with change detection.
PR Close#52473
By default, `toSignal` transforms an `Observable` into a `Signal`, including
the error channel of the Observable. When an error is received, the signal
begins throwing the error.
`toSignal` is intended to serve the same purpose as the `async` pipe, but
the async pipe has a different behavior with errors: it rejects them
outright, throwing them back into RxJS. Rx then propagates the error into
the browser's uncaught error handling logic. In the case of Angular, the
error is then caught by zone.js and reported via the application's
`ErrorHandler`.
This commit introduces a new option for `toSignal` called `rejectErrors`.
With that flag set, `toSignal` copies the async pipe's behavior, allowing
for easier migrations.
Fixes#51949
PR Close#52474
These special providers are configured when `walkProviderTree` is called. Because of this, they do not maintain any equality between subsequent runs of `walkProviderTree`. This prevents us from being able to compare the provider objects for equality between runs.
This commit changes the behaviour of getInjectorProviders to ignore these providers. In the future we will consider another approach for differentiating these providers from ones provided by users rather than the framework.
PR Close#52458
Recreates the fix for content projection in control flow in the new template pipeline. I also had to make the following adjustments to the pipeline:
1. The `TemplateOp.tag` property was being used to generate the name of the template function, rather than the actual tag name being passed into `ɵɵtemplate`. Since the content projection fix requires the tag name to be passed in, I've introduced a new `functionNameSuffix` property instead.
2. `TemplateOp.block` was being used to determine whether to pass `TemplateOp.tag` into the `ɵɵtemplate` instruction. Now that we're always passing in the tag name after the refactor in point 1, we no longer need this flag.
In addition to the refactors above, I also made some minor cleanups where I saw the opportunity to do so.
PR Close#52414
With the directive-based control flow users were able to conditionally project content using the `*` syntax. E.g. `<div *ngIf="expr" projectMe></div>` will be projected into `<ng-content select="[projectMe]"/>`, because the attributes and tag name from the `div` are copied to the template via the template creation instruction. With `@if` and `@for` that is not the case, because the conditional is placed *around* elements, rather than *on* them. The result is that content projection won't work in the same way if a user converts from `*ngIf` to `@if`.
These changes aim to cover the most common case by doing the same copying when a control flow node has *one and only one* root element or template node.
This approach comes with some caveats:
1. As soon as any other node is added to the root, the copying behavior won't work anymore. A diagnostic will be added to flag cases like this and to explain how to work around it.
2. If `preserveWhitespaces` is enabled, it's very likely that indentation will break this workaround, because it'll include an additional text node as the first child. We can work around it here, but in a discussion it was decided not to, because the user explicitly opted into preserving the whitespace and we would have to drop it from the generated code. The diagnostic mentioned point #1 will flag such cases to users.
Fixes#52277.
PR Close#52414
Previously, we would modified `dep.flags` directly to convert injection flags to booleans. This caused a mutation bug where subsequent calls to `getDependenciesFromInjectable` would result in the flags object containing false for every injection flag.
Now, we stop modifying `dep.flags` directly and instead assign the converted flags to a new object.
PR Close#52450
The current regexp supposes that there is at least one space between the `=` and the aliased variable.
As it is possible to write `let myIndex=index`, this commit updates the regexp to handle such a case.
PR Close#52444
Prior to this change, the transform function would be referenced with a potentially
relative import into an external declaration file. Such imports are not portable
and should not be created in this context. This commit addresses the issue by threading
though the originally used module specifier by means of the `Reference` type.
Fixes#52324
PR Close#52437
This commit fixes an issue where using literal types in the arguments of an input coercion
function could result in emitting invalid output, due to an assumption that TypeScript makes
when emitting literal types. Specifically, it takes the literal's text from its containing
source file, but this breaks when the literal type node has been transplanted into a
different source file. This issue has surfaced in the type-check code generator and is
already being addressed there, so this commit moves the relevant `TypeEmitter` class
from the `typecheck` module to the `translator` module, such that it can be reused for
emitting types in the type translator.
Fixes#51672
PR Close#52437
Fixes that our regex for parsing time values in defer blocks didn't allow for decimals. This isn't relevant for times in milliseconds, but it can be convenient to write something like `on timer(1.5s)`.
PR Close#52433
The `checkNoChanges` method does not belong in the API of production interface. `checkNoChanges` is
limited to testing and should not be used in any application code. Test
code should use `ComponentFixture` instead of `ChangeDetectorRef`.
Additionally, it is not desirable to have the `checkNoChanges` API
available in a context where `detectChanges` is not run first.
DEPRECATED: `ChangeDetectorRef.checkNoChanges` is deprecated.
Test code should use `ComponentFixture` instead of `ChangeDetectorRef`.
Application code should not call `ChangeDetectorRef.checkNoChanges` directly.
PR Close#52431
Adds some logic to skip over comments when resolving implicit `@defer` block triggers. This currently isn't a problem since we don't capture comments by default, but it may come up if we start capturing comments.
PR Close#52449
`RootViewRef<T>` extends `ViewRef<T>` and overrides 3 methods with behavior
that is identical to `ViewRef<T>`. This commit removes `RootViewRef<T>`
because it is not needed.
PR Close#52430
The `ViewRef<T>` interface extends `InternalViewRef` and is already not
part of the public API. There is no need for the extra `InternalViewRef`
interface. This confusing setup is likely leftover from the types
necessary to support both Ivy and ViewEngine.
PR Close#52430
When using `withFetch`, the `PRIMARY_HTTP_BACKEND` token is set.
The InMemory Backend services will also set that token.
This means that providers order will matter and the latest on the list will be the one instantiated
PR Close#52425
This commit adds a global epoch to the reactive graph, which can optimize
non-live reads.
When a non-live read occurs, a computed must poll its dependencies to check
if they've changed, and this operation is transitive and not cacheable.
Since non-live computeds don't receive dirty notifications, they're forced
to assume potential dirtiness on each and every read.
Using a global epoch, we can add an important optimization: if *no* signals
have been set globally since the last time it polled its dependencies, then
we *can* assume a clean state. This significantly improves performance of
large unwatched graphs when repeatedly reading values.
PR Close#52420
The `for` block has several parts which we know are required. This
commit improves the autocomplete snippet of the `for` block by adding
those required parts and providing placeholders.
PR Close#52405
The previous commits provided the scaffolding for `defer on`. In this commit, we build on that work, adding triggers for `immediate`, `timer`, `hover`, and `viewport`.
PR Close#52387
Previously, we supported a `HasConst` trait, allowing an op to be const collected automatically. However, that approach had the shortcoming that each op could only collect a single constant.
Instead, we now provide a `ConstCollectedExpr`, which collects constants at the expression level, allowing ops to have multiple collectible consts.
Then, we use this new abstraction to support the `defer on` conditions.
PR Close#52387
Previously, we had an "empty shell" implementation of defer conditions, and we used separate ops to represent secondary defer blocks.
Now, we have a real scaffolding for supporting the various defer conditions, and the secondary defer block information has been refactored onto the main defer op.
Additionally, to enable this, we refactor the way that using slot indices works. Instead of having a trait that causes users of slot indices to be linked to the allocated slot, we share a single `SlotHandle` object by reference. This allows an op to use slot information for more than one Xref at a time, and eliminates a layer of indirection.
Co-authored-by: Alex Rickabaugh <alxhub@users.noreply.github.com>
PR Close#52387
This commit updates the reactive template and host binding consumers to
only mark their declaration components for refresh, but not parents/ancestors.
This also updates the `AfterViewChecked` hook to run when a component is
refreshed during change detection but its host is not. It is reasonable
to expect that the `ngAfterViewChecked` lifecycle hook will run when a
signal updates and the component is refreshed. The hooks are typically
run when the host is refreshed so without this change, the update to
not mark ancestors dirty would have caused `ngAfterViewChecked` to not
run.
resolves#14628resolves#22646resolves#34347 - this is not the direct request of the issue but
generally forcing change detection to run is necessary only because a
value was updated that needs to be synced to the DOM. Values that use
signals will mark the component for check automatically so accessing the
`ChangeDetectorRef` of a child is not necessary. The other part of this
request was to avoid the need to "mark all views for checking since
it wouldn't affect anything but itself". This is directly addressed by
this commit - updating a signal that's read in the view's template
will not cause ancestors/"all views" to be refreshed.
PR Close#52302
Currently, the migration always use `$index` in the migrated trackBy function, whereas this variable might be aliased.
The compiler then errors with:
```
error TS2339: Property '$index' does not exist on type 'UsersComponent'.
110 @for (user of users; track byId($index, user); let i = $index) {
```
This commit updates the migration to use the aliased index if there is one.
PR Close#52423
The i18n placeholder resolution phase has accumulated too much logic,
making it difficult to understand. This commit refactors it into several
smaller phases to make it easier to manage.
I suspect this will undergo further refactoring in the near future as I
work through the ICU logic. In particular `ExtractedMessageOp` feels
like a bit of a grab bag of properties, and the i18n const collection
phase is also starting to get quite heavy. This refactor at least feels
like a good start.
PR Close#52390
Enables a handful of i18n tests that are currently skipped, but pass if
enabled. Some of them require alternate golden files because of
inconsequential differences in the cost array order.
PR Close#52390
This commit expands docs extraction for classes and interfaces to include inherited members. This relies on the type checker to get the _resolved_ members of the type so that the extractor doesn't need to reason about inheritance rules, which can get tricky (especially with regards to method overloads).
PR Close#52389
This commit adds decorators to the extracted API docs. It makes some
very hard-coded assumptions about the pattern used to declare decorators
that's extremely specific to what the framework does today.
PR Close#52389
Issue #50320 shows that in some cases, updating a signal that's a dependency
of a template during change detection of that template can have several
adverse effects. This can happen, for example, if the signal is set during
the lifecycle hook of a directive within the same template that reads the
signal.
This can cause a few things to happen:
* Straightforwardly, it can cause `ExpressionChanged` errors.
* Surprisingly, it can cause an assertion within the `ReactiveLViewConsumer`
to fail.
* Very surprisingly, it can cause change detection for an `OnPush` component
to stop working.
The root cause of these later behaviors is subtle, and is ultimately a
desync between the reactive graph and the view tree's notion of "dirty" for
a given view. This will be fixed with further work planned for change
detection to handle such updates directly. Until then, this commit improves
the DX through two changes:
1. The mechanism of "committing" `ReactiveLViewConsumer`s to a view is
changed to use the `consumerOnSignalRead` hook from the reactive graph.
This prevents the situation which required the assertion in the first
place.
2. A `console.warn` warning is added when a view is marked dirty via a
signal while it's still executing.
The warning informs users that they're pushing data against the direction of
change detection, risking `ExpressionChanged` or other issues. It's a
warning and not an error because the check is overly broad and captures
situations where the application would not actually break as a result, such
as if a `computed` marked the template dirty but still returned the same
value.
PR Close#52234
The `RouterTestingHarness` should throw an error if the call to `navigateByUrl`
expects a component to be activated but the navigation failed.
fixes#52344
PR Close#52357
Previously, because the platform injector does not have a provider container, this API would fail. Now, we account for this case specifically by returning the found providers immediately, without trying to calculate their importpaths.
Also previously, in the case where a boostrapped standalone component did not import any feature modules, the environment injector connected to that bootstrapped component would be the root injector configured by `bootstrapApplication`. This injector is configured through a `providers` array instead of an `imports` array, and also does not have a provider container. Similarly to the platform case, we account this for this by returning the found providers immediately if there is no provider container for our standalone component.
PR Close#52365
Previously this case was missed by the default framework injector profiler. Now in ngDevMode this event emits correctly when a service is configured with `providedIn`. This includes the case where injection tokens are configured with a `providedIn`.
This commit also includes unit tests for this new case in the injector profiler.
PR Close#52365
Angular recently gained a local compilation mode (see commit
345dd6d81a). This is intended to be used
with the TypeScript compiler option isolatedModules, which bans imports
of const enums.
This changes all const enums tagged with @publicApi to regular enums.
Fixes#46240
PR Close#51670
This updates the code to handle switches more elegantly in line with how the other blocks are handled. This allows nesting to be handled just like other blocks.
PR Close#52358
`globalThis` global property contains the global `this` value, which is usually akin to the global object. This is needed for better compatibility with CloudFlare workers were global nor window are defined as globals.
PR Close#52367
This commit runs change detection in a loop while there are still dirty
views to be refreshed in the tree. At the moment, this only applies to
transplanted views but will also apply to views with changed signals.
fixes angular#49801
PR Close#51854
When migrating an ng-template later on in a file, the migrationResult was not being reset to zero and causing offsets to be double applied due to ng-template nodes being included in the migration loop.
PR Close#52355
Previously, we would emit *two* pipe creation instructions for each pipe in a switch case. This is because we were visiting both the transformed and raw versions of the pipe bindings.
Now, we clear the raw case expressions array after generating the transformed test expression.
Also, we introduce some new goldens, because our pipe creation order is harmlessly different.
PR Close#52289
We roughly attempt to match TemplateDefinitionBuilder's pipe creation order, by placing pipe creation instructions after their target elements. However, we cannot fully emulate the "inside-out" ordering TemplateDefinitionBuilder uses when multiple pipes apply to one element, because TemplateDefinitionBuilder creates the pipes as expressions are visited, from the leaves up. Our order is perfectly adequate though.
We also add a non-compatibility-mode ordering, which just appends them to the end of the create block. This is better because it allows for more chaining opportunities.
PR Close#52289
Singleton property interpolation instructions consume only one variable, but are still emitted as an interpolation instruction (they cannot be collapsed because `propertyInterpolate` implicitly stringifies its argument.)
PR Close#52289
We were incorrectly emiting a extracted constant pool index for the final argument of the projection instruction. It actually takes an array literal.
(N.B.: This means we re-create the array every time! We should probably modify the runtime to use a const index for this.)
Additionally, we alter the projection op to not extend the element op base type.
PR Close#52289
The correct order of attributes and properties is:
1. Interpolated properties
2. Interpolated attributes
3. Non-interpolated properties
4. Non-interpolated attributes
This includes an additional nuance: singleton attribute interpolations, such as `[attr.foo]="{{bar}}"`, will be "collaped" into a simple `attribute` instruction. However, this is *not* the case for singleton property interpolations! The ordering phase must take this nuance into account to match the TemplateDefinitionBuilder order.
After the project lands, it might be nice to also collapse singleton property interpolations.
PR Close#52289
Previously, we ran the ordering phase near the end of the compilation. However, this meant that phases like slot assignment and variable offset assignment would happen first, and then the nice, monotonically-increasing orders would be scrambled by the reordering.
It's much more intelligible to order first, and then perform these assignments. However, to make this happen, some modifications to the ordering phase are required. In particular, we can no longer rely on `advance` instructions to break up orderable groups.
PR Close#52289
Many instructions consume variable slots, which are used to persist data between update runs. For top-level instructions, the offset into the variable data array is implicitly advanced, because those instructions always run.
However, instructions in non-top-level expressions cannot be assumed to run every time, because they might be conditionally executed. Therefore, they cannot implicitly advance the offset into the variable data, and must be given an explicitly assigned variable offset.
TemplateDefinitionBuilder assigned offsets top-to-bottom for all instructions *except* pure functions. Pure functions would be assigned offsets lazily, on a second pass.
Template Pipeline can now imitate this behavior, when in compatibility mode: pure functions are assigned offsets on a second pass.
This also makes the "variadic var offsets" phase unnecessary -- the new approach is more general and correct.
PR Close#52289
Previously, inside an event listener, template pipeline would always save the context from restoring a view, e.g.
```
const restored_ctx = r0.ɵɵrestoreView(s);
```
This is usually correct! However, consider the case of a listener in the template's root view. The appropriate context will already be available via closure capture, and we can just use it (as `ctx`).
Now, the context resolution phase understands that we don't need to use the restored view's saved context if we would have access to it by closure.
Note: we also create a new golden, because the const array is in a harmlessly different order.
PR Close#52289
Previously, the template pipeline did not handle "empty" reads gracefully: it would emit syntactically invalid reads of empty properties. Now we read `$implicit`.
This allows us to enable a test that relies on `$implicit`. However, we also have to create another golden, because our variable inlining is more aggressive.
PR Close#52289
We currently allow elements to be collapsed around pipe creation instructions. TemplateDefinitionBuilder disallows this, but only sometimes. Collapsing in this case is actually less generated code, and it's OK to allow it.
PR Close#52289
Previously, the cross entry-point dependency was created to share the `setDomTypes` function. This however, causes extra transformations "linking" during the application build since other Angular code in `@angular/platform-server` is pulled in.
With this commit we remove the cross dependency and thus remove the need for extra transformations in the server polyfill bundle with the result of having a slightly faster build.
See: https://github.com/angular/angular-cli/pull/26113
PR Close#52342
This commit updates the logic to ignore `after` and `minimum` conditions when `DeferBlockFixture.render` method is used in tests.
Resolves#52313.
PR Close#52314
This commit updates the code to report errors via `ErrorHandler` instance.
For dependency loading problems, errors are reported only when `@error` block is not provided.
PR Close#52320
This updates offset to handle pre and post offset properly for nested situations, rather than relying on solely nestCount. This should properly apply offset calculations at the right time to handle any nested situation.
PR Close#52332
The template pipeline can now generate track functions, and extract them into the constant pool (or optimize them if needed). Additionally, context variables such as `$index` can be used inside track functions and for loop bodies.
PR Close#52001
Add support for `repeaterCreate` and `repeater` instructions. Correctly count decls and vars, and support primary and empty blocks.
`track` functions are not yet extracted.
PR Close#52001
View compilations previously had context variables, which were variables available in the view that would result in a property read on the context object.
We now also support the notion of aliases. An alias is a variable available in the view compilation, which might be derived from a context variable, which it may reference by name. It is always inlined at all usage sites, and therefore is not allowed to depend on the current context.
Under the hood, aliases rely on the new `AlwaysInline` mode.
Co-authored-by: Alex Rickabaugh <alxhub@users.noreply.github.com>
PR Close#52001
The template pipeline now supports lexical variables that are always inlined into their call sites, even if multiple call sites exist.
An `AlwaysInline` variable may not rely on the current context, because it will potentially be inlined at several different locations.
Co-authored-by: Alex Rickabaugh <alxhub@users.noreply.github.com>
PR Close#52001
Prior to this commit relative HTTP requests were not being resolved to absolute even thought the behaviour is documented in https://angular.io/guide/universal#using-absolute-urls-for-http-data-requests-on-the-server.
This caused relative HTTP requests to fail when done on the server because of missing request context. This change is also required to eventually support HTTP requests handled during prerendering (SSG).
Closes#51626
PR Close#52326
Previously, autocompletions were not available in two main cases. We correct them.
1. Autocompletions immediately after `@` were usually not working, for example `foo @|`. We fix this by causing the lexer to not consider the `@` part of the text node.
2. Autocompletions such as `@\nfoo`, where a newline follows a bare `@`, were not working because the language service visitor considered us inside the subsequent text node. We fix this by adding a block name span for the block keyword, and special-case whether we are completing inside the name span. If we are, we don't continue to the following text node.
PR Close#52198
This commit adds the logic to cleanup all triggers once defer block is triggered.
When a trigger is created, its cleanup function is stored alongside other defer block info. Prefetch and regular triggers are store in different slots, since we need to invoke them at different time.
PR Close#52291
A few performance improvements and code cleanups in the after render hooks:
1. We were wrapping each `destroy` callback in another callback, because it was typed as `|undefined`. This is unnecessary, because the callback is guaranteed to exist. These changes pass the `destroy` function around directly and avoid the additional callback.
2. In server platforms we were recreating a noop `AfterRenderRef` on each invocation. We can save some memory by returning the same one.
3. Reworks the `AfterRenderCallback` so that it injects `NgZone` and `ErrorHandler` itself, instead of expecting them to be passed in. This reduces the amount of repetition in the code.
PR Close#52292
In #52110 the compiler was changed to produce `if` statements when type checking `@switch` in order to avoid a bug in the TypeScript compiler. In order to avoid duplicate diagnostics, the main `@switch` expression was ignored in each of the `@case` comparisons. This appears to have caused a regression where comparing incompatible types wasn't being reported anymore.
These changes resolve the issue by wrapping the expression in parentheses which allows the compiler to report comparison diagnostics while ignoring diagnostics in the expression itself.
Fixes#52315.
PR Close#52322
The current way of computing a route's params and data recomputes
inherited data from the inheritance root every time. When the
inheritance strategy is "emptyOnly", this isn't necessarily the root of
the tree, but some point along the way (it stops once it reaches an
ancestor route with a component).
Instead, this commit updates parameter inheritance to only inherit data
directly from the parent route (again, instead of recomputing all
inherited data back to the inheritance root). The only requirement for
making this work is that the parent route data has already calculated
and updated its own inherited data. This was really already a
requirement -- parents need to be processed before children.
In addition, the update to the inheritance algorithm in this commit
requires more of an understanding that a resolver running higher up in
the tree has to propagate inherited data downwards. The previous
algorithm hid this knowledge because resolvers would recompute inherited
data from the root when run. However, routes that did not have resolvers
rerun or never had resolvers at all would not get the updated resolved data.
fixes#51934
PR Close#52167
Now the method `getConstructorDependencies` no longer needs to do any post analysis, and can rely on the reflection host's result to generate ctor params. This will automatically include invalid factories which fix the issue.
PR Close#52215
Currently the reflection host's `getConstructorParameters` method is not aware of the compilation mode, and it generates result mainly assuming the compilation mode is full and we have access to global type info. As a result, its result is not very suitable for local compilation usage, particularly for deciding if a symbol is imported as type or not. This change plumbs a flag `isLocalCompilation` into reflection host to make it aware of the compilation mode.
Also changes made to the logic in the method `getConstructorParameters` so that in local compilation mode:
- returns NO_VALUE_DECLARATION type value ref only if the type is a type parameter
- returns local type value ref for any imported symbol, unless the import is type only in which case returns TYPE_ONLY_IMPORT type value ref
PR Close#52215
Removed the signals property definition from the Component interface since it already exists in the Directive interface and Component inherits from Directive
PR Close#52039
This commit refactors a couple places to improve performance:
* avoid checking parent tree if a current node has "skip hydration" flag
* avoid calling `isInSkipHydrationBlock` if there is no hydration info present
PR Close#52221
A lot of our tests are wrapped in `{}` which serves no purpose, aside from increasing the nesting level and, in some cases, causing confusion. The braces appear to be a leftover from a time when all tests were wrapped in a `function main() {}`. The function declaration was removed in #21053, but the braces remained, presumably because it was easier to search&replace for `function main()`, but not to remove the braces at the same time.
PR Close#52239
The commit adds messaging to the control flow template diagnostic to direct developers to the new
built-in control flow syntax in Angular.
PR Close#52268
This commit adds a benchmark for hydration runtime logic, which contains 2 parts: a baseline (create DOM nodes from scratch) and a main scenario (DOM matching instead of re-creating nodes).
PR Close#52206
This commit updates the message that we output in the console (once hydration is completed) to drop the reference to the developer preview.
PR Close#52197
This commit removes the `@developerPreview` annotation from the `provideClientHydration` function and related symbols, promoting them to stable.
PR Close#52197
Assuming that the trackBy function is a pure derivation from the collection
object and its index, we can skip trackBy calculation if items in the live
and new colelction have the same identity and index. Additionally this change
minimizes access to the LContainer array.
PR Close#52227
ICUs can be used outside of an i18n block. In this case the ICU should
be automatically wrapped in a new i18n block. This commit adds a new
phase to handle wrapping these bare ICUs.
PR Close#52250
ICU params in i18n messages are now resolved in the post-processing call
rather than in the initial message creation. This matches the output
generated by TemplateDefinitionBuilder.
PR Close#52250
ICUs are now ingested by adding ops to both the creation and update IR.
Both of these ops are ultimately removed before reification, but they
are needed to coordinate and link data between the creation and update
ops. This is done in a new ICU extraction phase that removes both ICU
ops and adds an i18nExpr op to the update IR.
PR Close#52250
This commit extracts the API reference info for generic parameters for
classes, methods, interfaces, and functions. It includes any constraints
and the default type if present.
PR Close#52204
Prior to this change the style element was appended to host element multiple times. Whilst the actual element was not added multiple to the DOM multiple times. This causes a performance regression and it caused repainting.
This can be observed in the below benchmark.
```js
(() => {
const time = (name, fn) => {
const t = performance.now();
fn();
console.log(name, performance.now() - t);
}
const s = document.createElement("style");
s.textContent = "@layer x{} @font-face { font-family: foo; }";
time("append and enable", () => {
document.head.append(s);
s.disabled = false;
});
time("compute body color", () => {
getComputedStyle(document.body).color;
});
time("compute body layout", () => {
document.body.offsetTop;
});
time("append and disable", () => {
document.head.append(s);
s.disabled = false;
});
time("compute body color", () => {
getComputedStyle(document.body).color;
});
time("compute body layout", () => {
document.body.offsetTop;
});
})();
```
Output
```
append and enable 0.20000000298023224
compute body color 0.7999999970197678
compute body layout 2.899999998509884
append and disable 0.10000000149011612
compute body color 0.7000000029802322
compute body layout 2.2999999970197678
```
When commenting the 2nd `document.head.append(s);`, the results are slightly different and we can see that calling `getComputedStyle` does not incur any performance impact this is a result of no repainting.
```
append and enable 0.10000000149011612
compute body color 0.7999999970197678
compute body layout 3.1999999955296516
append and disable 0.10000000149011612
compute body color 0
compute body layout 0
```
Pantheon benchmarks: http://docs/spreadsheets/d/1iLRLGCmVYZHuVRdI7dO_WM7wnQ1DvkS-tJzi-0-u1KY?resourcekey=0-kwtrf0nbAhcPqAGdqbdz4g#gid=0
PR Close#52237
Placing a structural directive on an element with an `i18n` attribute
was generating too many i18n blocks. This was due to both the element
and the template generating their own i18n block. To fix the issue, we
no longer generate top-level i18n blocks for structural directive
templates.
PR Close#52202
Structural directives on an ng-template (e.g. <ng-template *ngIf>) were
being assigned the wrong tag name ('ng-template' instead of null).
PR Close#52202
Fixes handling of placeholders for self-closing tags. Self-closing tags
set a combined value for the start tag placeholder, rather than separate
values for the start and close placeholders.
This commit also enables a number of now passing tests. For some of
these tests I had create a separate golden file due to the different
ordering of the const array. In the template pipeline, i18n and
attribute const collection happen in different pahses and we therefore
get a different order than TemplateDefinitionBuilder, which collected
everything in one pass. The order should not affect the overall behavior.
PR Close#52195
The way we were propagating params up to parent i18n ops didn't account
for the fact that a parent and child could both have a value for the
same placeholder. In order to properly merge the value for these cases,
we need to propagate the params up *before* serialization. Therefore I
removed the standalone param propagation phase and folded the logic into
the placeholder resolution phase.
PR Close#52195
I added these in an earlier PR when we were considering moving the empty
elements phase earlier. Since we decided not to do that, this commit
cleans up unnecessary references to the empty versions of the element to
simplify the code and types.
PR Close#52195
This adds the support of `if ` conditions with `as` clause when migrating to the control flow syntax.
It now adds the required semicolon before the `as` when migrating the template.
Before: `@if (user$ | async as user) {`
After: `@if (user$ | async; as user) {`
PR Close#52181
Fixes that the compiler was throwing an error if an element tag name is the same as a built-in prototype property (e.g. `constructor` or `toString`). The problem was that we were storing the tag names in an object literal with the `Object` prototype. These changes resolve the issue by creating an object without a prototype.
Fixes#52224.
PR Close#52225
Public afterRender phases have specific API guarantees which can be invalidated if the internal framework is implemented using them. Instead, the framework should use dedicated internal functions.
PR Close#52145
This commit drops the `ɵ` symbol from hydration annotation key: `__ɵnghData__` -> `__nghData__`. This helps ensure that there are no UTF8 symbols that might be damaged in case a web server is misconfigured.
Noticed while working on https://github.com/angular/angular/pull/52206.
PR Close#52207
We have the `DEFER_BLOCK_DEPENDENCY_INTERCEPTOR` DI token that we use in tests to intercept the dependency loading function from deferred blocks, however we were referencing it in a way that caused it to be retained in production bundles as well.
These changes guard the call site with `ngDevMode` since the token is only used for testing.
PR Close#52199
Contains the following minor improvements to the block entities migration:
* The migration won't be stopped anymore if it can't read a template file.
* The migration will exit early if a template doesn't contain the two characters we need to migrate.
* Reduced the amount of code that is wrapped by a try/catch to avoid suppressing errors.
PR Close#52209
DEPRECATED: NgProbeToken
The `NgProbeToken` is not used internally since the transition from View Engine to Ivy. The token has no utility and can be removed from applications and libraries.
PR Close#51396
Phase 2 sample code conversions per instructions in doc: https://docs.google.com/document/d/1QqnVK8Mc0O1gU9ctPrs-JJ42V9_dHCuEttD_01pXh34/edit
**Included**
1. ajs-quick-reference
Minor changes to remove references to NgModule. Converted sample to standalone.
2. architecture
Migrated the code sample. Made minor changes to remove references to NgModule. I explicitly deprecated the `architecture-module.md` page and removed it from the navigation.
4. deprecations / deprecations-guide
Migrated the code sample which required pulling NgModule and Reactive Forms material into a new `deprecated` folder. Made minor changes to clarify when advice was specific to NgModule (see `loadChildren` in particular).
5. displaying-data
Deleted this `displaying-data` sample entirely as there is no need for a sample app just to display a single, vanilla data binding in the deprecated `zone.md` page. Replaced reference in `zone.md` with an inline code snippet.
10. ngcontainer
Converted the code sample. There is no guide page for this sample. It can be displayed in Stackblitz
**Excluded**
3. cli-builder
Code sample is not an app; nothing to convert.
6-9 - related to getting-started and setup.
Waiting until Angular team is ready to proceed.
11. providers
This is in its own commit and PR 51918 because it may not make sense to convert. See that PR for details.
12. routing-with-urlmatcher
No work needed. Already Standalone.
13 schematics-for-libraries
Non-trivial (see doc notes) and Angular may decide to leave as is. Should have own PR.
14 setup
Non-trivial (see doc notes) and Angular may decide to leave as is. Should have own PR.
PR Close#51918
When the `viewport` triggers were first introduced, we ended up having to use a service to keep track of them, because using the same global event handling as the other events led to some inconsistent test failures. It looks like the failures were caused by the same bug fixed#52115 so now we can switch back to the previous approach which is a bit more compact.
PR Close#52156
This fixes an issue where `ng-template` nodes were removed even when used in other places than control flow directives.
Template to migrate:
```html
<ng-template #blockUsedElsewhere><div>Block</div></ng-template>
<ng-container *ngTemplateOutlet="blockUsedElsewhere"></ng-container>
```
Before:
```html
<ng-container *ngTemplateOutlet="blockUsedElsewhere"></ng-container>
```
After:
```html
<ng-template #blockUsedElsewhere><div>Block</div></ng-template>
<ng-container *ngTemplateOutlet="blockUsedElsewhere"></ng-container>
```
PR Close#52186
This adds the support of `let index as myIndex` in `*ngFor` for the control flow migration.
Before: `@for (itm of items; track itm)`
After: `@for (itm of items; track itm; let myIndex = $index)`
PR Close#52183
This commit splits the `render3/instructions/defer.ts` file (that contained most of the runtime code) into smalle
r files that are easier to maintain.
There are no functional changes in this PR, just organizing code.
PR Close#52152
In prod builds, selectors are optimized and spaces a removed. #48558 introduced a regression on selectors without spaces. This commit fixes tihs.
Fixes#49100
PR Close#49118
This change adjust the built-in for algorithm of dealing with embedded views
to update the repeater context (and more specifically - its index field)
only when views were added / removed "in the middle of LContainer" (in places
other than the LContainer end).
This skip iteration over the entire LContainer in most cases - and most importantly
in cases where no diff change was detected.
"
PR Close#52051
This adds a console warning to make it clear to users the migration is developer preview. It also shuffles around some code for better organization.
PR Close#52151
Currently the compiler allocates a variable slot to the `@for` loop expression which ends up unused since we don't store the result on the `LView`.
PR Close#52158
As part of the CircleCI migration it looks like we started
running the Bazel saucelabs job for all pull requests. This
was not done before because we weren't confident with the stability
of this job yet. This commit moves it back so that we don't block
pull requests with a job that is not considered stable.
The build job moved from CircleCI to GitHub actions, so we currently
mark all PRs as pending unnnecessarily.
In the future, this will be replaced by the unified status check. It's
set up here but was disabled at some point. Needs more investigation.
This adds `generate_api_docs` targets to all of the packages for which we publish api reference docs. One known issue here is that any type information that comes from another package (e.g. router depending on core) currently resolve to `any` because the other sources are not available in the program. This can be tackled in a follow-up commit.
This commit also updates the install patch for `@angular/build-tools` to use the local version of compiler-cli.
PR Close#52034
Non typed forms allow to pass null to nested groups when calling `formGroup.reset()`, this commit prevent an undefined access.
fixes#20509
PR Close#48830
A runtime error will be thrown if a non-standalone component is being rendered without its NgModule loaded in the browser. This error is thrown only in dev mode and only if the Angular option `forbidOrphanComponents` is set to true. The error contains useful info to find the orphan component in the source code.
PR Close#52061
A new method `isOrphanComponent` is added to the deps tracker API to check if the NgModule declaring this component, if exists, is loaded into the browser.
PR Close#52061
The flag `forbidOrphanRendering` is only set for non-standalone components, and indicates that the dev mode runtime should through error if the component is rendered without its ngModule loaded in the browser. This runtime error can help with further debugging.
PR Close#52061
A new flag added to the component's debug info to determine whether to throw runtime error (in dev mode) if component is being rendered without its NgModule. This flag is only set for non-standalone components.
PR Close#52061
Orphan component is an anti-pattern in Angular where a component is rendered while the NgModule declaring it is not installed. It is not easy to capture this scenario, specially in compile time. But it is possible to capture a special case in runtime where the component is being rendered without its NgModule even loaded into the browser. This change adds a flag in cli compiler option to enable such checking, and throwing a runtime exception if it happens. Note that such check is only done in dev mode.
Currently the check requires some generated code that is behind ngJitMode flag (i.e., call to ɵɵsetNgModuleScope), and the new flag can be set only if JIT mode is enabled (i.e., supportJitMode=true) otherwise an error will be thrown.
The orphan component is a main blocker for rolling out local compilation in g3. This option is needed for identifying and isolating such cases.
PR Close#52061
Based on recent discussions, these changes remove the Windows CI check because it has been too flaky for too long. Furthermore, we've concluded that the simulated file system in the compiler tests already catches the same set of bugs as running the tests on a real Windows system.
PR Close#52140
Using `afterRender` schedules long-living lifecycle hooks. Scheduling
such hooks inside reactive contexts could mean that many of the
same hooks would be scheduled, quickly piling up every time a
consumed signal changes. This is likely unintended and could degrade
application performance or result in unexpected behavior.
Additionally, scheduling `afterRender` inside a `computed` is considered
a side effect. Computed expressions are expected to be pure/ i.e. free
of side effects. We can avoid this caveat by detecting the reactive
context in development.
PR Close#52138
Using an `effect` inside a `computed` is a clear violation of
the conceptual idea of computed's being pure/ side-effect free.
Additionally, scheduling new effects from an existing actively
running effect is likely unintended as this could degrage application
performance or result in unintentional behaviors. Multiple long-living
effects would be scheduled every time the effect expressions runs.
For these reasons, we are explicitly preventing this pitfal, by
disallowing using `effect` inside reactive contexts.
PR Close#52138
This adds the new block syntax to dgeni docs pipeline, mainly copying
the way that elements (`<ng-content>` etc.) work. Actual doc content is
just a placeholder for this PR.
PR Close#52123
Creates set of unit tests for each function in the data transformation pipeline that enables injector metadata to be visualized as d3 graphs.
PR Close#51719
This commit introduces 2 new features into DevTools.
Directive level dependency inspection: Users can now view which dependencies their directives have injected in the property viewer tab. This view displays not only the dependency but also the resolution path that was used to service the injection.
Injector graph inspection: Users can now view a visualization of the element and environment hierarchies in their application. These trees are displayed separately but on the same page in the Injector Tree tab. User can click on individual injectors to view a list of all the providers configured in that injector, as well as highlight the resolution path from that injector to the root (with the corresponding environment injector connection highlighted as well).
PR Close#51719
Previously getDependenciesForTokenInInjector was unable to determine which node on a view serviced a specific injection. Now it is able to filter out those injections that did not come from the specific node for the NodeInjector passed into it.
Previously getInjectorMetadata was incorrectly looking up DOM elements for some directives (for example NgForOf) where an LContainer was created. Now the LContainer case is handled, and the non LContainer case uses `getFirstNativeNode` to more accurately get the element we want.
PR Close#51719
This commit adds support for extracting type alises. It currently
extracts the raw written type from the source without performing any
resolution, such as for resolving `typeof` queries, as current Angular
public APIs do not rely on this.
PR Close#52118
Animations events registered against the default renderer weren't registered against the animation renderer once it was loaded. This commit fixes this.
fixes#52076
PR Close#52087
Updates the Ivy AST to allow for `@switch` blocks to capture nested blocks that are not `@case` and `@default`. These blocks will be used for autocompletion in the language service.
These changes also update the logic for `@switch` and `@if` blocks so that they produce an AST node even if there are errors. The errors will still be surfaced to users, but producing AST nodes allows us to recover parts of the expression later if necessary.
PR Close#52136
This commit updates the score for one of the AIO tests. The problem is pre-existing (there is nothing in this PR that might cause the problem) and this change just brings the CI back to the "green" state.
PR Close#52116
This commit cleans up the signatures of `toSignal` to better handle the
types of situations that it might be used in, and produce better type
inference results.
Fixes#50687Fixes#50591
Co-authored-by: Andrew Scott <atscott@google.com>
PR Close#51991
This commit adds the ability to provide a function that will get called
immediately after the view transition is created. This will allow
developers to do things like add/remove classes from the DOM when the
transition animation is finished, skip the transition based on
application conditions, etc. Having access to the transition unlocks
just about every example outlined in https://developer.chrome.com/docs/web-platform/view-transitions.
Note that the timing of the `updateCallback` execution is in the spec as
being called asyncronously (https://drafts.csswg.org/css-view-transitions-1/#callbackdef-updatecallback).
This means the `onViewTransitionCreated` callback is guaranteed to
execute before the update callback which in turn means it is guaranteed
to execute before the view transition `ready`/animation. As a result, it
is safe/effictive to add classes to the document in the
`onViewTransitionCreated` function in order to control animations of
that transition and then remove those classes in the transition's `finished`
`Promise`. The animation also doesn't start until the `Promise` returned
by `updateCallback` resolves, so this would also guarantee that the
animation starts asynchronously.
resolves#51827
PR Close#52002
This commit introduces basic autocompletion support for the new block keywords. After typing `@`, the language service suggests the various block names.
PR Close#52121
PR #49672 added a g3-flavored migration for compiler option removal, but g3
doesn't use those options at all. So this migration is unnecessary and we
can remove it.
PR Close#52141
Adds a check to the viewport cleanup function to prevent it from re-processing elements that have been fully cleaned up, because it can lead to the `IntersectionObserver` being destroyed even though there are still pending triggers. This can happen, because we have cleanup callbacks both for the block is loaded, but also when the placeholder view is destroyed.
Fixes#52113.
PR Close#52115
Fixes that the new block syntax was generating instructions in the wrong order which meant that pipes were being declared too early. This meant that if the block is first in the template, any pipes used in it won't be able to inject things like `ChangeDetectorRef`.
These changes update the compiler and add a bunch of tests to ensure that pipes work as expected.
Fixes#52102.
PR Close#52112
Since expressions in event listener are added inside of a callback, type narrowing won't apply to them anymore. These changes add the logic to create a guard expression that will re-narrow the expression in the callback.
Fixes#52052.
PR Close#52069
Since expressions in event listener are added inside of a callback, type narrowing won't apply to them anymore. These changes add the logic to create a guard expression that will re-narrow the expression in the callback.
Fixes#52052.
PR Close#52069
When a route has loadComponent, its children should not inherit params and
data unless paramsInheritanceStrategy is 'always'.
fixes#52106
BREAKING CHANGE: Routes with `loadComponent` would incorrectly cause
child routes to inherit their data by default. The default
`paramsInheritanceStrategy` is `emptyOnly`. If parent data should be
inherited in child routes, this should be manually set to `always`.
PR Close#52114
This commit updates `@defer` logic related to handling `after` and `minimum` parameters tree-shakable.
If `after` or `minimum` was used on a `@loading` or `@placeholder` blocks, compiler generates an extra argument for the `ɵɵdefer` instruction. This extra argument is a reference to a function that brings timer-related code.
PR Close#52042
The error message now contains the code location of the component. It now looks like: "Error: NG01001: Orphan component found! Trying to render the component Main (at $PROJECT_ROOT/src/main.ts:8) without first loading the NgModule ..."
PR Close#51919
The current error stringifier only includes the class name. In this change a new stringifier is added which returns a more helpful string which includes the file path and line number. Note that this is only the case with components, and for other class types (directive, pipes) it will fallback to the current stringifier. Subsequent changes can cover the case of directive and pipes as well.
PR Close#51919
A new field `debugInfo` is added to the component definition. Now the runtime ɵsetClassDebugInfo stores the debug info for components in this new field.
PR Close#51919
A new statement will be generated for components which will attach some useful debug info to them to be used in runtime error handling. Currently this only happens in full and local compilation modes.
PR Close#51919
A new utility function `compileClassDebugInfo` is introduced which creates compile result necessary to generate statement for attaching some useful debug info into angular classes. An example of teh new statement would be:
```
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(Main, { className: "Main", filePath: "$PROJECT_ROOT/src/main.ts", lineNumber: 8 }); })();
```
Currently, the debug info contains:
- the class name
- the file path in which it is defined
- the line number in which it is defined
The debug info will be used in runtime to generate more helpful error messages.
PR Close#51919
This commit updates the tracking of dirty child views to be a flag
rather than a counter. This is a much more simple method and less likely
to get into the same 'always-wrong' situation that could happen with the
counter (if it is off by 1 once, it's off by 1 forever and you either
get infinite change detection or your view is never refreshed).
PR Close#51515
The current implementation assumes a qualified name consists of just two identifier, e.g., Foo.Bar. However it can be more nested, like Foo.Bar.Baz.XX.YY. While such nested patterns are quite uncommon and devs mostly just use two identifier here, the TS compiler seems to throw error if we make such assumption and it broke quite a lot of targets in g3 when compiled in local mode. So here we handle this nested property of qualified names.
PR Close#51947
This commit removes the `withNoDomReuse` function to minimize public API. The `withNoDomReuse` function used to disable DOM reuse, which is the main feature of the `provideClientHydration()`.
The `withNoDomReuse()` function was in the "developer preview" mode, so the removal happens without prior deprecation.
BREAKING CHANGE:
The `withNoDomReuse()` function was removed from the public API. If you need to disable hydration, you can exclude the `provideClientHydration()` call from provider list in your application (which would disable hydration features for the entire application) or use `ngSkipHydration` attribute to disable hydration for particular components. See this guide for additional information: https://angular.io/guide/hydration#how-to-skip-hydration-for-particular-components.
PR Close#52057
Fixes that, depending on the matching and import order, in some cases we weren't throwing the error saying that a directive matched multiple times on the same element.
Fixes#52072.
PR Close#52073
Cleans up the i18n placeholder resolution phase by extracting the
details of how the map is serialized into its own class, instead of
mixing it with the phase's traversal logic.
PR Close#51988
Template instructions exist in the parent view, but for the purposes of
the i18n placeholders, they should use the subTemplateIndex of the i18n
op wrapping their view.
PR Close#51988
The custom logic in the generate advance phase for i18n expressions did
not work in all cases. Instead we add a new phase to update the
expression's target op, and then allow the standard advance generation
code to determine the number of advance instructions needed.
Co-authored-by: Dylan Hunn <dylhunn@users.noreply.github.com>
PR Close#51988
Fills in values for sub-template placeholders in i18n messages. This
includes both the tag placeholders for ng-template tags, as well as
merging in any placeholders from the child i18n block.
PR Close#51988
Adds an additional sub-template index parameter to child i18n blocks
that are propagated from the root block. This additional paramete
indicates the index of the template in the i18n message.
Co-authored-by: Dylan Hunn <dylhunn@users.noreply.github.com>
PR Close#51988
This commit adds support for extracting function overloads. Interestingly, this worked in an earlier version when the code was extracting all statements in every source file, but the existing compiler API for extracting all exported declarations from an entry-point only returns the first function declaration in cases when there are overloads.
This also marks abstract classes as abstract, required inputs as required, and filters out Angular-private APIs.
PR Close#52040
This commit adds the code to mark newly created embedded views (that represent `@defer` block states) as dirty to indicate that the view sgould be checked during the next change detection cycle.
Resolves#52094.
PR Close#52095
We type check `@switch` blocks by generating identical TS `switch` statements in the TCB, however TS currently has a bug where parenthesized `switch` block expressions don't narrow their types. Since we use parenthesized expressions to wrap AST nodes for diagnostics, this will bug will affect all Angular-generated `switch` statements.
These changes work around the issue by generating `if`/`else if`/`else` statements that represent the `switch`.
Some alternatives that were considered:
1. Moving the `switch` expression to a constant - this is fairly simple to implement, but it won't fully resolve the narrowing issue since the same constant will have to be used in expressions inside the different cases.
2. Removing the outer-most parenthesis from the switch expression - this works and allows us to continue using switch statements, but because we use parenthesized expressions to map diagnostics to their template locations, I wasn't sure if it won't lead to worse template dignostics.
Fixes#52077.
PR Close#52110
This change adjust the equality comparator used by NgSwitch - now it
defaults to === from previously used ==. This change is based on the
following reasoning:
- align behaviour with the built-in switch block);
- improve performance (avoid type coercion);
- enable better type-checking.
BREAKING CHANGE:
the NgSwitch directive now defaults to the === equality operator,
migrating from the previously used ==. NgSwitch expressions and / or
individual condition values need adjusting to this stricter equality
check. The added warning message should help pinpointing NgSwitch
usages where adjustements are needed.
Fixes#33873
PR Close#51504
This change removes the `mutate` method from the `WritableSignal` interface and
completely drops it from the public API surface.
The initial API proposal for Angular signals included the mutate method, allowing
in-place modification of JS objects, without changing their references (identity).
This was based on the reasoning that identity change on modification is not necessary
as we can send the “modified” notification through the signals graph.
Unfortunately the signal-specific change notification is lost as soon as we read
signal value outside of a reactive context (outside of a reactive graph).
In other words - any code outside of the Angular signals library can’t know
that an object is modified.
Secondly, to make the mutate method work, we’ve defaulted the signal value equality function
to the one that considers non-primitive values as always different.
This is unfortunate for people working with immutable data structures
(this is notably the case for the popular state management libraries)
as the default equality function de-optimizes memoization in computed,
making the application less performant.
Given the above reasons we prefer to remove the mutate method in the signals library -
at least for now. There are just too many sharp edges and tradeoffs that we don’t fully
understand yet.
BREAKING CHANGE:
The `mutate` method was removed from the `WritableSignal` interface and completely
dropped from the public API surface. As an alternative please use the update method and
make immutable changes to the object.
Example before:
```typescript
items.mutate(itemsArray => itemsArray.push(newItem));
```
Example after:
```typescript
items.update(itemsArray => [itemsArray, …newItem]);
```
PR Close#51986
This commit reorganizes the Angular code a bit, and moves signals into a
newly defined `@angular/core/primitives` location. This will be used inside
g3 to allow non-Angular targets to depend on the signals core without
incurring a dependency on the whole framework.
PR Close#51986
This commit refactors the signals API surface of Angular out of the
//packages/core/src/signals package. This is done in preparation of moving
the core signals package into a new 'primitives' package that's decoupled
from the public API.
PR Close#51986
The code already supports `DatePipeConfig` to have only some properties
set, and not all. But the typing disallows it. This aligns the typing
with the code.
PR Close#51287
`provideClientHydration()` accepts new `HydrationFeature` : `HttpTransferCacheOptions`.
`withHttpTransferCacheOptions` accepts an option object:
* `includeHeaders` : list of headers entries to keep in the cache with the request
* `filter` a callback to determine if a request should be cached
* `includePostRequests`: to include POST requests in the allowed methods
Implements some of the features requested in #50117
PR Close#52029
Fixes that the compiler wasn't picking up pipes used inside defer block triggers as dependencies. We had implemented the `visitDeferredTrigger` visitor method, but it wasn't being called, because we weren't going through the `visitAll` method of the deferred block. We don't use `visitAll`, because child nodes have to be processed differently than the connected blocks and triggers.
Fixes#52068.
PR Close#52071
The `_enabledBlockTypes` config option was removed recently, since we've enabled @-syntax by default. This commit removes `_enabledBlockTypes` references from the `compiler-cli` test cases.
PR Close#52066
This commit adds a logic to produce a warning in case HttpClient doesn't use fetch during SSR.
It's recommended to use `fetch` for performance and compatibility reasons.
PR Close#52037
This change removes the `mutate` method from the `WritableSignal` interface and
completely drops it from the public API surface.
The initial API proposal for Angular signals included the mutate method, allowing
in-place modification of JS objects, without changing their references (identity).
This was based on the reasoning that identity change on modification is not necessary
as we can send the “modified” notification through the signals graph.
Unfortunately the signal-specific change notification is lost as soon as we read
signal value outside of a reactive context (outside of a reactive graph).
In other words - any code outside of the Angular signals library can’t know
that an object is modified.
Secondly, to make the mutate method work, we’ve defaulted the signal value equality function
to the one that considers non-primitive values as always different.
This is unfortunate for people working with immutable data structures
(this is notably the case for the popular state management libraries)
as the default equality function de-optimizes memoization in computed,
making the application less performant.
Given the above reasons we prefer to remove the mutate method in the signals library -
at least for now. There are just too many sharp edges and tradeoffs that we don’t fully
understand yet.
BREAKING CHANGE:
The `mutate` method was removed from the `WritableSignal` interface and completely
dropped from the public API surface. As an alternative please use the update method and
make immutable changes to the object.
Example before:
```typescript
items.mutate(itemsArray => itemsArray.push(newItem));
```
Example after:
```typescript
items.update(itemsArray => [itemsArray, …newItem]);
```
PR Close#51821
Two key refactors to enable deeper language service support for blocks:
(1) We now generate accurate source spans for the various block types. Additionally, all the top-level source spans for a block are now *inclusive* of all the connected or descending blocks. This helps the language service visit connected blocks.
(2) The language service's template visitor was previously skipping over the AST nodes corresponding to several block types. We are now careful to visit all such nodes.
PR Close#52038
Fixes a bug with REMOVE_STYLES_ON_COMPONENT_DESTROY when a component is destroyed and re-created, its previous stylesheets will not be re-used and instead a new stylesheet will still be created each time.
PR Close#52019
This commit adds runtime code to support `after` and `minimum` parameters in the `@placeholder` and `@loading` blocks. The code uses the `TimerScheduler` service added earlier for `on timer` triggers.
PR Close#52009
Adds an `UnknownBlock` node to the Ivy AST to represent blocks that haven't been recognized by the compiler. This will make it easier to integrate blocks into the language service.
PR Close#52047
Adds some logic to treat incomplete blocks as empty blocks so that we can recover from them. Also logs an error about the incomplete block.
PR Close#52047
Updates the lexer to parse blocks as incomplete, instead of throwing errors. This will allow us to better handle them further down in the pipeline.
PR Close#52047
Revert (with improvements of): dcf18dc74c
We recently landed a change that allows `toSignal` to be called
from within reactive contexts (e.g. `effect`/`computed`). After
more thorough investigatio and consideration with the team, we
feel like allowing `toSignal` to be called in such contexts is
encouraging non-ideal / hard-to-notice code patterns.
e.g. a new subscription to an observable is made every time `toSignal`
is invoked. There is no caching done here. Additionally, multiple new
subscriptions can trigger unintended side-effects- that may slow down
the app, result in incorrect/unexpected behavior or perform unnecessary
work.
Users should instead move the `toSignal` call outside of the `computed`
or `effect` and then read the signal values from within their `computed`. e.g.
```ts
computed(() => {
const smth = toSignal(coldObservable$)
return smth() + 2;
}
```
--> should instead be:
```ts
const smth = toSignal(coldObsverable$);
computed(() => smth() + 2);
```
In cases where a new subscription for each invocation is actually intended, a manual
subscription can be made. That way it's also much more obvious to users
that they are triggering side-effects every time, or causing new
subscriptions.
PR Close#52049
GC and render events can happen _while_ running scripts as well as
outside of the script blocks. The new metric entries capture both
the gc and render time happening in the scrip blocks.
PR Close#50771
This adds API doc extraction for interfaces, largely using the same code paths for classes. The primary difference between classes and interfaces is that classes have member _declarations_ while interfaces have member _signatures_. This largely doesn't matter for the purposes of extraction, but the types are distinct with no common base types, so we have to do a fair amount of type unioning and aliasing.
PR Close#52006
Upgrade the existing warning so it now logs an error instead, when an LCP element is determined to not be usings the `priority` attribute. Error is logged, not thrown.
PR Close#52004
When the `ts.Project` creates the language service plugin (in this case,
the Angular Language Service), it sets the project's language service to
the new language service returned by the plugin create:
https://sourcegraph.com/github.com/microsoft/TypeScript@b12af0fa2bbd4b015e59adcfb49988cea7f919a1/-/blob/src/server/project.ts?L2035-2044
The project may be reloaded in response to various events, such as a
change to the tsconfig file, which then recreates the plugin. When this
happens, the language service that gets passed to the plugin `create`
function will not be the typescript language service, but rather the
previous instance of the new language service returned by the last call
to `create`.
This commit ensures that subsequent calls to `create` for the
`NgLanguageService` plugin for a project after the first call are able
to retrieve and hold on to the _TypeScript_ language service.
fixes https://github.com/angular/vscode-ng-language-service/issues/1923
PR Close#51912
A couple tests were already passing, and just needed to be enabled. This includes tests pertaining to:
* ng-template
* host binding styling slots
* and host animation bindings
* some literal tests (which were missing some $foo$ escaped names)
We add pipeline-specific versions of the following tests, and enable them:
* A local refs test. The consts for the element attributes and the consts for local reference are collected in the reverse order, but the emitted template is functionally the same.
* A safe accesstest. Consider the expression `$any(val)?.foo`. `TemplateDefinitionBuilder` extracts a temporary variable: `($tmp_0_0$ = $ctx$.val) == null ? null : $tmp_0_0$.foo`. It presumably does this because it considers the `$any(...)` to be a function call. However, this is not a real call, so Template Pipeline safely ignores it and declines to generate a temporary.
* Another local refs test. AttributeMarker.Template is emitted at the end of the const array (instead of the middle)
PR Close#51950
Consider an `ng-template` which is generated as a result of a structural directive:
```
<div *ngFor="let inner of items"
(click)="onClick(inner)"
[title]="getTitle()"
>
```
This should logically expand into something like the following:
```
<ng-template [ngForOf]="..." >
<div (click)="..." [title]="..."></div>
</ng-template>
```
Note that the `(click)` handler and the `[title]` property are only present on the inner div, *not* on the enclosing generated `ng-template`.
Previously, Template Pipeline would place these bindings on *both* the tempate and the inner element.
However, we can't just remove them completely, because these bindings should still be matchable on the generated `ng-template` (which is very surprising, but nonetheless true).
We resolve this issue with two improvements:
(1) The ingestion step is now much smarter about determining not only if a binding is on a template element, but whether it actually targets that template element.
(2) We use `ExtractedAttributeOp` directly, rather than going through `BindingOp`, to cause the `ng-template` to still receive these bindings in its `consts` array for matching purposes.
PR Close#51950
For components, the parser already extracts the `important` property (and it is later disregarded). However, because host bindings use a totally separate parsing code path, this was never happing for host bindings.
Here, we add some code to the host style parsing phase to drop the `!important` suffix.
We could solve this category of problems for good by parsing host bindings with the same code as template bindings.
PR Close#51950
Previously, we always generated temporary variable declarations at the beginning of each view's update block. This is wrong, for two reasons:
1. Temporaries can be used in the create block
2. When listeners use temporaries, we should declare them inside the listener.
Now, we always place temporaries at the beginning of the enclosing OpList, and recursively try to generate them when we find a listener.
PR Close#51950
Currently, if there are 2 nested @defer blocks with the same dependency, Angular throws an error at runtime to indicate that there was a duplicate component def in the registry. This commit updates the logic to only append dependencies when they didn't previously exist in the registry.
PR Close#51964
#51885 patched a call site that threw an error but there were 2 others call that needed to be wrapped in the same way by a try/catch.
`initializeFully` is part of the calls in `responseWith(handleFetch)`.
Same #51885, throwing `SwCriticalError`allows the driver to fallback to `safeFetch` and ensure `responseWith` doesn't fail.
Fixes#50378
PR Close#51960
Currently the TCB for aliased `if` blocks looks something like this:
```
// Markup: `@if (expr; as alias) { {{alias}} }
if (block.condition) {
var alias = block.condition;
"" + alias;
}
```
The problem with this approach is that the type of `alias` won't be narrowed. This is something that `NgIf` currently supports.
These changes resolve the issue by emitting the variable outside the `if` block and using the variable reference instead:
```
// Markup: `@if (expr; as alias) { {{alias}} }
var alias = block.condition;
if (alias) {
"" + alias;
}
```
PR Close#51952
The context of an embedded view ref at some point was switched from a
getter to an actual assignable property. This is something we reverted
with the previous commit as it introduces additional complexity for our
generated code (in terms of closures capturing the `ctx`).
This change impacted the template outlet code because we actively relied
on swapping out the full context if the user changes it. Previousl,
before we allowed to swap out the context (in v16), we mutated the
initial view context if it didn't change structurally- and in other
cases the view was re-created. We improved this performance aspect with
the changes to allow for the context to be swapped out + actually also
fixed a bug where the initial context object was mutated and the user
could observe this change.
This commit adjusts for context not being replacable- while still
keeping the bugs fixed and preserving the performance wins of not
having to destroy/re-create the view whenever the context changes.
Benchmarks: https://hackmd.io/J0Ci_JzxQ0K1AA1omXhIQQ
PR Close#51887
This partially reverts commit a3e17190e7
and deprecates behavior added.
The context of an embedded view ref at some point was switched from a
getter to an actual assignable property. This is something we revert
as it introduces additional complexity for our generated code
(in terms of closures capturing the `ctx`), creates technical
limitations for Angular's internals and the usage pattern is rarely
used (and can be addressed via simple assignments, `Object.assign` or
the use of a proxy if replacing the full context object is still
desirable)
DEPRECATED: Swapping out the context object for `EmbeddedViewRef`
is no longer supported. Support for this was introduced with v12.0.0, but
this pattern is rarely used. There is no replacement, but you can use
simple assignments in most cases, or `Object.assign , or alternatively
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
as an example).
Also adds a warning if the deprecated
PR Close#51887
We are including a file, for some reason, that is outside of the root
dir. This breaks TypeScript/ or more specifically VSCode from picking
up this tsconfig- breaking path mappings and hence auto completion.
PR Close#51887
When adding a new view flag, you currently need to adjust the last number of the last
3 flags. All of these share the same number so the shifting ones can just use
the base-10 IndexWithinInitPhaseShift.
PR Close#51839
Reworks a few more places to output arrow functions instead of function declarations in order to reduce the amount of code we generate. Some of these places include:
* Factories in injectable definitions.
* Forward references.
* `dependencies` function in the component definition.
* `consts` function in the component definition.
PR Close#52010
Updates the TCB for `@for` loop blocks to allow nullable values. The runtime already supports it and this makes it easier to switch from `NgFor`.
Fixes#51993.
PR Close#51997
The new list reconcilation algorithm, an alternative to
the DefaultIterableListDiffer. It works by performing updates
in place instead of creating intermediate data describing changes
to apply. For lists expressed as an Array it performs additional
optimizations for the moves and swap scenarios.
The new list diffing approach is meant to be used in the new control
flow and should me much faster as compared to the ngFor with the
DefaultIterableListDiffer.
PR Close#51980
The template pipeline now supports basic forms of `defer` blocks. This includes the `loading`, `placeholder`, and `error` blocks, as well as the loading and placeholder configuration options.
Lazy dependencies and prefetch are not yet implemented.
PR Close#51942
Previously, we had many individual constants collected at different places in the template pipeline, using `job.addConst(...)`. Now, this trait can be used to cause any op or expression to receive const collection.
PR Close#51942
Ops with `ConsumesSlotOpTrait` have a self-xref, and are assigned a corresponding `slot`.
Ops with `UsesSlotIndexTrait` have a `target`-xref, and are assigned the `slot` of that `target`.
In both cases, the field name `slot` is used, but it means different things. Therefore, any op which both consumes and uses a slot will have a collision of two different meanings on its `slot` field.
This commit renames `slot` to `slotTarget` in the `UsesSlotIndexTrait`, to eliminate this collision.
PR Close#51942
Enables the new `@` block syntax by default by removing the `enabledBlockTypes` flags. There are still some internal flags that allow special use cases to opt out of the block syntax, like during XML parsing and when compiling older libraries (see #51979).
PR Close#51994
Increases the `minVersion` of component declarations that use bloks to v17 in order to indicate to users that they need to update if the library they're using is on the new syntax, while preserving backwards compatibility for libraries that do not use the syntax.
PR Close#51979
Adds some logic to enable parsing of block syntax in the linker. Note that the syntax is only enabled on code compiled with Angular v17 or later.
PR Close#51979
We were previously emitting pure functions as `function foo(args) {return bar;}`, but `TemplateDefinitionBuilder` uses arrow functions instead (`const foo = (args) => bar`). By matching this behavior, we can enable many additional tests.
PR Close#51961
This is a deceptively simple fix for a deep issue. Consider the following template:
```
<button [title]="myTitle" [id]="(auth().identity() | async)" [tabindex]="1">
```
`TemplateDefinitionBuilder` allocates the following variable (binding) slots:
v[0] = [title] binding
v[1] = [id] binding
v[2] = [tabindex] binding
v[3] = pipe binding
v[4] = pipe binding
As you can see, all three top-level property bindings were assigned variable indices. Then, variables for nested expressions were assigned.
Before this change, Template Pipeline would choose the following order:
v[0] = [title] binding
v[1] = [id] binding
v[2] = pipe binding
v[3] = pipe binding
v[4] = [tabindex] binding
With this order, nested expressions have their variables counted and assigned before subsequent top-level property bindings. This results in different variable indices for `pipeBinding` expressions that are not inside the final property binding.
However, this is not just different -- it's actually incorrect! Consider a case like the following:
```
<button [p1]="c ? (a | pipe) : 3" [p2]="b | pipe">
```
These pipe bindings are executed *conditionally*. This means that, because we don't count and assign all the "fixed" variable slots first, i.e. those belonging to the property bindings, their indices might end up incorrect, depending on whether or not a pipeBinding happened as part of the update block.
With this change, we count all variables on top-level ops first, and then descend into all expressions.
PR Close#51961
Fixes an issue where if animations are enabled, deferred blocks don't remove their placeholder blocks immediately from the DOM. The problem is that we register the event handlers in `afterRender` which runs outside the zone, but the logic that removes the DOM nodes during animations is tied to change detection.
These changes resolve the issue by binding the listeners inside the zone. This was the intention from the beginning, I just forgot that `afterRender` runs outside the zone.
Fixes#51970.
PR Close#51971
Currently, there is no change detection scheduled after triggering `on idle` condition, since `requestIdleCallback` is not patched by Zone.js. This commit invokes the callback in NgZone, so that the code that is invoked within the callback can use zones and a new change detection round is scheduled as needed.
Fixes#51973.
PR Close#51975
This API allows for inspection of a given injector to determine it's type (Element, Environment, Null) as well as it's "source".
- For Environment injectors the source is the source of the injector; `injector.source`.
- For Element injectors the name is the DOM Element that created the injector.
- For the Null Injector this is the string `"Null Injector"`.
PR Close#51900
This commit adds hydration support for repeaters (for loops) and empty blocks. The logic looks up a dehydrated view and use this information for hydration. Otherwise, DOM elements for a view are created from scratch.
PR Close#51920
An `if` block can specify an alias for its main expression. We now support these in the template pipeline:
- We generate a temporary variable for the original expression
- We pass the temporary to the `conditional` instruction's context argument
- We provide the alias's name in the ambient context variables map
The context variables map now also accepts a name whose lookup value on the context object is empty. This will be interpreted as a read of the entire context object.
PR Close#51931
This is a pure refactor: we previously crammed a lot of data into a complicated array on the conditional op. Now, we use a new conditional branch expression to store that information.
PR Close#51931
This entails adding a bit of extra logic to the existing conditional ingestion and corresponding phase, because `if` blocks lack a test expression.
Additionally, enable a couple more `switch` tests by resolving a curious issue -- we now consume a variable for conditionals.
PR Close#51931
Rather than rely on the empty element collapsing phase to run first, add
logic to the empty element phase to ignore pipes when deciding whether
to collapse an element.
PR Close#51876
Refactors the i18n handling to only pass the relevant information from
the i18n AST through to the IR, instead of passing the entire
I18nMetadata.
PR Close#51876
Matches the behavior of `TemplateDefinitionBuilder`, advancing to the
last element in the i18n block before evaluating i18n expressions.
PR Close#51876
Moves the empty element phase earlier, to before pipe creation. This
ensures that adjacent i18nStart/i18nEnd ops will be collapsed into a
isingle i18n op, rather than remaining uncollapsed if a pipe is inserted
between them.
PR Close#51876
This integration test aims to cover that we do not break the code splitting of the animation module when we use `provideAnimationsAsync()`.
PR Close#50738
`provideLazyLoadedAnimations()` returns providers which allow the lazy loading of the animation module.
Lazy loading of the animation code can shave off up to 16KB gzipped of the main bundle.
PR Close#50738
Adds support for defining `viewport`, `interaction` and `hover` triggers with no parameters. If the framework encounters such a case, it resolves the trigger to the root element of the `@placeholder` block. Triggers with no parameters have the following restrictions:
1. They have to be placed on an `@defer` block that has an `@placeholder`.
2. The `@placeholder` can only have one root node.
3. The root placeholder node has to be an element.
PR Close#51922
If a trigger element can't be accessed from the defer block, we don't generate any instructions for it. These changes add a diagnostic that will surface the error to users.
PR Close#51922
Prior to this change `this.isStable.pipe(first((isStable) => isStable)).toPromise()` had to be done in multiple places across the framework and the Angular CLI see https://github.com/angular/angular-cli/pull/25856#discussion_r1328158846. In the majority of cases an Observable based `isStable` API is not needed. This also removes the need for RXJS operator imports.
PR Close#51807
This commit updates the `if` and `switch` logic to support hydration. The logic attempts to find dehydrated views in containers while processing `if` and `switch` instructions. If a dehydrated is found, its used to further match elements. Otherwise, DOM elements for a view are created from scratch.
PR Close#51915
Previously, dehydrated views lookup was triggered only when ViewContainerRef was injected. The new control flow logic uses lower level APIs, thus having the code only in the ViewContainerRef is not sufficient.
This commit adds the logic to invoke the process of dehydrated views lookup from the `template` instruction, thus enabling it for new control flow instructions as well.
PR Close#51915
Changes `TemplateDefinitionBuilder` to output i18n message parameters in
sorted order to make it easier for the template pipeline to generate
identical output. This does not result in any functional change, but
will make it much easier to shared output golden files with the template
pipeline.
PR Close#51911
This commit updates hydration runtime code to avoid creating an empty array when we can avoid it. Instead, we just check whether the field is `null` directly (without using nullish coalescing).
PR Close#51917
#51891 introduces a new syntax that assigns a new meaning to the `@` and `}` in Angular templates. This is problematic for existing apps which may have the characters in their templates already, because it can lead to syntax errors.
These changes add an `ng update` schematic that will replace any usages of the special characters with their HTML entities.
PR Close#51905
Fixes that we were allocating slots for the expressions of `if`, `else if`, `switch` and `case` blocks which we weren't using for anything.
PR Close#51913
This commit updates runtime logic of defer blocks to schedule a single `requestIdleCallback` for a group of defer blocks created within a single change detection cycle (for example, as a result of a defer block being defined in a for loop).
PR Close#51750
The router currently restricts all further redirects after an absolute
redirect. Because there's no documented reason for _why_ this
restriction is in place, I'm now deeming this unnecessary. Developers
should not be restricted in this manner. Instead, configs that may
have caused infinite redirects in the past should be updated to not be
infinite. It is confusing to ignore configs with redirects after an
absolute redirect occurred because it creates different matching rules
depending on the whether an absolute redirect has happened or not.
For additional context on why I believe removing this restriction is
necessary, #13373 asks for allowing `redirectTo` to be a function. It
would make sense to allow this function to return a `UrlTree` like other
guards in the Router. When guards in the `Router` return `UrlTree`, they
cancel the current navigation and start a new one to re-do the route
matching. Since we're already in the router matching part, we don't need
to cancel the navigation. However, the restriction on absolute redirects
here then creates a weird situation where developers wouldn't see any
other redirects if they returned a `UrlTree` as an absolute redirect
from `redirectTo`.
resolves#39770
BREAKING CHANGE: Absolute redirects no longer prevent further redirects.
Route configurations may need to be adjusted to prevent infinite
redirects where additional redirects were previously ignored after an
absolute redirect occurred.
PR Close#51731
Currently the field encapsulation undergoes some static analysis to check if it is `ViewEncapsulation` enum. Such static check fails in local compilation mode in g3 as the symbol cannot be resolved. On the other hand this field has to be resolved statically as its value determined the generated code. So in local compilation mode we add a lighter resolving logic which relies only on local information.
PR Close#51848
Currently the field changeDetection undergoes some static analysis to check if it is `ChangeDetectionStrategy` enum. Such static check fails in local compilation mode in g3 as the symbol cannot be resolved. So in local compilation mode we bypass such resolving and just write the expression as is into the component definition.
PR Close#51848
On Safari, the cache might fail on methods like `match` with an `Internal error`. Critical errors allows to fallback to `safeFetch()` in the `Driver`.
fixes: #50378
PR Close#51885
Switches the syntax for blocks from `{#block}{/block}` to `@block {}` based on the feedback from the community.
Read more about the decision-making process in our blog: https://blog.angular.io/meet-angulars-new-control-flow-a02c6eee7843
The existing block types changed in the following ways:
**Conditional blocks:**
```html
<!-- Before -->
{#if cond}
Main content
{:else if otherCond}
Else if content
{:else}
Else content
{/if}
<!-- After -->
@if (cond) {
Main content
} @else if (otherCond) {
Else if content
} @else {
Else content
}
```
**Deferred blocks**
```html
<!-- Before -->
{#defer when isLoaded}
Main content
{:loading} Loading...
{:placeholder} <icon>pending</icon>
{:error} Failed to load
{/defer}
<!-- After -->
@defer (when isLoaded) {
Main content
} @loading {
Loading...
} @placeholder {
<icon>pending</icon>
} @error {
Failed to load
}
```
**Switch blocks:**
```html
<!-- Before -->
{#switch value}
{:case 1}
One
{:case 2}
Two
{:default}
Default
{/switch}
<!-- After -->
@switch (value) {
@case (1) {
One
}
@case (2) {
Two
}
@default {
Default
}
}
```
**For loops**
```html
<!-- Before -->
{#for item of items; track item}
{{item.name}}
{:empty} No items
{/for}
<!-- After -->
@for (item of items; track item) {
{{item.name}}
} @empty {
No items
}
```
PR Close#51891
This commit disables a couple newly-added tests related to `on idle` trigger condition for @defer blocks. Tests would be re-enabled back once we identify the reason of flakiness and fix it.
PR Close#51895
Reworks the `setClassMetadata` calls to generate arrow functions instead of full anonymous function declarations. While this won't have an effect on production bundle sizes, it's easier to read and it should lead to small parsing time gains in dev mode.
PR Close#51637
This commit adds a logic to handle `on immediate` conditions both as a main condition, as well as a prefetching condition (i.e. `prefetch on immediate`).
PR Close#51630
Adds support for `on viewport` and `prefetch on viewport` triggers which will load the deferred content when the element comes into the view.
PR Close#51874
Adds support for `on hover` and `prefetch on hover` triggers. Some code had to be moved around so it could be reused from the `on interaction` triggers.
PR Close#51874
Updates the logic that generates the instructions for the `on interaction` and `prefetch on interaction` triggers to their final shape. Now the instructions take two arguments:
1. `triggerIndex` - index at which to find the trigger in the view where it will be rendered.
2. `walkUpTimes` - tells the runtime how many views up it needs to go to find the trigger element. If the argument is omitted, it means that the trigger is in the same view as the deferred block. A positive number means that the runtime needs to go up X amount of times to find the trigger. A negative number means that the trigger is inside the root view of the placeholder block. Negative numbers are capped at -1 since the placeholder is always in the same position at runtime.
PR Close#51830
Reworks the compiler to use the API introduced in #51816 to match triggers to the element nodes they point to. This will be used to generate the new instructions for `on interaction` and `prefetch on interaction`.
PR Close#51830
The `NoopAnimationDriver` as static property of `AnimationDriver` prevents it from being removed by tree shaking. This commit deprecates it and exposes the `NoopAnimationDriver` on the public API to replace its usage.
DEPRECATED:
The `AnimationDriver.NOOP` symbol is deprecated, use `NoopAnimationDriver` instead.
PR Close#51843
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of type assertions.
PR Close#49754
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertions for example.
PR Close#49754
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertions for example.
PR Close#49754
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertions for example.
PR Close#49754
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertions for example.
PR Close#49754
The `Writable` type is usefull when we want overwrite readonly properties and we still want to maintain code navigation/reference. It should be use instead of `any` type assertion for example.
PR Close#49754
We control most flags via Starlark and therefore limit configuration
options via `tsconfig` to a minimum. We do not intend to support the
enabled block types option via Starlark, so this commit allows for
the option to be picked up.
(This is useful for benchmarking the new control flow blocks).
PR Close#51862
In Devtools bar chart we can see the total time for all the directive instances in one change detection run.
This PR changes the bar chart to display the total count and time for all directive instances instead of showing the time for each directive instance separately in one change detection run.
PR Close#50866
This change simply flip the flag which enables using the deps tracker in JIT compilation (the logic is already implemented in a previous PR). Some tests which depend on the old JIT implementation (e.g., patching the scope info into the type) are modified accordingly.
PR Close#51415
Using verification helpers such as `isComponent` may trigger JIT compilation. Now in some tests such compilation is made purposely to fail, and so in such cases any reference to the `depsTracker.clearScopeCacheFor` method will cause the exception to be thrown earlier than expected which results in teh test failure. Such scenario is the case in the next commit when we enable using the deps tracker in the jit compilation. Note that such failure is only for the framework tests and is a very edge case. The tests in downstream apps will not lead to such scenario of failure at all.
PR Close#51415
This commit adds an option to the view transition feature to skip the first transition.
This option is not available in RouterModule.forRoot.
resolves#51815
PR Close#51825
The `setupTestingRouter` function is a factory function for creating a
new instance of the `Router`. This function is effectively a no-op.
Developers should use `RouterModule.forRoot` or `provideRouter` in tests
instead.
BREAKING CHANGE: The `setupTestingRouter` function has been removed. Use
`RouterModule.forRoot` or `provideRouter` to setup the `Router` for
tests instead.
PR Close#51826
This PR moves the Observable subscription of toSignal outside of the
reactive context. As the result the toSignal calls are allowed in the
computed, effect and all other reactive consumers.
This is based on the reasoning that we already allow signals creation
in a reactive context. Plus a similar change was done to the async pipe
in the https://github.com/angular/angular/pull/50522Fixes#51027
PR Close#51831
This commit adds the necessary mechanisms to perform cleanup of prefetch triggers when resource loading starts. Previously, this logic was missing, which resulted in retaining those triggers.
PR Close#51856
So far this docs extraction has pulls API info from all exported symbols in the program. This commit changes to extracting only symbols that are exported via a specified entry-point. This commit also exports the docs entities through the compiler-cli `index.ts`.
PR Close#51828
This commit refactors the loadChildren callback execution of the router config loader
into a function that can be used with SSR for the purposes of route extraction.
PR Close#51818
Certain tools in g3 which dynamically bootstrap a component (e.g., custom routers) simply swallow the exception coming from bootstrapping the component and show an empty outlet. Such cases are very difficult to debug as the dev has no clue why the component was not rendered. As bad as this pattern is, fixing all such tools for a better error handling is beyond the scope of our effort. Instead, in this change we print the error messages coming from calculating component dependencies (part of component rendering) to the console for a better visibility into the error. This change only affects local compilation where the component dependencies are calculated in runtime. This change can potentially shed light into many failures of local compilation in g3.
PR Close#51824
Standalone component need to include the imported NgModules as part of their dependencies in order to be able to use the injection tokens coming from these NgModules. To do so, in this change the imported NgModules are included in the standalone component compilation scope.
PR Close#51819
Currently the compiler in local mode assumes that the standalone component imports are array expressions. This is not always true as they can be const variables as well. This change allow non-array expressions for standalone component imports field and passes that expression to the downstream tools such as deps tracker to compute the component's deps in runtime.
PR Close#51819
Current implementation assumes that NgModule imports/exports fields are always arrays and thus it concats them for the injector definition. But this is not always the case and imports/exports could be non-arrays such as const variable. Such pattern happens in g3 and so must be addressed.
PR Close#51819
Adds support for template type checking of the `track` expression of a `for` loop block. Tracking expressions are treated as any other expression for type checking, however we have some special validation that doesn't allow them to access template variables and local references.
PR Close#51690
Adds support for template type checking inside `for` blocks. It is implemented by generating a JS `for...of` statement inside the TCB. The various loop variables (e.g. `$index`) are implemented by declaring a local number variable.
PR Close#51690
Adds support for template type checking inside `if` blocks. It is implemented by generating a JS `if` statement inside the TCB which allows us to do type narrowing of the expression. The `as` parameter is implemented by declaring a variable inside the `if` statement.
PR Close#51690
Adds support for template type checking inside `switch` blocks. It is implemented by generating a JS `switch` statement inside the TCB which allows us to do type narrowing of the expression.
PR Close#51690
The browserUrlTree is only used to support the onSameUrlNavigation: 'ignore' logic. We can achieve this functionality without having this state tracked inside the Router. Instead, we can re-examine what ignore means: We don't want to rerun the matching logic, guards, or resolvers when we already know that nothing is changing.
Outside of the "navigated", there are two things that constitute a "change":
1. The browser URL might change. Because of skipLocationChange, the browser URL might not always match the internal state of the Router (we can navigate to a path but skip updating the browser URL). If we're navigating to a place that would change the browser URL, we should process the navigation. Theoretically, all we need to really do is update the browser URL instead of processing the whole navigation w/ guards, redirects, and resolvers. But this doesn't matter that much because the default value for runGuardsAndResolvers will skip all of this anyways.
2. The internal state of the Router might change. That is, we're navigating to a new path and may or may not be updating the updating the browser URL.
If either of the above are true, we process the navigation. If both are false, we aren't changing anything so we can safely ignore the navigation request (as long as onSameUrlNavigation === 'ignore').
Why is this change important?
* Simplification of Router internals. The Router has a lot of special case handling and one-offs to handle a limited set of scenarios. Removing these when possible makes the code easier to follow
PR Close#48065
Adds a utility to the `BoundTarget` that helps with resolving which element a deferred block is pointing to. We need a separate method for this, because deferred blocks have some special logic for where the trigger can be located.
PR Close#51816
When the `TargetBinder` was written, the only embedded-view-based nodes were templates, but now we have `{#if}`, `{#switch}` and `{#defer}` which have similar semantics. These changes rework the binder to account for the new nodes.
PR Close#51816
Content project allows the content to specify its own selector for matching against content projection slots, using the `ngProjectAs` special attribute. We can now treat this attribue specially, and generate the appropriate flag in the consts array, followed by the parsed CSS selector.
PR Close#51544
Supporting content projection requires us to emit three new kinds of output:
1. An `ngContentSelectors` field on the component metadata, which points to an array in the constant pool with all of the `select` attributes from `<ng-content>` elements.
2. One `projectionDef` instruction at the beginning of each root view template function for a component. That `projectionDef` points to a constant pool expression, which contains *parsed* selectors for all `<ng-content>` elements in the root's entire view tree.
3. A `projection` instruction for each `<ng-content>` slot in the view tree. These each get a data slot, a monotonically increasing "content slot", and a pointer to the tag's attributes in the component const array.
We support the first two features entirely within a new compilation phase.
The third feature, collection of processed attributes, is a bit trickier. We now treat `<ng-content>` tags as element-like ops, and use the normal attribute ingestion pipeline to process any attributes, and assign the appropriate `ConstIndex`.
**Note**: We also split up a number of the tests into two expectations files, one for the view functions, and one for other const listerals from the constant pool. This is because `TemplateDefinitionBuilder` emits the literals in a quirky order (mixed in with the view functions) due to how it lazily generates view functions. Our eager ordering is totally different, but by splitting the expectations, we can still share the same tests with `TemplateDefinitionBuilder`.
PR Close#51544
The new built-in control flow design includes calls to the `template` instruction with fewer arguments. This was previously handled implicitly, but it's more extensible to add an explicit flag to the template op to handle this case.
PR Close#51544
Although there are several pages, only `service-worker-getting-started.md` has an example.
That example code was migrated.
Worked around the few references to NgModule.
Other changes as follows:
**Revised "Getting Started"**
The original service worker example page (`service-worker-getting-started.md`) is full of holes! I don’t know how anyone got this working just by following this page
- it doesn’t tell you where to get the example (and it isn’t generated by AIO)
- it doesn’t tell you that ng serve doesn’t support service worker apps
- it mentions http-server in passing but not what that is or where to get it.
- several commands tell you to supply the “project-name” but (a) it doesn’t tell you how to find that name and (b) you never actually have to provide a name at all. That includes on the command that gets http-server going.
**Hid section on `ngsw-config` tool**
Hid the discussion of the `ngsw-config` tool in `service-worker-config.md` because
(a) the command invoke it didn't seem to work and (b) it referenced `<project-name>`
without explaining what that is or where to find it.
Left the hidden text in the page in case someone wants to do something about this.
Meanwhile, you seem to be able to edit the `ngsw-config.json` and then rebuild.
That should suffice.
**Disabled E2E**
The AIO CI will no longer attempt to run the (thin) E2E tests.
These tests could lightly test the app with the dev server but couldn't test the Service Worker aspects; that would require launching the app with something other than `ng serve` and the AIO CI is not set up for that.
The existing tests appeared to pass when run locally with the dev server.
However, only one of them actually ran; test runner reported.
"There were tests whose specified size is too big."
Decided to bypass E2E testing of this project for now.
PR Close#51687
The `malformedUriErrorHandler` is used as a recovery mechanism for when the `UrlSerializer`
throws an error when parsing a URL string. If custom error handling is
desired for this, it should instead be done inside the
`UrlSerializer.parse` method itself. There's no reason to have an entire
feature option built around what can otherwise just be `try...catch`.
BREAKING CHANGE: `malformedUriErrorHandler` is no longer available in
the `RouterModule.forRoot` options. URL parsing errors should instead be
handled in the `UrlSerializer.parse` method.
PR Close#51745
Currently deps tracker includes the exported scope of the exported NgModule only in the exported scope of that NgModule. This is in agreement with what AoT does today. But JIT diverges from this behavior by including these exported scopes into the compilation scope as well. Since deps tracker is going to be used for both AoT (local compilation mode) and JIT, the question might be which behavior the deps tracker should follow? Today it follows the AoT one, but it breaks some tests in Google which seem to depend on this behavior of JIT. So it is better to migrate deps tracker to what JIT does. This leads to a wider compilation scope in local compilation compared to full compilations, but it won't break any existing thing.
PR Close#51791
This change contains runtime logic needed to flatten the NgModule bootstrap field in local compilation mode. While it is quite odd to pass a "nested" array as NgModule bootstrap, it is still required to support this case in local compilation mode since it is supported in full compilation mode.
PR Close#51767
Today in local compilation mode the NgModule bootstrap definition is moved as it is into the runtime `ɵɵdefineNgModule`. This runtime was initially made for AoT full compilation mode and assumes that the bootstrap info is already flattened and resolved. This is not the case in local compilation where the bootstrap is the raw expression coming from the NgModule decorator and can be a nested array. To get around this problem we move the bootstrap along with other scope info (e.g., declarations, imports, exports) to the runtime`ɵɵsetNgModuleScope` to be further analyzed and flattened in runtime.
PR Close#51767
This change flattens the imports info on standalone component decorators in runtime dev mode by adding flattening logic to the deps tracker. Such flattening has no effect in AoT full compilation mode since these arrays are already resolved and flattened by AoT static analysis, but in local compilation mode it is needed since the raw array as appears on the component decorator will be passed to the deps tracker, and so it needs to be flattened.
This change does not affect prod runtime since deps tracker is only used in dev mode.
PR Close#51767
This change flattens the imports/exports/declarations info on ngModule decorators in runtime dev mode by adding flattening logic to the runtime `ɵɵsetNgModuleScope`. Such flattening has no effect in AoT full compilation mode since these arrays are already resolved and flattened by AoT static analysis, but in local compilation mode it is needed since the raw array as appears on the NgModule decorator will be passed to the runtime `ɵɵsetNgModuleScope`, and so it needs to be flattened.
This change has to effect on prod runtime as `ɵɵsetNgModuleScope` is not used in prod.
PR Close#51767
Currently when ESBuild bundles an application importing from
`@angular/core`, the signals library will be discovered during
export analysis. ESBuild will come across the constants for the reactive
signal graph- and end up considering some of these as side-effects given
the pattern of using a spread assignment for extending from e.g.
`REACTIVE_NODE` (a similar issue may occur if we e.g. extend from the
computed reactive node).
See more details on the issue: https://github.com/evanw/esbuild/issues/3392
Even though, ESBuild preserves these constants now, and all of its
dependencies— Terser will consider these as side-effect free and
eliminate these constants. This may require multiple passes though, and
might not be sufficient, depending on the chain of reactive node
extensions. E.g. in the signals branch we noticed some constants
unnecessarily being preserved.
PR Close#51809
Based on top of #51717
This commit adds extraction for enums, pipes, and NgModules. It also adds a couple of tests for JsDoc extraction that weren't covered in the previous commit.
PR Close#51733
Based on top of #51713
This commit adds docs extraction for information provided in JsDoc comments, including descriptions and Jsdoc tags.
PR Close#51733
Based on top of #51697
Adds extraction for accessors (getters/setters), rest params, and resolved type info for everything so far. This also refactors function extraction into a new class and splits tests for common class info and directive info into separate files.
PR Close#51733
Based on top of #51685
This expands on the extraction with information for directives, including inputs and outputs. As part of this change, I've refactored the extraction code related to class and to directives into their own extractor classes to more cleanly separate extraction logic based on type of statement.
PR Close#51733
Based on top of #51682
This expands on the skeleton previously added to extract docs info for classes, including properties, methods, and method parameters. Type information and Angular-specific info (e.g. inputs) will come in future PRs.
PR Close#51733
This commit adds a barebones skeleton for extracting information to be used for extracting info that can be used for API reference generation. Subsequent PRs will expand on this with increasingly real extraction. I started with @alxhub's #51615 and very slightly polished to get to this minimal commit.
PR Close#51733
This commit adds support for zone.js 0.14.0 and drops support for older versions
BREAKING CHANGE: Angular now required `zone.js` version `~0.14.0`
PR Close#51774
Another try at deflaking the tests on Windows. I'm trying a couple of fixes here:
1. I noticed that it's usually the indexer tests that fail during flaky runs. These tests also happen to be the only ones that don't pass in the `files` argument of `NgtscTestEnvironment.setup`. When `files` isn't passed in, we don't hit the file path that sets up the `MockFileSystem`. With these changes I make it so that we always initialize the mock file system.
2. The missing file system error usually comes from the `absoluteFrom` call that initializes the optional `workingDir` argument. My theory is that because it's a default value for an argument, it gets called too early before everything is initialized. These changes move the `absoluteFrom` call further down until it's needed.
PR Close#51804
upgrade the warning for lazy-loaded lcp images when using NgOptimizedImage to an error
BREAKING CHANGE:
Previously when NgOptimizedImage directive detected that an LCP image is lazy-loaded, a console warning was produced. Now the directive throws an error to make it more discoverable in a console. If you receive this error, refer to this guide for additional information: https://angular.io/guide/image-directive#step-4-mark-images-as-priority
PR Close#51748
Terser does not treat `Symbol` as side-effect free- so if we end up with
a symbol export being loaded, it will result in the symbol being
retained.
We noticed this in the signals prototyping where symbols exported
from `computed` ended up appearing in symbol bundling tests.
PR Close#51776
This commit moves the destroy logic from 'effect' in the lower-level
'watch' so this implementation is shared among varius watch implementations.
PR Close#51757
Certain code patterns and tools in Google (and possibly 3P world) lead to the situation that a component is bootstrapped/rendered without its ng-module being loaded in the browser. Technically speaking this should be an anti-pattern since the ng-module could contain some runtime logic (e.g., providing something, calling some services, etc) and its not being loaded leads to unexpected behaviour. However, in many cases ng-module is an empty class and its only usage is for providing scope, and since in AoT full compilation mode we already hard-code dependencies into components so we can get away with not loading the ng-module. But in AoT local compilation mode it is not possible to get away since the component's dependencies are computed in runtime and the presence of the corresponding ng-module in the browser is needed. For this reason in this change it is forbidden to attempt to render a component without first loading its ng-module in local compilation mode and an explicit error message is created to make this situation clear. This error message can help with catching such cases when running TGP in Google.
It would be an interesting question as to whether to ban this situation in full compilation mode as well, as it is error prone and these errors are sometimes very hard to debug.
PR Close#51726
Use the head_ref value for the conncurency group on ci-priviledged rather than the ref, so that the
main ref is not used and cancelling across pull requests and the main branch
PR Close#51784
This commit removes access to deep imports and `zone-testing-bundle` and `zone-testing-node-bundle`
This commit removed access to deep and legacy `dist` imports. `zone-testing-bundle` and `zone-testing-node-bundle` are also no longer generated.
BREAKING CHANGE:
Deep and legacy `dist/` imports like `zone.js/bundles/zone-testing.js` and `zone.js/dist/zone` are no longer allowed. `zone-testing-bundle` and `zone-testing-node-bundle` are also no longer part of the package.
The proper way to import `zone.js` and `zone.js/testing` is:
```js
import 'zone.js';
import 'zone.js/testing';
```
PR Close#51752
This commit adds explicit type annotations to the reactive node prototype objects,
such that the prototypes are type-checked against the interface they are supposed
to (partially) implement. This also allows IDEs to better track usages of reactive
node properties, improving code navigation.
PR Close#51722
When a producer is no longer used, the consumer has to update its internal data structure
that keeps track of all producers. There used to be an issue where only half of the stale
producers would actually be removed from this data structure, as the intended upper bound
of the number of producers to remove would decrease with each removed producer, therefore
not reaching all producers that should be removed from the data structure.
This commit fixes the issue by truncating the arrays directly, without going through
individual `pop` operations. An assertion that would catch the inconsistent state in
the internal data structures of the signal graph has been introduced.
PR Close#51722
* Updates two of the md files to prioritize standalone components/architecture
* Updates three examples referenced in the guides
* Updates the svg diagram to reference the EnvironmentInjector instead of the ModuleInjector
PR Close#51572
BREAKING CHANGE: Node.js v16 support has been removed and the minimum support version has been bumped to 18.13.0.
Node.js v16 is planned to be End-of-Life on 2023-09-11. Angular will stop supporting Node.js v16 in Angular v17. For Node.js release schedule details, please see: https://github.com/nodejs/release#release-schedule
PR Close#51755
The `verifyPlaceholdersIntegrity` check in the compliance tests was basically a noop, because it was returning false inside a `forEach` callback. Fixing it revealed that it had fallen out of date, because one of the regexes it uses was incorrect. The problem is that it assumed the placeholder keys would always be string literals, however it's possible that they're identifiers. These changes resolve the issue by not looking at the keys at all since we don't do anything with them.
PR Close#51751
This commit updates the `jasmine.DEFAULT_TIMEOUT_INTERVAL` value for some AIO tests from 10 -> 20 seconds to give more time to complete processing. This commit also refactors tests to use async/await pattern.
PR Close#51747
Adds support for passing in `@Component.styles` as a string. Also introduces a new `styleUrl` property on `@Component` for providing a single stylesheet. This is more convenient for the most common case where a component only has one stylesheet associated with it.
PR Close#51715
The code for detecting a Windows CI run from #51701 didn't work, because Bazel isolates the environment variables. These changes work around the issue by passing in a custom variable with the `--test_env` flag.
PR Close#51738
E2E tests passed locally
**Added `readme.md` to the example code**
This explains how to build and run the example for both English and French.
**Archived `i18n-optional-manual-runtime-locale.md`**
I was asked to cut out a substantial swath of this page by reviewer "zip-fa". All that remained was a brief paragraph. I removed the page from the navigation after copying the remaining text to `i18n-optional-import-global-variants.md`. The page is still reachable by 3rd party links.
PR Close#51589
Heavily reworked with advice from Alan Agius.
FWIW
* `ng test` fails because there are no unit tests
* `yarn e2e` builds but fails - `Unable to start a WebDriver session.`
**Added `readme.md` to sample code**
Makes it easier for the casual downloader to try the example.
**Added `universal-ngmodule`**
The existing ngModule-based doc has a lot of guidance for developers who are still building with NgModule. Given that we are preserving the existing NgModule guidance (with modifications), it seems prudent to preserve the NgModule form of the Universal guidance. So I copied the existing guide and code to `universal-ngmodule` and added it to the left-side navigation under the "NgModules" sub-tree.
Warning: it retains all of the faults of the original guide ... faults that were addressed in the current revision.
PR Close#51564
Currently internally Angular has some customized tsconfig files, because we don't align with the tsconfig of the rest of g3. These changes enable `noImplicitReturns` and `noPropertyAccessFromIndexSignature` to align better with the internal config.
PR Close#51728
Previously effects were queued as they became dirty, and this queue was
flushed at various checkpoints during the change detection cycle. The result
was that change detection _was_ the effect runner, and without executing CD,
effects would not execute. This leads a particular tradeoff:
* effects are subject to unidirectional data flow (bad for dx)
* effects don't cause a new round of CD (good/bad depending on use case)
* effects can be used to implement control flow efficiently (desirable)
This commit changes the scheduling mechanism. Effects are now scheduled via
the microtask queue. This changes the tradeoffs:
* effects are no longer limited by unidirectional data flow (easy dx)
* effects registered in the Angular zone will trigger CD after they run
(same as `Promise.resolve` really)
* the public `effect()` type of effect probably isn't a good building block
for our built-in control flow, and we'll need a new internal abstraction.
As `effect()` is in developer preview, changing the execution timing is not
considered breaking even though it may impact current users.
PR Close#51049
The View Transitions API enables easy animations when transitioning between different DOM states. This commit adds an opt-in feature to the Router which runs the component activation and deactivation logic in the document.startViewTransition callback. If the browser does not support this API, route activation and deactivation will happen synchronously.
resolves#49401
PR Close#51314
The experimental tag is part of the stability tags along with "deprecated". This commit updates some code to pick up experimental as well.
PR Close#51712
The localize package intentionally duplicates some logic from the
compiler to avoid adding a dependency. This is now an error in the
packaging rule to prevent common pitfalls/code duplication. Here it's
an explicit decision though so we mark it as such and ask for the check
to be ignored for the particular import.
PR Close#51500
PR Close#51558
Improves the error handling story for after*Render by delegating errors to an ErrorHandler, so that one failure does not break every callback.
PR Close#51662
For versions 5.x through 8.x, this is based on the `package.json` file of `@angular/compiler-cli`.
For versions 2.x through 4.x, this is based on Angular's changelog.
PR Close#51645
To further modernize and improve the performance of the i18n digest generation,
The 64-bit aspects of the process now use the native `BigInt` instead of a
custom JavaScript implementation. This removes the need for the big_integer
helper code and associated tests as the code was not used anywhere else in the
framework. Only the `BigInt` constructor, `BigInt.asUintN` function, and
`.toString` function are currently used. `BigInt` literals can unfortunately
not yet be used due to the bazel test devmode setup which compiles the TypeScript
code at an EcmaScript level that does not yet support the literals.
Browser support information:
- BigInt constructor: https://caniuse.com/mdn-javascript_builtins_bigint_bigint
- BigInt asUintN: https://caniuse.com/mdn-javascript_builtins_bigint_asuintn
- BigInt toString: https://caniuse.com/mdn-javascript_builtins_bigint_tostring
PR Close#48321
With #51148, the `ngComponentOutlet` directive now supports inputs.
This allows a less verbose and simpler API to instantiate components dynamicaly.
Fixes#49875
PR Close#49915
This commit update the lock file to force a new `node_modules` cache as this causes the patch to fail due to GitHub caching and at present, there is also no way to provide a key to invalidate the cache.
PR Close#51652
This is needed to better support native ESM modules and avoid the otherwise necessary deep imports like `zone.js/fesm2015/zone-node.js` due to disallowed directory imports.
PR Close#51652
For redirects, most of the logic between wildcard and regular redirects
is identical. Combine what can be combined there. Once that was done,
the first part of the matching for redirects looks almost identical to the regular
matching. Create helpers and combine simplify code where possible there
as well.
PR Close#51543
This commit updates the return types of the matching functions to only
return an array when more than one return value is actually possible.
PR Close#51543
Reworks the pure functions to use arrow functions with an implicit return instead of function expressions. This allows us to shave off some bytes for each pure function, because we can avoid some of the syntax.
PR Close#51668
This commit updates the logic to add `prefetch on idle` support for defer blocks. Previously, the `on idle` logic was already implemented for the main loading and rendering. This commit reuses the same logic to bring it to the prefetching mechanism.
PR Close#51629
This flag allows message event listeners to prevent callbacks from executing within the NgZone if they contain a special `__ignore_ng_zone__` flag.
This functionality is built with Angular DevTools in mind, where it prevents an infinite change detection loop in inspecting applications that have message event listeners:
CD -> Inspected app emits componentTreeDirty event to DevTools -> DevTools emits event to get new component Tree from Inspected app -> Inspected app message event listener fires -> CD
PR Close#51339
This commit removes the `urlHandlingStrategy` from the public Router's API
BREAKING CHANGE:
`urlHandlingStrategy` has been removed from the Router public API.
This should instead be configured through the provideRouter or RouterModule.forRoot APIs.
PR Close#51631
These changes build on top of #51514 to add support for advanced expressions inside the `track` parameter of `for` loop blocks. There are two different outputs that the compiler can generate:
1. If the tracking function only references the item or `$index`, the compiler generates a pure arrow function as a constant references in the `repeaterCreate` instruction.
2. If the tracking function has references to properties outside of the `for` loop block, the compiler will rewrite those references to go through `this` and generate a function declaration. The runtime will `bind` the declaration to the current component instance so that the rewritten `this` references are resolved correctly.
Advanced tracking expression come with the following limitations to ensure the best possible performance:
1. They can only reference the item, `$index` and properties directly on the component instance. This means that there'll be an error when accessing this like local template variables and references. While we could get this to work, we would have to traverse the context tree at runtime which will degrade the performance of the loop, because it's a linear time operation that is performed on each comparison. Furthermore, allowing local references would require us re-evaluate the list when any one of them has changed.
2. Pipes aren't allowed inside the tracking function.
3. Object literals and pipes used inside the tracking expression will be recreated on each invocation.
PR Close#51618
Adds an instruction that allows us to access the containing component instance directly instead of having to traverse the context tree. This will be necessary for the tracking function of `for` loop blocks.
PR Close#51618
Adds type checking for the contents of `if`, `switch` and `for` blocks.
**Note:** this is just an initial implementation to get some basic type checking working and to figure out the testing setup. We'll need special TCB structures for this syntax so that we can support type narrowing.
PR Close#51570
When `preserveWhitespaces` is enabled, `switch` blocks can end up with content inside their main block due to the indentation that is usually used for the nested cases. This was tripping up the validation that doesn't allow content inside the main block of `switch`.
These changes update the validation to ignore empty text nodes.
PR Close#51570
This commit updates the runtime implementation of defer blocks to avoid their triggering on the server. This behavior was described in the RFC (https://github.com/angular/angular/discussions/50716, see "Server Side Rendering Behavior" section): only a placeholder is rendered on the server at this moment. This commit also updates the logic to make sure that the placeholder content is hydrated after SSR.
PR Close#51530
This commit fixes a bug in the change detection algorithm that would
ignore the `OnPush`/dirty flag of a component's host when it is created
dynamically. That is, `OnPush` components that were not marked dirty but
were created as embedded views would have their host bindings and `ngDoCheck`
function always run even if they were not dirty.
BREAKING CHANGE: `OnPush` components that are created dynamically now
only have their host bindings refreshed and `ngDoCheck run` during change
detection if they are dirty.
Previously, a bug in the change detection would result in the `OnPush`
configuration of dynamically created components to be ignored when
executing host bindings and the `ngDoCheck` function. This is
rarely encountered but can happen if code has a handle on the
`ComponentRef` instance and updates values read in the `OnPush`
component template without then calling either `markForCheck` or
`detectChanges` on that component's `ChangeDetectorRef`.
PR Close#51356
This commit refactors the router internals to track state inside a separate
`StateManager`. This helps open the door to managing the state in
different, swappable providers. The current interface needed by the
Router is: `currentUrlTree`, `rawUrlTree`, `browserUrlTree`,
`routerState`, and `handleNavigationEvent` (other properties are because
some router properties are writeable when they shouldn't be). This is
a suprisingly small interface and can hopefully be made smaller in the
future (i.e. removing 1 or more of the 3 tracked of `UrlTree`s).
PR Close#48481
This commit switches the signals library from a bidirectional symmetric
dependency graph using weak references, to a bidirectional _asymmetric_
graph which uses strong references. This is made possible with a reference
counting algorithm which only tracks producer -> consumer references for
effect-like "live" consumers, preventing memory leaks.
The new algorithm should be simpler and faster than the previous
implementation as weak references are fairly slow to create and traverse.
A tradeoff is that non-live consumers must now poll their producers when
read, as they cannot rely on dirty notifications.
As part of this refactoring, the `ReactiveNode` class is replaced with an
interface instead, and methods are moved to standalone functions. This is
paired with instantiating individual signals/computeds via `Object.create`
against a prototype node which contains static or initial values. This
technique, in conjunction with the rest, greatly improves the performance
of node creation.
PR Close#51226
In preparation for adding support for phases to after*Render, which will increase the implementation size, this commit splits out the optional logic so that it can be tree-shaken and dynamically loaded.
PR Close#51541
`NGMODULE_VE_DEPENDENCY_ON_IVY_LIB` was a ViewEngine related error. This commit removes the doc page but keeps a redirection for older versions still throwing this error.
PR Close#51588
None of the guide pages mentions ngModules. Only `observables-in-angular` needed conversion to Standalone.
However, some of the guide pages reflect old versions of RxJS, including signatures that are no longer valid. These have been corrected.
More significantly, *the existing guide is pretty bad at explaining RxJS and its usage*. It was written (by me I think) in the very early days of Angular and Angular RxJS instruction. I've taught numerous "RxJS in Angular" classes since and learned from that experience what does and does not work with students.
There was neither the time nor the charter to completely overhaul this guide. But this commit attempts to remove what flops with students and to bring the teaching closer to what seems more effectively. I hope reviewers agree that my revisions are an improvement.
**Revised Overview**
The overview doc, `observables.md`, had a few errors (ex: `next` is NOT REQUIRED) and deprecated patterns (you now must pass the Observer object to `subscribe`).
More importantly, it was wildly overcomplicated and scary, especially when it got into multi-casting.
Moved the multi-casting section to "RxJS Library" and rewrote it (with working example) for simplicity and context.
I made other changes in an effort to make this an overview that is more comprehensive and more clear. I paid particular attention to the "Basic usage and terms" section.
Finally, I relocated the "Naming conventions for observables" section here from `rx-library`. This is the section that describes the dollar-sign convention. It made more sense for it to be here.
**Revised "RxJS Library" page and code**
*RxJS no longer supports chaining* and hasn't for a very long time. Removed note in `rx-library.md` that suggested you could use operator chaining.
The RxJS `pipe` discussion in the "Operators" section was just weird. Almost no one calls the `pipe` function. We certainly should *start* there. We should start with how people actually use operators - by adding them to the argument list of the `Observable.pipe()` method.
I kept the original `pipe` function example but subordinated it in a "callout". Most readers will (and should) ignore it.
`Subject` is a *critically important RxJS mechanism for creating custom observables*. It was completely missing from the list of observable creators on this guide page. So I added it to the "Observable creation functions" section of the guide and wrote an accompanying `MessageService` code sample (see the new `rx-library/app/` folder).
The `MessageService` is a pretty common pattern in Angular apps - far more common than creating an observable from a counter or an event, two of the creation patterns currently on this page.
This new section also afforded an opportunity to show how RxJS helps with building loosely coupled applications. We will soon be talking about Signals. Many will wonder whether and when they should still use RxJS.
At least a partial answer is that RxJS is really good at progressively combining and enhancing streams of data as they cross component boundaries. Of course you can pass signals around; but they are not as rich in transformers as RxJS. This is where RxJS shines.
**Revised "Comparing observables"**
The Promises section in `comparing-observables.md` had many errors and misleading remarks.
The comparison of error handling was especially egregious; the code example for that was nonsense.
The "Chain" sub-section was really about transforming values. It also failed to demonstrate chaining promise `.then`s.
Reworked these sub-sections and improved the code samples to match.
PR Close#51516
The data `Observable` is not updated unless there have been changes to
the object. The current diffing does not look at `symbol` keys of the
object but the `title` property is stored as a private `symbol`. This
commit updates the object diffing to include symbols.
fixes#51401
PR Close#51561
We temporarily enable video recording for Saucelabs bazel tests. We are
seeing some flakiness here, and before we can replace the legacy job,
we should understand why the browsers sometimes disconnect.
PR Close#51533
Saucelabs seemingly has increased the maximum idle timeout. So we
leverage that to improve stability of our tests. Useful when e.g.
the heartbeat webdriver commands are for some reasons delayed.
PR Close#51533
- Emphasized the importance of using the same InjectionToken instance for both provider and injection call.
- Added examples to illustrate correct usages to prevent NullInjectorError.
PR Close#51386
This change aligns the settings between G3 and P3 as `REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT` is already set to `true` internally.
BREAKING CHANGE: `REMOVE_STYLES_ON_COMPONENT_DESTROY` default value is now `true`. This causes CSS of components to be removed from the DOM when destroyed. You retain the previous behaviour by providing the `REMOVE_STYLES_ON_COMPONENT_DESTROY` injection token.
```ts
import {REMOVE_STYLES_ON_COMPONENT_DESTROY} from '@angular/platform-browser';
...
providers: [{
provide: REMOVE_STYLES_ON_COMPONENT_DESTROY,
useValue: false,
}]
```
PR Close#51571
**Unit Testing Code Does Not Compile**
The compilation error is:
```
The compilation error is
./src/testing/http-client.spec.ts - Error: Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: /home/projects/obk3vc--run/src/testing/http-client.spec.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
```
I’m not sure what to say about unit testing HTTP in a full Standalone app. Is it different?
_This is the only known remaining defect in this conversion of HTTP to Standalone._
**Edited content of `http-request-data-from-server.md`**
The current version of this page is confusing. In particular
* It tells readers they **should always unsubscribe** from the HttpClient method calls. This is *not true* and this example doesn't even do it. I replaced this instruction with more nuanced advice and an explanation of why it is OK to not unsubscribe to HttpClient methods.
* There is a "helpful" note about using the RxJS `map` operator to transform the response. This is *not "helpfulf"*. It is *confusing* because the sample doesn't use `map` anywhere. It was unnecessary here, even if it might be helpful elsewhere. I removed this note.
* The "Requesting a typed response" section seemed unclear to me, particularly because the guide begins with a `get` request that already has the `Config` return type specification. My revision attempts to make this more clear.
* The bold "callout" about the `observe` and `responseType` options appears out of nowhere after "Requesting a typed response". It's disconcerting at best. I moved it to the bottom of the page and linked to it from the `options` discussion at the top.
I made a few other revisions that I hope improve the readability of this page.
**Corrected `http-make-jsonp-request.md`**
The JSONP example, handwritten in the guide page, would not have compiled. I added one that does to `heroes.service.ts` and displayed it on this page.
**Corrected `http-handle-request-errors.md`
This page ended with a section called "Sending data to a server" that introduces PUT, POST, and DELETE. These features have nothing to do with error handling and the verbiage here duplicates the opening paragraphs of the next topic which does: "Send data to a server". So I deleted this section from the error handling guide page.
**Archived http-setup-server-communication.md**
`http-setup-server-communication.md` appears to be the original long document that has since been divided over the other pages in this folder.
It shouldn’t be in the reader’s flow. I did update it for Standalone. But I also removed it from left-nav and marked as archived.
PR Close#51400
This commit removes deprecated properties on the Router. These are meant
to be configured through DI and not meant to be changed during runtime.
BREAKING CHANGE: The following Router properties have been removed from
the public API:
- canceledNavigationResolution
- paramsInheritanceStrategy
- titleStrategy
- urlUpdateStrategy
- malformedUriErrorHandler
These should instead be configured through the `provideRouter` or
`RouterModule.forRoot` APIs.
PR Close#51502
The localize package intentionally duplicates some logic from the
compiler to avoid adding a dependency. This is now an error in the
packaging rule to prevent common pitfalls/code duplication. Here it's
an explicit decision though so we mark it as such and ask for the check
to be ignored for the particular import.
PR Close#51500
The upgrade package duplicaes some of code due to relative
imports between entry-points. This caused bundlers to
inline shared functions twice in both FESM outputs.
This is an acceptable limitation and we are not changing this
because the primary entry-point is not synced into G3. It's non-trivial
to remove these cross relative imports right now because the primary
entry-point is not even built in G3 so instead we just ignore the
relative imports using a re-export file.
Note: To simplify this change, we continue using namespace exports
as exporting individual named exports for all these possible usages
is rather cumbersome and also we had existing namespace imports for
e.g. `angular1.ts`. The code of upgrade is rarely edited these days
PR Close#51500
The common packages were duplicating a little bit of code due
to relative imports between entry-points. This caused bundlers to
inline shared functions twice in both FESM outputs.i
PR Close#51500
The animations packages were duplicating a little bit of code due
to relative imports between entry-points. This caused bundlers to
inline shared functions twice in both FESM outputs.
PR Close#51500
We were collecting all ES2022 files from entry-points (including
transitive files). Those are later on combined and filtered so that
we know which files to copy over to the package. There was no
deduping here. This did not have an effect, but could be a source
of slowness in `ng_package` and also breaks validation checks which
could show same errors multiple times for the same file.
PR Close#51500
Fixes that there was code duplication between the primary entry-point,
the testing entry-point and the rxjs-interop entry-point.
This code duplication resulted in additional code size (really
neglibible here because rxjs-interop did not duplicate large parts of
core, and `testing` is not used in production).
On the other hand though, the duplication resulted in a subtle JIT
dependency tracking issue due to the `depsTracker` no longer being a
singleton. This caused test failures as in:
https://github.com/angular/angular/pull/51415.
PR Close#51500
Introduces a check into `ng_package` that will ensure that there are no
cross entry-point or cross-package relative imports that would end up
contributing to duplicate code. Not only would duplicate code result in
size increases, but also it could cause subtle hard-to-debug bugs,
especially when cross imports rely on e.g. singletons. Like for example
the deps tracker that is used in angular/core but also in
angular/core/testing.
PR Close#51500
**Pipes Sample Code**
Migrated all sample code in the `examples/pipes` folder. Did not touch the pipes in the ToH or Testing folders.
>The existing, complex discussion of the `CurrencyPipe` within `pipes-transform-data.md` cried out for a new `concurrency-formatting.component` example`.
**Extracted "pipe precedence" into its own page**
The topic had been extracted from `pipe.md` and tacked on to the bottom of the `pipes-overview.md` page.
It's an advanced and somewhat obscure topic that doesn't belong in the overview. Rather than throw it away, I created a new `pipe-precedence.md` page and added it to the bottom of the pipes section navigation.
I also tried to improve both the guide text and the companion component, `precedence.component`.
**How to create a pipe is missing**
The readers are told they can create their own pipes in several places throughout the docs. But there are no links and you can't navigate to a page that covers the topic. This is a serious omission!
The topic is introduced in the `pipes-custom-data-trans.md` page (extracted verbatim from `pipes.md`). But you can't navigate to this page and their are no links to it.
TODO: restore this page and add it to the left-nav.
**Change `pipes.md` references to `pipe-overview.md`**
The original, kitchen-sink page, `pipes.md`, was disconnected from navigation long ago, in favor of multiple pages such as `pipe-overview.md`. The page is still in the AIO documentation and can be found by searching or by links from 3rd party documenters. Landing on that page hides the left-nav.
In this commit, we treat `pipes.md` as deprecated (which it seems to be). Therefore, this commit retargets previous `pipes.md` references to `pipe-overview.md`.
>The `change-detection-slow-computations.md` is the exception. It refers to "pure pipes", a subject not covered in the current pipe documentation. That reference is retargeted to `api/core/Pipe#pure`.
Certain code files are only referenced in `pipe.md`. They still work and are displayed in the overall pipes code sample as before. Now they are marked with deprecation comments for future treatment or removal.
For consistency, certain sections of `pipes.md` were replaced by the contents of the corresponding current pages.
PR Close#51333
With the new control flow and defer blocks it'll be common for several template instructions to be declare one after another. These changes add support for chaining to the `template` instruction which will allow us to save some bytes.
PR Close#51546
Adds the initial implementation to generate the instructions for the `for` loop block.
**Note:** the expressions we support in the `track` paramateter are currently limited to tracking by identity or index, or a specific property of the item. Supporting more advanced expression will require additional work that I'll do in a follow-up PR.
PR Close#51514
This commit fixes an issue where serialization of a view container fails in case it uses a component host as an anchor. This fix is similar to the fix from #51247, but for cases when we insert a component (that acts as a host for a view container) deeper in a hierarchy.
Resolves#51318.
PR Close#51456
`switch` blocks are part of the new control flow syntax. This commit adds support for processing them, and emitting the appropriate templates and conditional instructions.
PR Close#51518
This commit adds runtime implementation of a basic preloading mechanism for defer blocks. The base prefetching logic invokes a dependency loading function (generated by the compiler) when a corresponding `prefetch when` condition is triggered. The `prefetch on` triggers would be implemented in followup PRs.
We plan to explore additional prefetching techniques and will followup with more PRs later (based on the research).
PR Close#51529
Component compilation and host binding compilation previously used separate compilation emit functions. This was a bit messy, because we had to manage the relative orders of both phase lists. Indeed, there was already some inconsistency between the precise orders!
This commit refactors the emit functions to share the same phase list, and thus guarantees they will always be in the same order.
PR Close#51498
`syntheticHostListener` and `listener` have ordering dependencies. We reuse the existing ordering phase, and generalize it to also order create mode instructions.
PR Close#51498
Animation listeners on host bindings result in a special `syntheticHostListener` instruction. We can now emit this instruction.
Additionally, the naming phase for events has been slightly refactored to smoothly incorporate whether the event is from a host listener, as well as whether it is an animation listener.
PR Close#51498
For host bindings, `TemplateDefinitionBuilder` seems to use a different binding ordering, in which style bindings come after all the property bindings. We approximate that by treating `hostProperty` differently from `property` in the ordering phase.
PR Close#51498
The template pipeline is already capable of parsing and processing class and style attributes on templates. We now extend that functionality to host bindings.
The parser, for some reason, splits out class and style attributes into a `specialAttributes` field. We merge them back into the main attributes map, and allow the template pipeline to process them normally.
PR Close#51498
TemplateDefinitionBuilder only extracts host attributes if they are text attributes. For example, `[attr.foo]="'my-value'"` is not extracted despite being a string literal, because it is not a text attribute.
PR Close#51498
Host property bindings can be animation bindings, and should be ingested and emitted as such, as well as being processed by the renaming phase.
PR Close#51498
Host bindings can apply static attributes. These will be extracted to a `hostAttrs` field on the host binding function's metadata.
In order to achieve this, we add an `attributes` field to the host binding job. Then, we peform attribute exraction on host bindings. We finally populate the `attributes` field directly, instead of relying on a `consts` array.
PR Close#51498
Convert `CompilationJob` into a abstract class in order to extract common code. Separate host binding jobs and units, in order to allow for more code sharing.
PR Close#51498
Adds a new phase to resolve element placeholders in i18n messages.
This requires adding the i18n message to element ops, which means the
creation of i18n start/end ops can now be done in a separate phase
instead of during ingestion.
PR Close#51353
Creates a new `ExtractedMessageOp` which is consumed by the const
collection pahse to serialize the i18n message into the consts array.
Also adds support to the consts array for initialization statements.
PR Close#51353
Adds i18n block start & end ops, as well as a new phase to construct the
i18n message variable to be added to the consts array.
Co-authored-by: Alex Rickabaugh <alx+alxhub@alxandria.net>
Co-authored-by: Dylan Hunn <dylhunn@gmail.com>
PR Close#51353
Guide pages do not mention `NgModule` so they are untouched (and not "reviewed" either).
All code was migrated, including code in the `template-expression-operators` folder despite it only being referenced in the “archived” guide, `template-expression-operators.md`.
PR Close#51364
This commit adds an initial implementation of the `{#defer}` block runtime, which supports the `when` conditions. More conditions and basic prefetching support will be added in followup PRs.
PR Close#51347
aio currently uses the same `<meta name="Description">` content for every page. It seems like this might be causing a problem with search engine indexing such that different pages are being marked as duplicates of each other. It's unfortunately impossible to know whether this will actually fix the issue without it going live.
PR Close#51487
Extends the compiler to add support for generating arrow functions in the output AST. This will be required for the `for` control flow block and we can potentially leverage it in other places to reduces the amount of generated code.
PR Close#51436
Rather than the navigation transitions managing Router state, this
commit updates the Router to manage its own state based on ongoing
transition events. In the future, this can be abstracted even further to
have a totally separate class that manages the Router state. This would
allow the potential for swapping state manager implementations rather
than having to implement all types of state management in a single place.
One finding during tests was that unexpected errors thrown by the state management code moved
to the Router here will no longer be caught by the transition pipe's `catchError`.
This only includes calls to the following public Api methods:
* `go`, `replaceState`, `historyGo`, `isCurrentPathEqualTo` on `Location`
* `UrlSerializer.serialize`
* `UrlHandlingStrategy.merge`.
None of these methods should throw if the router is expected to function.
These might throw when tests include incomplete mocks, which is not
supported, or in cases where the actual browser methods like
`replaceState` would throw. This will already result in unexpected/unsupported
behavior. The failure case here is now arguably better - the navigation
itself still completes but the state update (either updating Router
internal state or updating the browser URL) fails separately and is
unhandled.
PR Close#48427
Setting the page ID is currently broken for the first page because the
helper method's second parameter is optional, which allowed the initally
`undefined` page ID to be used again when the router performs its
initial navigation.
fixes#50983
PR Close#51441
Updates the control flow tests to use the compiler instead of manually-written instructions. Also adds a couple of tests that I was using along the way to verify that things work as expected.
PR Close#51380
Adds the logic to generate the instructions for `if` blocks. There are two primary use cases we need to account for:
A conditional that doesn't use the `as` parameter of the `if` block. To support it we generate a nested ternary expression that evaluates to the index of the template whose condition is truthy. If the block doesn't have an `else` branch, we pass in a special `-1` value which means that no view will be rendered.
Example with an `else`:
```ts
// {#if expr}
// ...
// {:else if otherExpr} ...
// {:else} ...
// {/if}
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 0, 0);
ɵɵtemplate(1, App_Conditional_1_Template, 0, 0);
ɵɵtemplate(2, App_Conditional_2_Template, 0, 0);
}
if (rf & 2) {
ɵɵconditional(0, ctx.expr ? 0 : ctx.otherExpr ? 1 : 2);
}
```
Example without an `else`:
```ts
// {#if expr}
// ...
// {:else if otherExpr} ...
// {/if}
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 0, 0);
ɵɵtemplate(1, App_Conditional_1_Template, 0, 0);
}
if (rf & 2) {
ɵɵconditional(0, ctx.expr ? 0 : ctx.otherExpr ? 1 : -1);
}
```
If a conditional captures it's value in an alias (e.g. `{#if expr; as foo}`) we need to assign the value to a temporary variable before passing it along to `conditional`.
```ts
// {#if expr; as alias}...{/if}
if (rf & 1) {
ɵɵtemplate(0, App_Conditional_0_Template, 1, 0);
}
if (rf & 2) {
let App_contFlowTmp;
ɵɵconditional(0, (App_contFlowTmp = ctx.expr) ? 0 : -1, App_contFlowTmp);
}
```
PR Close#51380
Angular 16.1 introduced the input transform feature, requiring the partial compilation output to be extended
with a reference to the input transform function. This has resulted in a subtle breaking change, where older
versions of the Angular linker can no longer consume libraries that have started to use this feature.
We do try to support using a 16.1 library from an Angular 16.0 application, but if a library actually
adopts a new feature then this is no longer possible. In such cases, it is desirable to report a message
telling the user that their version of the Angular compiler is too old, as determined by the `"minVersion"`
property that is present in each partial declaration. This version would still indicate that the declaration
required at least Angular 14.0 to be compiled, but this is not accurate once input transforms are being
used. Consequently, this error would not be reported, causing a less informative error once the input transform
was being observed.
Fixes#51411
PR Close#51413
In local compilation mode it is not possible to use an imported string for component's template or styles as it cannot be resolved statically in compile time. There are some such use cases in g3 and potentially devs might incorporate such pattern. At the moment such pattern will cause the local compilation fail with generic error messages (e.g., so and so at position 1 is not a reference, etc). This change makes specific error messages with helpful hints for such cases. These new error messages can help devs to quickly resolve the issue as well as make it possible to identify existing issues in g3.
PR Close#51338
The runtime `ɵɵsetNgModuleScope` is modified to accept raw scope info as passed to it in local compilation mode. The runtime further registers the ng-module in the deps tracker. Then the runtime `ɵɵgetComponentDepsFactory` is implemented to use the deps tracker to get the component dependencies which leads to a valid and working Angular code.
PR Close#51377
The standalone components import as passed to the deps tracker will be the raw import, i.e., it is either a Type or a module with providers or a factory of these. So we use the existing type `RawScopeInfoFromDecorator` for these imports instead of the current one to be more realistic.
PR Close#51377
The current logic requires that standalone component always provide an array of raw imports. But such array could be dropped from the downstream tools if the component has no imports. So it is more natural to allow undefined raw imports for standalone components and treat it as empty array.
PR Close#51377
This refactoring is needed for next commit not to produce circular deps as we start using the `depsTracker` inside `ɵɵsetNgModuleScope`. The runtime `ɵɵsetComponentScope` is not needed to move but it moved to the new file just for consistency sake.
PR Close#51377
`tsickle` is not used in any code paths in 3P and we can remove
this complexity. The `tsickle` npm package has not been released
in a while and we are risking breakages with e.g. future TypeScript
versions.
Note that the `ng_module` rule was updated to not emit through
tsickle at all. The tsickle in 1P is done directly by `tsc_wrapped`
and our code path in `compiler-cli` is not needed at all.
PR Close#50602
The example for clearing secondary outlets currently only works because
the named outlet appears at the root of the application's route config.
If developers follow this example with an outlet that is not at the
root level, they will not be able to close the outlet.
This commit updates the example to provide a more robust way
of clearing the outlet from the activated outlet component
as well as providing a warning about how the commands are applied.
Lastly, there is a small bit of guidance provided for developers who
might want to explore the ability to close an outlet from any location
in the app, without needing to be aware of the activated route.
An example of this can be found here:
https://stackblitz.com/edit/close-outlet-from-anywhereresolves#51373resolves#13523
PR Close#51376
This commit updates TestBed to wait for async component metadata resolution before compiling components.
Async metadata is added by the compiler in case a component uses defer blocks, which contain deferrable
symbols.
PR Close#51182
This commit updates compiler logic to generate the `setClassMetadataAsync` calls for components that used defer blocks. The `setClassMetadataAsync` function loads deferrable dependencies and invokes the `setClassMetadata` synchronously once everything is loaded. This change is needed to avoid eager references to deferrable symbols in component metadata in generated code.
PR Close#51182
Fixes that we weren't processing `when` conditions correctly which led to a compilation error when a pipe is used inside the expression.
PR Close#51368
We enabled a lint rule internally to require that multi-provided
`InjectionToken`s have a `readonly` array type, the tokens in this
PR do not follow this rule and are causing lint violations.
Fixes#51124
PR Close#51125
This adds a section to cover the case of CDNs that have optimizations that will break both Angular and Hydration by stripping comment nodes.
PR Close#51355
The runtime `ɵɵsetNgModuleScope` is modified to accept raw scope info as passed to it in local compilation mode. The runtime further registers the ng-module in the deps tracker. Then the runtime `ɵɵgetComponentDepsFactory` is implemented to use the deps tracker to get the component dependencies which leads to a valid and working Angular code.
PR Close#51309
The standalone components import as passed to the deps tracker will be the raw import, i.e., it is either a Type or a module with providers or a factory of these. So we use the existing type `RawScopeInfoFromDecorator` for these imports instead of the current one to be more realistic.
PR Close#51309
The current logic requires that standalone component always provide an array of raw imports. But such array could be dropped from the downstream tools if the component has no imports. So it is more natural to allow undefined raw imports for standalone components and treat it as empty array.
PR Close#51309
This refactoring is needed for next commit not to produce circular deps as we start using the `depsTracker` inside `ɵɵsetNgModuleScope`. The runtime `ɵɵsetComponentScope` is not needed to move but it moved to the new file just for consistency sake.
PR Close#51309
This change simply flip the flag which enables using the deps tracker in JIT compilation (the logic is already implemented in a previous PR). Some tests which depend on the old JIT implementation (e.g., patching the scope info into the type) are modified accordingly.
PR Close#51293
Using verification helpers such as `isComponent` may trigger JIT compilation. Now in some tests such compilation is made purposely to fail, and so in such cases any reference to the `depsTracker.clearScopeCacheFor` method will cause the exception to be thrown earlier than expected which results in teh test failure. Such scenario is the case in the next commit when we enable using the deps tracker in the jit compilation. Note that such failure is only for the framework tests and is a very edge case. The tests in downstream apps will not lead to such scenario of failure at all.
PR Close#51293
Empty path routes are effectively 'passthrough' routes that do not
appear in the URL. When these exist in the route tree, we do not want to
apply named outlet commands to that tree location. Instead, we skip past
this location in the tree, effectively squashing/removing this
passthrough route from the tree.
fixes#50356
PR Close#51292
The documentation incorrectly stated that the app.module.ts file is generated
when the --standalone flag is used. This is not the case, and the documentation
should accurately reflect the behavior.
Closes#51306
PR Close#51307
An empty runtime is added just to make the local compiled angular files valid to run. A separate PR will implement the runtime in the right way using the deps tracker.
PR Close#51089
A factory generator function called "i0.ɵɵgetComponentDepsFactory" is added to generate a factory function for component dependencies. This function will use the deps tracker to calculate the component's dependencies.
For standalone components the component imports (if exists) will be passed to this function. Alternatively this function can grab the imports directly from the decorate, but such extraaction needs some runtime logic which overlapps with what the trait compiler is doing. So better to pass the imports directly to this function at compile time.
PR Close#51089
In local mode the compiler combines the raw imports and exports and pass them to the injector definition as the imports field. It is not possible to filter out ng modules at compile time though, and it will be done in runtime.
Unit tests also added, and since that was the first time adding tests for local compilation some tweaks had to be made in order to disable diagnostics in local compilation mode in order for tests to run (such situation is also the case in real compilation where we ignore all teh diagnostics basically)
PR Close#51089
A minor error is present within the documentation. Specifically, in the documentation for the CanActivateFn function, a reference is made to the CanActivateChildFn function. However, it appears that the CanActivateChildFn function is not utilized or referenced elsewhere in the documentation of CanActivateFn.
PR Close#51283
The current change is done behind a flag which is set to false. So no change in code path took place here. In a followup PR the flag is changed to true which will make the actual change.
PR Close#51122
For cases when a root component also acts as an anchor node for a ViewContainerRef (for example, when ViewContainerRef is injected in a root component), there is a need to serialize information about the component itself, as well as an LContainer that represents this ViewContainerRef. Effectively, we need to serialize 2 pieces of info: (1) hydration info for the root component itself and (2) hydration info for the ViewContainerRef instance (an LContainer). Each piece of information is included into the hydration data (in the TransferState object) separately, thus we end up with 2 ids. Since we only have 1 root element, we encode both bits of info into a single string: ids are separated by the `|` char (e.g. `10|25`, where `10` is the ngh for a component view and 25 is the `ngh` for a root view which holds LContainer).
Previously, we were only including component-related information, thus all the views in the view container remained dehydrated and duplicated (client-rendered from scratch) on the client.
Resolves#51157.
PR Close#51247
This refactoring adds utility functions to add / remove LView from LContainer.
Those utils are preparation for the control flow and defer work.
Existing code was refactored to use the new utility functions and avoid
any code duplication.
PR Close#51191
non-destructive hydration expects the DOM tree to have the same structure in both places.
With this commit, the app will throw an error if comments are stripped out by the http server (eg by some CDNs).
fixes#51160
PR Close#51170
This commit updates the logic to drop regular imports when all symbols that it brings can be defer-loaded.
The change ensures that there is no mix of regular and dynamic imports present in a source file.
PR Close#51171
Fixes that if a directive/pipe is used after a nested `defer` block, we weren't tracking it as lazy anymore. This was due to the fact that we were resetting the `isInDeferBlock` to false every time instead of the previous value.
PR Close#51262
Adds validations for the following invalid deferred block structures:
* Duplicated triggers.
* Multiple `minimum` parameters on `placeholder` and `loading` blocks.
* Multiple `after` parameters on `loading` blocks.
PR Close#51262
Stores the `deferred` block triggers as a map instead of an array, because triggers can't be duplicated and because having to search through an array will be inconvenient later on.
I've also added a `DeferredBlock.visitAll` method to deduplicate the logic from the various visitor implementations.
PR Close#51262
Adds a new phase that converts previously extracted
ExtractedAttributeOps representing a style attribute into individual
ExtractedAttributeOps representing each of the style properties set in
the style attribute.
PR Close#51258
Refactors ElementAttributes to be an implementation detail of the const
collection phase, rather than an object that is added to all ElementOps.
PR Close#51258
Refactors the attribute extraction phase to create a new temporary op
called `ExtractedAttributeOp` rather than directly populating
`ElementAttributes`.
PR Close#51258
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
# **NOTE 3**: If you change the version of Node.js provided by the docker images, also update `.devcontainer/recommended-Dockerfile` to match the new version.
/** Time to wait after navigation starts before showing the progress bar. This delay allows a small amount of time to skip showing the progress bar when a navigation is effectively immediate. 30ms is approximately the amount of time we can wait before a delay is perceptible.*/
* For the `Tutorials`, we display the navigation in the dropdown and it has flat structure (all items are displayed as items with level === 0).
*
* For the `Reference` we would like to give possibility to expand the "level === 1" items cause they are not visible in the first slide of navigation list.
// Skip expand when active item is API Reference homepage - `/api`.
// It protect us from displaying second level of the navigation when user clicks on `Reference`,
// Because in this situation we want to display the first level, which contains, in addition to the API Reference, also the CLI Reference, Error Encyclopedia etc.
- See [scripts/tutorials/README.md](/scripts/tutorials/README.md) for more information about the tutorials script.
- See [adev/src/content/tutorials/README.md](/adev/src/content/tutorials/README.md) for more information about the tutorials content.
---
## Scenarios
### Loading a project
1. The page responsible for the embedded editor lazy loads the [`EmbeddedEditor`](./embedded-editor.component.ts) component and the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts), then triggers the initialization of all components and services. The embedded editor is available in the following pages:
- homepage: https://angular.dev
- playground: https://angular.dev/playground
- tutorial pages: https://angular.dev/tutorials
2. The project assets are fetched by the [`EmbeddedTutorialManager`](./embedded-tutorial-manager.service.ts). Meanwhile:
- The code editor is initialized
- The code editor initializes the TypeScript Web Worker, which initializes the "default file system map" using TypeScript's CDN.
- The WebContainer is initialized
- The terminal is initialized
3. The tutorial source code is mounted in the `WebContainer`'s filesystem by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts)
4. The tutorial project dependencies are installed by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts).
5. The development server is started by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts) and the types are loaded by the [`TypingsLoader`](./typings-loader.service.ts) service.
6. The preview is loaded with the URL provided by the WebContainer API after the development server is started.
7. The project is ready.
### Updating the code
1. The user update the code in the code editor.
2. The code editor state is updated on real time, without debouncing so that the user can see the changes in the code editor and CodeMirror can handle the changes accordingly.
3. At the same time, the changes are sent to the TypeScript web worker to provide diagnostics, autocomplete and type features as soon as possible.
4. The code changes are debounced to be written in the WebContainer filesystem by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts).
5. After the debounce time is reached, the code changes are written in the WebContainer filesystem by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts), then the user can see the changes in the preview.
### Creating a new file
1. The user clicks on the new file button.
2. The new file tab is opened.
3. The user types the new file name.
4. If the file name is valid, the file is created in the WebContainer filesystem by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts).
-`..` is disallowed in the file name to prevent users to create files outside the `src` directory.
5. The file is added to the TypeScript virtual file system, allowing the TypeScript web worker to provide diagnostics, autocomplete and type features for the new file. Also, exports from the new file are available in other files.
6. The new file is added as the last tab in the code editor and the new file can be edited.
Note: If the new file name matches a file that already exists but is hidden in the code editor, the content for that file will show up in the created file. An example for a file that always exists is `index.html`.
### Deleting a file
1. The user clicks on the delete file button.
2. The file is deleted from the WebContainer filesystem by the [`NodeRuntimeSandbox`](./node-runtime-sandbox.service.ts).
3. The file is removed from the TypeScript virtual file system.
4. The file is removed from the code editor tabs.
Note: Some files can't be deleted to prevent users to break the app, being `src/main.ts`and `src/index.html`
### Switching a project
The embedded editor considers a project change when the embedded editor was already initialized and the user changes the page in the following scenarios:
- Navigating through tutorial steps
- Going from the homepage after the embedded editor is initialized to the playground
- Going from a tutorial page to the playground
- Going from a tutorial page to the homepage
- Going from the playground to the homepage
When a project change is detected, the [`EmbeddedTutorialManager`](./embedded-tutorial-manager.service.ts) emits the `tutorialChanged` observable, which is listened in multiple sub-components and services, then each component/service performs the necessary operations to switch the project.
The following steps are executed on project change:
1. The new project files are fetched by the [`EmbeddedTutorialManager`](./embedded-tutorial-manager.service.ts).
2. The new project files are mounted in the WebContainer filesystem.
3. The TypeScript virtual filesystem is updated with the new files and contents.
4. The previous project and new project files are compared.
1. Files that are not available in the new project are deleted from the WebContainer filesystem.
2. Files that have the same path and name have their content replaced on the previous step when the files are mounted.
5. The previous project dependencies are compared with the new project dependencies.
1. If there are differences, a `npm install` is triggered, hiding the preview and going to the install loading step.
2. If there are no differences, the project is ready.
6. Some states are reset, for example the "reveal answer" state if the previous project was in the "reveal answer" state.
[CodeMirror](https://codemirror.net/) is the library used to handle the code editor.
The `CodeMirrorEditor` service manages the CodeMirror instance and all the interactions with the library used to handle the code editor.
- handle the file edits and the CodeMirror view and state
- handle the current project files in the code editor
- handle the file creations and deletions
- handle the file changes
- handle all the CodeMirror specific events and extensions
###### [TypeScript Web Worker](./code-editor/workers/typescript-vfs.worker.ts)
The TypeScript features are provided by the TypeScript web worker, that is initialized by the `CodeMirrorEditor` service.
The TypeScript web worker uses `@typescript/vfs` and the TypeScript language service to provide diagnostics, autocomplete and type features.
#### [`Preview`](./preview/preview.component.ts)
The preview component manages the `iframe` responsible for displaying the tutorial project preview, with the URL provided by the WebContainer API after the development server is started.
While the project is being initialized, the preview displays the loading state.
Responsible for managing the WebContainer instance and all communication with its API. This service handles:
- the WebContainer instance
- all Node.js scripts
- the WebContainer filesystem, mounting the tutorial project files, writing new content, deleting and creating files.
- the terminal session, reading and processing user inputs.
- the tutorial project dependencies, installing the dependencies.
- the processes running inside the WebContainer, being the npm scripts to install the dependencies, run the development server and the user inputs for the `ng` CLI.
Manages the editor UI state, being responsible for handling the user interactions with the editor tabs, switching between the preview, the terminal and the console.
Responsible for handling the download button in the embedded editor, fetching the tutorial project files and generating a zip file with the project content.
#### [`AlertManager`](./alert-manager.service.ts)
Manage the alerts displayed in the embedded editor, being the out of memory alert when multiple tabs are opened, and unsupported environments alerts.
message=`Your browser is currently limiting the memory available to run the Angular Tutorials or Playground. If you have multiple tabs open with Tutorials or Playground, please close some of them and refresh this page.`;
break;
caseAlertReason.MOBILE:
message=`You are running the embedded editor in a mobile device, this may result in an Out of memory error.`;
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.