Commit graph

2886 commits

Author SHA1 Message Date
Alan Agius
9d1fb33f5e fix(core): introduce BootstrapContext for improved server bootstrapping (#63640)
This commit introduces a number of changes to the server bootstrapping process to make it more robust and less error-prone, especially for concurrent requests.

Previously, the server rendering process relied on a module-level global platform injector. This could lead to issues in server-side rendering environments where multiple requests are processed concurrently, as they could inadvertently share or overwrite the global injector state.

The new approach introduces a `BootstrapContext` that is passed to the `bootstrapApplication` function. This context provides a platform reference that is scoped to the individual request, ensuring that each server-side render has an isolated platform injector. This prevents state leakage between concurrent requests and makes the overall process more reliable.

BREAKING CHANGE:
The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.

Before:
```ts
const bootstrap = () => bootstrapApplication(AppComponent, config);
```

After:
```ts
const bootstrap = (context: BootstrapContext) =>
  bootstrapApplication(AppComponent, config, context);
```

A schematic is provided to automatically update `main.server.ts` files to pass the `BootstrapContext` to the `bootstrapApplication` call.

In addition, `getPlatform()` and `destroyPlatform()` will now return `null` and be a no-op respectively when running in a server environment.

(cherry picked from commit 8bf80c9d2314b4f2bcf3df83ae01552a6fc49834)

PR Close #63640
2025-09-09 10:46:27 -07:00
Kristiyan Kostadinov
3aa45a2fa1 fix(core): resolve forward-referenced host directives during directive matching (#58492) (#58500)
When the compiler generates the `HostDirectivesFeature`, it generates either an eager call (`ɵɵHostDirectivesFeature([])`) or a lazy call (`ɵɵHostDirectivesFeature(() => [])`. The lazy call is necessary when there are forward references within the `hostDirectives` array. Currently we resolve the lazy variant when the component definition is created which has been enough for most cases, however if the host is injected by one of its host directives, we can run into a reference error because DI is synchronous and the host's class hasn't been defined yet.

These changes resolve the issue by pushing the lazy resolution later during directive matching when all classes are guanrateed to exist.

Fixes #58485.

PR Close #58492

PR Close #58500
2024-11-04 17:18:52 +01:00
Kristiyan Kostadinov
46bafb0b0a fix(core): clean up afterRender after it is executed (#58119)
We stop tracking `afterRender` hooks as soon as they execute, but their on destroy callbacks stay registered until either the injector is destroyed or the user calls `destroy` manually. This was leading to memory leaks in the `@defer` triggers based on top of `afterRender` when placed inside long-lived views, because the callback would execute, but its destroy logic was waiting for the view to be destroyed.

These changes resolve the issue by destroying the `AfterRenderRef` once it is executed.

PR Close #58119
2024-10-08 13:27:07 -07:00
arturovt
46a2ad39f5 fix(common): prevent warning about oversize image twice (#58021)
I’ve noticed that there was a loop inside a loop. Since we’re already iterating through
`images` using `forEach`, it was running a `for` loop through `images` again. This was
probably a mistake made when the functionality was initially added. The test actually
verified that `logs.length` is `1`, but in the real environment, it logs twice
(which is quite obvious due to the code).

I’ve also added the missing file to the Bazel target.

PR Close #58021
2024-10-02 11:46:18 +00:00
arturovt
8f2b0ede59 fix(common): skip checking whether SVGs are oversized (#57966)
Prior to this commit, the `ImagePerformanceWarning` class was checking all `img`
elements in the DOM to determine whether they were oversized after the DOM loading
was complete. We should not check SVGs because they are vector-based and can scale
infinitely without losing quality.

Closes #57941

PR Close #57966
2024-09-30 13:28:46 -07:00
Kristiyan Kostadinov
2f347ef8fc fix(core): provide flag to opt into manual cleanup for after render hooks (#57917)
Adds a `manualCleanup` flag to `afterRender` and `afterNextRender`, similarly to `effect`. The reason is that currently if the hook is created outside of an injection context, it requires an injector to be passed in. In some cases that injector might be an injector that is never destroyed (e.g. `EnvironmentInjector`) which can give a false sense of security users thinking that the hook will be cleaned up automatically. We fell into this in the CDK which caused a memory leak (see https://github.com/angular/components/pull/29709). With the `manualCleanup` option users explicitly opt into cleaning the hook up themselves.

PR Close #57917
2024-09-26 14:20:55 -07:00
Thomas Nguyen
2e7cfcb2ef refactor(core): Remove global event delegation code. (#57893)
This is no longer needed since we are no longer experimenting with it.

PR Close #57893
2024-09-26 14:18:18 -07:00
Joey Perrott
03ac3c299d refactor: update license text to point to angular.dev (#57902)
Update license text to point to angular.dev instead of angular.io

PR Close #57902
2024-09-24 15:28:46 +02:00
Kristiyan Kostadinov
df42d2be16 test: avoid leaking some LViews in tests (#57546)
We had some tests that were leaking LViews, because we were testing things like `createComponent`, but not destroying them afterwards. These changes clean up most of them, although there are a handful still left that I didn't have time to fully track down.

PR Close #57546
2024-08-27 13:29:09 -07:00
Kristiyan Kostadinov
106917af87 fix(core): avoid leaking memory if component throws during creation (#57546)
When we create the LView for a component, we track it in the `TRACKED_LVIEWS` map. It gets untracked when it is destroy, but if it throws during creation, the user won't have access to a `ComponentRef` in order to clean it up.

These changes automatically untrack the related LViews if the component couldn't be created.

PR Close #57546
2024-08-27 13:29:09 -07:00
Thomas Nguyen
6d3a2af146 fix(core): Do not bubble capture events. (#57476)
These should only fire if the target is the same as the targetElement. Also, delete an out of date test since capture/non-capture tests are separately covered.

PR Close #57476
2024-08-23 14:46:55 -07:00
Alex Rickabaugh
6059ca8f1f refactor(core): restructure AfterRenderManager to connect related phases (#57453) (#57504)
The `afterRender` infrastructure was first implemented around the idea of
independent, singular hooks. It was later updated to support a spec of
multiple hooks that pass values from one to another as they execute, but the
implementation still worked in terms of singular hooks under the hood. This
creates a number of maintenance issues, and a few bugs. For example, when
one hook fails, further hooks in the pipeline should no longer execute, but
this was hard to ensure under the old design.

This refactoring restructures `afterRender` infrastructure significantly to
introduce the concept of a "sequence", a collection of hooks of different
phases that execute together. Overall, the implementation is simplified
while making it more resilient to issues and future use cases, such as the
upcoming `afterRenderEffect`.

As part of this refactoring, the `internalAfterNextRender` concept is
removed, as well as the unused `queueStateUpdate` concept which used it.

PR Close #57453

PR Close #57504
2024-08-23 12:48:01 -07:00
Andrew Scott
9de30a7b1c fix(core): Allow zoneless scheduler to run inside fakeAsync (#56932)
The zoneless scheduler callback was executed in the root zone rather
than simply in `runOutsideAngular` to allow us to land the hybrid mode
change detection (scheduler always enabled, even for zones) without
breaking a ton of existing `fakeAsync` tests that could/would fail with
the "timer(s) still in queue" error. However, this caused another
problem: when a test executes inside `fakeAsync`, it cannot flush the
scheduled time. A similar problem exists with event and run coalescing (#56767).
This change would allow `fakeAsync` to flush the zoneless-scheduled
change detections and minimize breaking existing tests
by flushing pending timers at the end of the test, which actually now
matches what's done internally.

PR Close #56932
2024-08-15 12:32:24 -04:00
Thomas Nguyen
8104fc2126 refactor(core): Call stopPropagation and preventDefault unconditionally within the patched methods. (#57354)
This fixes a few tests in g3 and is a bug fix for the event dispatcher. Otherwise, bubbling might
continue.

PR Close #57354
2024-08-13 12:09:57 -07:00
Thomas Nguyen
7accd9d885 fix(core): Account for addEventListener to be passed a Window or Document. (#57354)
This happened to work for other event listeners since both had a
addEventListener method.

PR Close #57354
2024-08-13 12:09:57 -07:00
Andrew Kushnir
5558e275ee fix(core): take skip hydration flag into account while hydrating i18n blocks (#57299)
This commit updates serialization and hydration i18n logic to take into account situations when i18n blocks are located within "skip hydration" blocks.

Resolves #57105.

PR Close #57299
2024-08-09 08:07:49 -07:00
Andrew Scott
296216cbe1 fix(core): Allow hybrid CD scheduling to support multiple "Angular zones" (#57267)
This commit updates the inside/outside NgZone detection of the hybrid CD
scheduling to track the actual instance of the NgZone being used rather
than the name "Angular" (how `isInsideAngularZone` works). This allows
the scheduling to work correctly when there are multiple versions of
Angular running on the page.

fixes #57261

PR Close #57267
2024-08-08 10:46:26 -07:00
Thomas Nguyen
9af760eb51 fix(core): Account for addEventListener to be passed a Window or Document. (#57282)
This happened to work for other event listeners since both had a
addEventListener method.

PR Close #57282
2024-08-08 08:32:11 -07:00
Kristiyan Kostadinov
513a4fe05e refactor(core): replace usages of removeChild (#57203)
These changes replace most usages of `removeChild` with `remove`. The latter has the advantage of not having to look up the `parentNode` and ensure that the child being removed actually belongs to the specific parent.

The refactor should be fairly safe since all the browsers we cover support `remove`. [Something similar was done in Components](https://github.com/angular/components/pull/23592) some time ago and there haven't been any bug reports as a result.

PR Close #57203
2024-08-07 16:46:09 +00:00
Andrew Scott
7919982063 feat(core): Add whenStable helper on ApplicationRef (#57190)
This commit adds a `whenStable` function to `ApplicationRef` to cover
the most common use-case for the `isStable` observable.

PR Close #57190
2024-08-06 21:28:16 +00:00
Andrew Scott
70e8b40750 fix(zone.js): Update the default behavior of fakeAsync to flush after the test (#57240)
From the internal issue on the matter:

> When using the standard Jasmine version of it promises returned by the body function are automatically awaited. The Catalyst version of it is fake-async, so awaiting the promise does not make sense; however it would be nice if Catalyst automatically flushed the promise to replicate the experience of using standard it. This would allow users to do the following:

```
it('should fail later', async () => {
  await new Promise(r => setTimeout(r));
  fail('failure');
});
```
> In Catalyst today the above test will pass. If this proposal to automatically flush the resulting promise were implemented it would fail.

Flushing after the tests complete has been the default behavior inside
Google since 2020. Very few tests remain that use the old behavior of
only flushing microtasks. The example above would actually fail with
`fakeAsync` due to the pending timer, but the argument still remains the
same. We might as well just flush if we're going to fail the test
anyways by throwing if there's no flush at the end.

BREAKING CHANGE: `fakeAsync` will now flush pending timers at the end of
the given function by default. To opt-out of this, you can use `{flush:
false}` in options parameter of `fakeAsync`

PR Close #57240
2024-08-05 20:24:54 +00:00
Thomas Nguyen
2a915d1912 refactor(core): Remove clickmod support from Angular. (#57201)
This was an old feature that mapped shift + click (et al) to "clickmod". This doesn't really make sense to add to Angular, so let's remove it.

PR Close #57201
2024-08-02 14:20:53 +00:00
Paul Gschwendtner
187666480f test: update symbol golden after lock file maintenance (#57205)
Lock file maintenance updated Terser, which impacts the bundle
optimizations being tested via the symbol golden tests.

There was a small noticable change in the symbol golden where
`withDomHydration` is now preserved, and the underlying function
that was previously detected is gone. Seemingly Terser now inlines
this function and had to preserve `withDomHydration` as the entry point.

PR Close #57205
2024-07-31 16:02:11 +00:00
Andrew Scott
b558f99150 refactor(core): Update callback schedulers to cancel pending timers (#57186)
Rather than leaving the timers around as no-ops, this commit updates the
logic to also attempt to clear or cancel the timers. This is helpful for
the eventual goal of running the scheduler in the `fakeAsync` zone (if
the test is running in `fakeAsync`) rather than scheduling in the root
zone and making it impossible to flush.

PR Close #57186
2024-07-30 18:05:09 +00:00
Andrew Scott
b3836c2f1c refactor(core): Private option to rethrow ApplicationRef.tick errors in tests (#57153)
This creates a private option that can be used internally while we
migrate this to the default and only behavior. ~200 tests in TGP have errors
that are being swallowed (console.log) and not causing the test to fail.
We can first explicitly opt those out, flip the default internally, then
"fix" them by adding expect...toThrow.

PR Close #57153
2024-07-30 18:04:27 +00:00
Andrew Scott
2a4f488a6c fix(core): warnings for oversized images and lazy-lcp present with bootstrapModule (#57060)
This commit adds the `ImagePerformanceWarning` to the common bootstrap
code rather than only starting it when using `bootstrapApplication`.

PR Close #57060
2024-07-30 18:03:35 +00:00
Andrew Scott
3459289ef0 feat(core): bootstrapModule can configure NgZone in providers (#57060)
This commit allows configuring `NgZone` through the providers for
`bootstrapModule`. Prior to this change, developers had to configure
`NgZone` in the `BootstrapOptions`.

PR Close #57060
2024-07-30 18:03:35 +00:00
Andrew Scott
3a63c9ebbe fix(core): errors during ApplicationRef.tick should be rethrown for zoneless tests (#56993)
The behavior of `ComponentFixture` for zoneless tests was decided somewhat through guesswork, trial, and error. In addition, working on the zoneless fixture revealed oddities in the behavior of the zone-based fixture, or behaviors that we felt were counterintuitive. The most consequential difference is how change detection works: `detectChanges` goes through ApplicationRef.tick in zoneless while it is `changeDetectorRef.detectChanges` in the zone fixture.

We felt that running change detection through `ApplicationRef.tick` was important for several reasons:
* Aligning application behavior more closely with the test behavior (almost all views are attached to application ref in reality)
* Ensuring that afterRender* hooks are executed when calling `fixture.detectChanges`
* Ensuring that the change detection runs again if render hooks update state

This change, however, has some noticeable consequences that will break some tests, mostly around how errors are handled. `ApplicationRef.tick` catches errors that happen during change detection and reports them to the ErrorHandler from DI. The default error handler only logs the error to the console. This will break tests which have `expect(() => fixture.detectChanges()).toThrow()`. In addition, it allows tests to pass when there are real errors encountered during change detection.

This change ensures that errors from `ApplicationRef.tick` are rethrown
and will fail the test. We should also do a follow-up investigation to
determine whether we can/should also do this for the zone-based
`ComponentFixture`.

fixes #56977

PR Close #56993
2024-07-29 13:49:00 -07:00
Tom Wilkinson
83117f1a0d refactor(core): Switch to using concat rather than spread operator for events. (#57103)
Internally, the JSCompiler does not dead code eliminate this code when its using spread.

PR Close #57103
2024-07-23 15:54:23 -07:00
Thomas Nguyen
3664cd6cb2 refactor(core): Allow manual renderer listens to contribute to event delegation as well. (#56799)
There are existing usages that inject the renderer to manualy listen (often for event
delegation purposes). These should contribute as well.

PR Close #56799
2024-07-19 13:42:26 -07:00
Matthieu Riegler
7d4b2d2413 fix(core): afterNextRender hooks return that callback value. (#57031)
`afterRender` was working fine but `afterNextRender` wasn't

PR Close #57031
2024-07-19 13:40:59 -07:00
Tom Wilkinson
425f44c133 refactor(core): Move logic into early event contract files. (#56994)
Also remove some dead a11y code, now that a11y is in `ActionResolver`.

PR Close #56994
2024-07-18 12:05:17 -07:00
Kristiyan Kostadinov
e504ad97d4 fix(core): not all callbacks running when registered at the same time (#56981)
Fixes that only the first callback was firing when multiple are registered in the same call to `afterNextRender`, e.g. `afterNextRender({earlyRead: fn, read: fn});`

Fixes #56979.

PR Close #56981
2024-07-16 08:42:26 -07:00
Kristiyan Kostadinov
9167fc815c fix(compiler): JIT mode incorrectly interpreting host directive configuration in partial compilation (#57002)
Fixes that the runtime implementation of `ɵɵngDeclareDirective` was interpreting the `hostDirectives` mapping incorrectly. Instead of treating the inputs/outputs as `['binding', 'alias']` arrays, it was parsing them as `['binding: alias']`. This was leading to runtime errors if a user is consuming a partially-compiled library in JIT mode.

Fixes #54096.

PR Close #57002
2024-07-16 08:37:26 -07:00
Tom Wilkinson
d011c9f7ba refactor(core): Refactor EarlyEventContract to prepare for using it as a container. (#56900)
This is the first step towards combining `EarlyEventContract` and `EventContract`. It contains a few refactors, such as making names more consistent.

The goal of this refactor is to remove the `EarlyEventContract` class altogether, as well as `EventContract`.

To install the early event contract with the default events in early script tag, users will call:

`bootstrapGlobalEarlyEventContract()`

And for boostraping:

`registerGlobalDispatcher(dispatcher)`

PR Close #56900
2024-07-10 13:53:03 -07:00
Paul Gschwendtner
7f550ea0c8 refactor(compiler-cli): move JIT transforms into ngtsc (#56892)
This commit moves the JIT transforms into the ngtsc folder. They existed
outside of ngtsc mostly as an historic artifact— and now with compiler
relying on them even more deeply, it makes sense to move them into
`ngtsc/transform`.

PR Close #56892
2024-07-10 17:29:20 +02:00
Andrew Kushnir
c1e3262119 test(core): simplify @defer-based test to make CI more stable (#56904)
This commit updates one of the `@defer`-based test to use the `on immediate` trigger to make a test mor
e stable without the need to add mocks for the `on idle` (default) condition.

PR Close #56904
2024-07-09 09:36:11 +02:00
Andrew Kushnir
00d9cd240d fix(core): establish proper defer injector hierarchy for components attached to ApplicationRef (#56763)
This commit updates the logic that create an injector for defer blocks (when it's needed) to account for a situation when a component is instantiated without a connection to the current component tree. This can happen if a component is created using its factory function or via `createComponent()` call.

Resolves #56372.

PR Close #56763
2024-07-03 14:08:43 +00:00
Thomas Nguyen
3d1bc5a51e refactor(core): Add an ngOnDestroy to GlobalEventDelegation. (#56762)
It seems that this makes test libs that contain > 1 test file pass.

PR Close #56762
2024-07-01 20:33:17 +00:00
Thomas Nguyen
551027e04e refactor(core): Set the jsaction cache directly instead of using jsaction attribute. (#56747)
This should make things somewhat faster, since setAttribute can be slower than addEventListener. Jsaction attribute is still needed for SSR though.

PR Close #56747
2024-07-01 17:31:24 +00:00
Kristiyan Kostadinov
2a1291e942 fix(compiler): give precedence to local let declarations over parent ones (#56752)
Currently the logic that maps a name to a variable looks at the variables in their definition order. This means that `@let` declarations from parent views will always come before local ones, because the local ones are declared inline whereas the parent ones are hoisted to the top of the function.

These changes resolve the issue by giving precedence to the local variables.

Fixes #56737.

PR Close #56752
2024-07-01 14:03:57 +00:00
Tom Wilkinson
040d86137e refactor(core): Remove dom.ts and use native Element.prototype.contains. (#56591)
Delete the entire dom.ts file, it is no longer needed.

PR Close #56591
2024-06-27 18:28:19 +00:00
Tom Wilkinson
3773f406ac refactor(core): Remove ActionResolver code from EventContract (#56723)
Now that all `Dispatcher` implementations use `ActionResolver`, `EventContract` no longer needs to. Additionally, all a11y click support has been removed. `EventContract` will not specifically listen for `keydown` automatically, as all `EventContract` instances already have `keydown` listeners. This removes the need for the `A11Y_CLICK_SUPPORT` define, which will be removed in a future PR.

PR Close #56723
2024-06-27 18:27:44 +00:00
Matthieu Riegler
d23aa878a0 test(core): Add testing for defer error block (#56561)
In #56558 it was raised that we used an devMode function in a prod scope.
This commit adds a test when an defer error block is missing in devMode and prodMode

PR Close #56561
2024-06-27 15:53:19 +00:00
Thomas Nguyen
40fb81fd0e refactor(core): Add global event delegation provider (#56247)
This replaces all addEventListener calls with a stashing function,
and installs an event listener on the document body to retrieve
the stashed function;

PR Close #56247
2024-06-27 14:24:47 +00:00
Kristiyan Kostadinov
0a48d584f2 feat(core): add support for let syntax (#56715)
Enables the new `@let` syntax by default.

`@let` declarations are defined as:
1. The `@let` keyword.
2. Followed by one or more whitespaces.
3. Followed by a valid JavaScript name and zero or more whitespaces.
4. Followed by the `=` symbol and zero or more whitespaces.
5. Followed by an Angular expression which can be multi-line.
6. Terminated by the `;` symbol.

Example usage:
```
@let user = user$ | async;
@let greeting = user ? 'Hello, ' + user.name : 'Loading';
<h1>{{greeting}}</h1>
```

Fixes #15280.

PR Close #56715
2024-06-26 12:37:02 -07:00
Kristiyan Kostadinov
bbe39c1738 refactor(core): integrate let instructions into the runtime (#56527)
Adds the implementation of the following new instructions:
* `declareLet` - creation-time instruction that initializes the slot for a let declaration.
* `storeLet` - update-time instruction that stores the current value of a let declaration.
* `readContextLet` - instruction that reads the stored value of a let declaration from a different view.

On top of the instructions, it also introduces a new `LetDeclaration` TNode type.
The new TNode is nececessary for DI to work correctly in pipes inside the let expression,
as well as for proper hydration support.

PR Close #56527
2024-06-26 08:48:31 -07:00
Matthieu Riegler
5be16d06bd fix(core): prevent calling devMode only function on @defer error. (#56559)
`getTemplateLocationDetails()` is a devMode only function and should guarded by `ngDevMode` or calling it will throw an error.

fixes #56558

PR Close #56559
2024-06-25 09:17:33 -07:00
Kristiyan Kostadinov
64990a50ed refactor(compiler): integrate let declarations into the template pipeline (#56299)
These changes integrate let declarations into the template pipeline. This involves a few operations:
* Producing a `declareLet` instruction call at creation time to initialize the declaration.
* Producing a `storeLet` instruction call in the place of the let declaration, including the necessary `advance` calls beforehand.
* For let declarations used within their declaration view, moving the `const` to be placed right after the `storeLet` call to ensure the their value has been computed.
* For let declarations that are _only_ used in their declaration view, removing the `storeLet` call and inlining the expression into the constant statement.

PR Close #56299
2024-06-20 08:48:52 -07:00
Joey Perrott
0bd55a684f refactor(docs-infra): complete removal of aio directory (#56496)
Finish removal of aio directory as it is no longer used or relied upon.

PR Close #56496
2024-06-18 12:26:00 -07:00