Skip to content

Commit

Permalink
Merge pull request #242 from angular/main
Browse files Browse the repository at this point in the history
Create a new pull request by comparing changes across two branches
  • Loading branch information
GulajavaMinistudio authored Oct 11, 2024
2 parents e19ac75 + fc6c76a commit d1ba1a9
Show file tree
Hide file tree
Showing 30 changed files with 645 additions and 97 deletions.
88 changes: 88 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,91 @@
<a name="19.0.0-next.9"></a>
# 19.0.0-next.9 (2024-10-10)
## Breaking Changes
### compiler
- `this.foo` property reads no longer refer to template context variables. If you intended to read the template variable, do not use `this.`.
### core
- The deprecated `factories` property in `KeyValueDiffers` has been removed.
### localize
- The `name` option in the `ng add `@localize`` schematic has been removed in favor of the `project` option.
### platform-browser
- The deprecated `BrowserModule.withServerTransition` method has been removed. Please use the `APP_ID` DI token to set the application id instead.
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [09f589f000](https://github.com/angular/angular/commit/09f589f0006f4b428b675b83c12c0dc8ebb7e45f) | fix | `this.a` should always refer to class property `a` ([#55183](https://github.com/angular/angular/pull/55183)) |
| [e8d1944999](https://github.com/angular/angular/commit/e8d1944999e1fdfbd67630d475334c0d7f41a0eb) | fix | add multiple :host and nested selectors support ([#57796](https://github.com/angular/angular/pull/57796)) |
| [82144b6d63](https://github.com/angular/angular/commit/82144b6d63d072d112d1a7f4dcc018a1d64bb994) | fix | allow combinators inside pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
| [292ea4714f](https://github.com/angular/angular/commit/292ea4714fb7e76cf1748d2f9059991e05c42574) | fix | fix comment typo ([#57796](https://github.com/angular/angular/pull/57796)) |
| [69529d8873](https://github.com/angular/angular/commit/69529d8873fbd7888ab68fddc6e7c654c5065764) | fix | fix parsing of the :host-context with pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
| [2374b87b64](https://github.com/angular/angular/commit/2374b87b643e0373f85cf126d4b01b2fff785f64) | fix | preserve attributes attached to :host selector ([#57796](https://github.com/angular/angular/pull/57796)) |
| [46a6324c82](https://github.com/angular/angular/commit/46a6324c82a41b69c16a4c8c9f3fc52d1ecf6917) | fix | scope :host-context inside pseudo selectors, do not decrease specificity ([#57796](https://github.com/angular/angular/pull/57796)) |
| [bc5f1175e9](https://github.com/angular/angular/commit/bc5f1175e9f39dfa2699c4de19ee9af4ce4b50d1) | fix | transform pseudo selectors correctly for the encapsulated view ([#57796](https://github.com/angular/angular/pull/57796)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [8d8c03abc4](https://github.com/angular/angular/commit/8d8c03abc40099da268d7301f029954f3e3f1c90) | fix | defer symbols only used in types ([#58104](https://github.com/angular/angular/pull/58104)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [ee426c62f0](https://github.com/angular/angular/commit/ee426c62f07579ec7dc89ce9582972cc1e3471d4) | fix | allow signal write error ([#57973](https://github.com/angular/angular/pull/57973)) |
| [67db4305c2](https://github.com/angular/angular/commit/67db4305c2261625fd54d284c29e94e26cb19488) | fix | clean up afterRender after it is executed ([#58119](https://github.com/angular/angular/pull/58119)) |
| [656b5d3e78](https://github.com/angular/angular/commit/656b5d3e78004229a76488e0de1eb1d3508d8f6d) | fix | Re-assign error codes to be within core bounds (<1000) ([#53455](https://github.com/angular/angular/pull/53455)) |
| [97fb86d331](https://github.com/angular/angular/commit/97fb86d3310ae891ba4d894a8d3479eda08bd4c2) | perf | set encapsulation to `None` for empty component styles ([#57130](https://github.com/angular/angular/pull/57130)) |
| [c15ec36bd1](https://github.com/angular/angular/commit/c15ec36bd1dcff4c7c387337a5bcfd928994db2f) | refactor | remove deprecated `factories` Property in `KeyValueDiffers` ([#58064](https://github.com/angular/angular/pull/58064)) |
### language-service
| Commit | Type | Description |
| -- | -- | -- |
| [bc83fc1e2e](https://github.com/angular/angular/commit/bc83fc1e2ebac1a99b6e8ed63cea48f48dd7c863) | feat | support converting to signal queries in VSCode extension ([#58106](https://github.com/angular/angular/pull/58106)) |
### localize
| Commit | Type | Description |
| -- | -- | -- |
| [9c3bd1b5d1](https://github.com/angular/angular/commit/9c3bd1b5d119bdcd4818892deae7f8a17861da42) | refactor | remove deprecated `name` option. ([#58063](https://github.com/angular/angular/pull/58063)) |
### migrations
| Commit | Type | Description |
| -- | -- | -- |
| [c1aa411cf1](https://github.com/angular/angular/commit/c1aa411cf13259d991c8f224a2bafc3e9763fe8d) | fix | properly resolve tsconfig paths on windows ([#58137](https://github.com/angular/angular/pull/58137)) |
### platform-browser
| Commit | Type | Description |
| -- | -- | -- |
| [5c61f46409](https://github.com/angular/angular/commit/5c61f46409855bb8fe66d71a9c16c00753032987) | refactor | remove deprecated `BrowserModule.withServerTransition` method ([#58062](https://github.com/angular/angular/pull/58062)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [9e82559de4](https://github.com/angular/angular/commit/9e82559de4e99a1aedf645a05b01fc08d3f4b1b1) | fix | destroy `PlatformRef` when error happens during the `bootstrap()` phase ([#58112](https://github.com/angular/angular/pull/58112)) |
### service-worker
| Commit | Type | Description |
| -- | -- | -- |
| [1479af978c](https://github.com/angular/angular/commit/1479af978cd2bbe4ee9f1ca9682684b8e5135fa7) | feat | finish implementation of refreshAhead feature ([#53356](https://github.com/angular/angular/pull/53356)) |

<!-- CHANGELOG SPLIT MARKER -->

<a name="18.2.8"></a>
# 18.2.8 (2024-10-10)
### compiler
| Commit | Type | Description |
| -- | -- | -- |
| [11692c8dab](https://github.com/angular/angular/commit/11692c8dab2a78dc8780ceed301242d51dee7c9c) | fix | add multiple :host and nested selectors support ([#57796](https://github.com/angular/angular/pull/57796)) |
| [66dcc691f5](https://github.com/angular/angular/commit/66dcc691f55eafc9de9a233b9bab53284fc13e1b) | fix | allow combinators inside pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
| [48a1437e77](https://github.com/angular/angular/commit/48a1437e77be5c3b29b8bbcd1b5d7784fbb67e68) | fix | fix comment typo ([#57796](https://github.com/angular/angular/pull/57796)) |
| [d325f9b55f](https://github.com/angular/angular/commit/d325f9b55f248e5bd059645be901f210018f8fa2) | fix | fix parsing of the :host-context with pseudo selectors ([#57796](https://github.com/angular/angular/pull/57796)) |
| [aea747ab3b](https://github.com/angular/angular/commit/aea747ab3bcbca79dbbc7ddfc41e11b9e43952eb) | fix | preserve attributes attached to :host selector ([#57796](https://github.com/angular/angular/pull/57796)) |
| [21be258be6](https://github.com/angular/angular/commit/21be258be687a300ca22daad823e0b931029db35) | fix | scope :host-context inside pseudo selectors, do not decrease specificity ([#57796](https://github.com/angular/angular/pull/57796)) |
| [7a6fd427d5](https://github.com/angular/angular/commit/7a6fd427d5ad70ad4c50693f54a6e77bf51eea86) | fix | transform pseudo selectors correctly for the encapsulated view ([#57796](https://github.com/angular/angular/pull/57796)) |
### compiler-cli
| Commit | Type | Description |
| -- | -- | -- |
| [f187c3abf8](https://github.com/angular/angular/commit/f187c3abf8b9547b2692995f344cd7dcb9f32ebc) | fix | defer symbols only used in types ([#58104](https://github.com/angular/angular/pull/58104)) |
### core
| Commit | Type | Description |
| -- | -- | -- |
| [46bafb0b0a](https://github.com/angular/angular/commit/46bafb0b0a952d8e9c2a0099f0607354697bbeaa) | fix | clean up afterRender after it is executed ([#58119](https://github.com/angular/angular/pull/58119)) |
### platform-server
| Commit | Type | Description |
| -- | -- | -- |
| [b40875a2cc](https://github.com/angular/angular/commit/b40875a2cc28a94015e6392044a03b30c2559999) | fix | destroy `PlatformRef` when error happens during the `bootstrap()` phase ([#58112](https://github.com/angular/angular/pull/58112)) ([#58135](https://github.com/angular/angular/pull/58135)) |

<!-- CHANGELOG SPLIT MARKER -->

<a name="19.0.0-next.8"></a>
# 19.0.0-next.8 (2024-10-02)
### common
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
* found in the LICENSE file at https://angular.dev/license
*/

import {ChangeDetectionStrategy, Component, Input, computed, inject} from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
DestroyRef,
Input,
computed,
inject,
} from '@angular/core';
import {RouterLink} from '@angular/router';
import {TableOfContentsLevel} from '../../interfaces/index';
import {TableOfContentsLoader} from '../../services/table-of-contents-loader.service';
Expand All @@ -27,6 +34,8 @@ export class TableOfContents {

private readonly scrollSpy = inject(TableOfContentsScrollSpy);
private readonly tableOfContentsLoader = inject(TableOfContentsLoader);
private readonly destroyRef = inject(DestroyRef);

tableOfContentItems = this.tableOfContentsLoader.tableOfContentItems;

activeItemId = this.scrollSpy.activeItemId;
Expand All @@ -35,7 +44,7 @@ export class TableOfContents {

ngAfterViewInit() {
this.tableOfContentsLoader.buildTableOfContent(this.contentSourceElement);
this.scrollSpy.startListeningToScroll(this.contentSourceElement);
this.scrollSpy.startListeningToScroll(this.contentSourceElement, this.destroyRef);
}

scrollToTop(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export class DocViewer implements OnChanges {
private readonly elementRef = inject(ElementRef);
private readonly location = inject(Location);
private readonly navigationState = inject(NavigationState);
private readonly platformId = inject(PLATFORM_ID);
private readonly router = inject(Router);
private readonly viewContainer = inject(ViewContainerRef);
private readonly environmentInjector = inject(EnvironmentInjector);
Expand All @@ -86,6 +85,8 @@ export class DocViewer implements OnChanges {
private animateContent = false;
private readonly pendingTasks = inject(PendingTasks);

private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));

private countOfExamples = 0;

async ngOnChanges(changes: SimpleChanges): Promise<void> {
Expand All @@ -97,11 +98,10 @@ export class DocViewer implements OnChanges {
}

async renderContentsAndRunClientSetup(content?: string): Promise<void> {
const isBrowser = isPlatformBrowser(this.platformId);
const contentContainer = this.elementRef.nativeElement;

if (content) {
if (isBrowser && !(this.document as any).startViewTransition) {
if (this.isBrowser && !(this.document as any).startViewTransition) {
// Apply a special class to the host node to trigger animation.
// Note: when a page is hydrated, the `content` would be empty,
// so we don't trigger an animation to avoid a content flickering
Expand All @@ -112,7 +112,7 @@ export class DocViewer implements OnChanges {
contentContainer.innerHTML = content;
}

if (isBrowser) {
if (this.isBrowser) {
// First we setup event listeners on the HTML we just loaded.
// We want to do this before things like the example viewers are loaded.
this.setupAnchorListeners(contentContainer);
Expand Down Expand Up @@ -301,6 +301,14 @@ export class DocViewer implements OnChanges {
// during SSG.
this.appRef.attachView(componentRef.hostView);

// This is wrapped with `isBrowser` in for hydration purposes.
if (this.isBrowser) {
// The `docs-viewer` may be rendered multiple times when navigating
// between pages, which will create new components that need to be
// destroyed for gradual cleanup.
this.destroyRef.onDestroy(() => componentRef.destroy());
}

return componentRef;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
* found in the LICENSE file at https://angular.dev/license
*/

import {DestroyRef} from '@angular/core';
import {DOCUMENT, ViewportScroller} from '@angular/common';
import {TestBed, discardPeriodicTasks, fakeAsync, tick} from '@angular/core/testing';

import {WINDOW} from '../providers';

import {TableOfContentsLoader} from './table-of-contents-loader.service';
import {SCROLL_EVENT_DELAY, TableOfContentsScrollSpy} from './table-of-contents-scroll-spy.service';
import {DOCUMENT, ViewportScroller} from '@angular/common';
import {TableOfContentsLevel} from '../interfaces';

describe('TableOfContentsScrollSpy', () => {
let service: TableOfContentsScrollSpy;
let destroyRef: DestroyRef;
const fakeWindow = {
addEventListener: () => {},
removeEventListener: () => {},
Expand Down Expand Up @@ -68,6 +70,7 @@ describe('TableOfContentsScrollSpy', () => {
const tableOfContentsLoaderSpy = TestBed.inject(TableOfContentsLoader);
tableOfContentsLoaderSpy.tableOfContentItems.set(fakeToCItems);
service = TestBed.inject(TableOfContentsScrollSpy);
destroyRef = TestBed.inject(DestroyRef);
});

it('should be created', () => {
Expand All @@ -94,7 +97,7 @@ describe('TableOfContentsScrollSpy', () => {
const scrollableContainer = doc;
const setActiveItemIdSpy = spyOn(service as any, 'setActiveItemId');

service.startListeningToScroll(doc.querySelector('fake-selector'));
service.startListeningToScroll(doc.querySelector('fake-selector'), destroyRef);

scrollableContainer.dispatchEvent(new Event('scroll'));
tick(SCROLL_EVENT_DELAY - 2);
Expand All @@ -118,7 +121,7 @@ describe('TableOfContentsScrollSpy', () => {
const doc = TestBed.inject(DOCUMENT);
const scrollableContainer = doc;

service.startListeningToScroll(doc.querySelector('fake-selector'));
service.startListeningToScroll(doc.querySelector('fake-selector'), destroyRef);

fakeWindow.scrollY = 1238;
scrollableContainer.dispatchEvent(new Event('scroll'));
Expand All @@ -133,7 +136,7 @@ describe('TableOfContentsScrollSpy', () => {
const doc = TestBed.inject(DOCUMENT);
const scrollableContainer = doc;

service.startListeningToScroll(doc.querySelector('fake-selector'));
service.startListeningToScroll(doc.querySelector('fake-selector'), destroyRef);

fakeWindow.scrollY = 99;
scrollableContainer.dispatchEvent(new Event('scroll'));
Expand Down
36 changes: 25 additions & 11 deletions adev/shared-docs/services/table-of-contents-scroll-spy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const SCROLL_FINISH_DELAY = SCROLL_EVENT_DELAY * 2;
// The service is responsible for listening for scrolling and resizing,
// thanks to which it sets the active item in the Table of contents
export class TableOfContentsScrollSpy {
private readonly destroyRef = inject(DestroyRef);
private readonly tableOfContentsLoader = inject(TableOfContentsLoader);
private readonly document = inject(DOCUMENT);
private readonly window = inject(WINDOW);
Expand All @@ -41,12 +40,25 @@ export class TableOfContentsScrollSpy {
activeItemId = signal<string | null>(null);
scrollbarThumbOnTop = signal<boolean>(true);

startListeningToScroll(contentSourceElement: HTMLElement | null): void {
startListeningToScroll(
contentSourceElement: HTMLElement | null,
// `destroyRef` is required because the caller may invoke `startListeningToScroll`
// multiple times. Without it, previous event listeners would not be disposed of,
// leading to the accumulation of new event listeners.
destroyRef: DestroyRef,
) {
this.contentSourceElement = contentSourceElement;
this.lastContentWidth = this.getContentWidth();

this.setScrollEventHandlers();
this.setResizeEventHandlers();
this.setScrollEventHandlers(destroyRef);
this.setResizeEventHandlers(destroyRef);

destroyRef.onDestroy(() => {
// We also need to clean up the source element once the view that calls
// `startListeningToScroll` is destroyed, as this will keep a reference
// to an element that has been removed from the DOM.
this.contentSourceElement = null;
});
}

scrollToTop(): void {
Expand All @@ -72,9 +84,9 @@ export class TableOfContentsScrollSpy {
}

// After window resize, we should update top value of each table content item
private setResizeEventHandlers() {
private setResizeEventHandlers(destroyRef: DestroyRef) {
fromEvent(this.window, 'resize')
.pipe(debounceTime(RESIZE_EVENT_DELAY), takeUntilDestroyed(this.destroyRef), startWith())
.pipe(debounceTime(RESIZE_EVENT_DELAY), takeUntilDestroyed(destroyRef), startWith())
.subscribe(() => {
this.updateHeadingsTopAfterResize();
});
Expand All @@ -83,14 +95,16 @@ export class TableOfContentsScrollSpy {
// assets (fonts, images) are loaded. They can (and will) change the y-position of the headings.
const docsViewer = this.document.querySelector('docs-viewer');
if (docsViewer) {
afterNextRender(
const ref = afterNextRender(
() => {
const resizeObserver = new ResizeObserver(() => this.updateHeadingsTopAfterResize());
resizeObserver.observe(docsViewer);
this.destroyRef.onDestroy(() => resizeObserver.disconnect());
destroyRef.onDestroy(() => resizeObserver.disconnect());
},
{injector: this.injector},
{injector: this.injector, manualCleanup: true},
);

destroyRef.onDestroy(() => ref.destroy());
}
}

Expand All @@ -104,10 +118,10 @@ export class TableOfContentsScrollSpy {
}
}

private setScrollEventHandlers(): void {
private setScrollEventHandlers(destroyRef: DestroyRef): void {
const scroll$ = fromEvent(this.document, 'scroll').pipe(
auditTime(SCROLL_EVENT_DELAY),
takeUntilDestroyed(this.destroyRef),
takeUntilDestroyed(destroyRef),
);

scroll$.subscribe(() => this.setActiveItemId());
Expand Down
2 changes: 1 addition & 1 deletion adev/src/content/guide/signals/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ data.set(['test']);

Equality functions can be provided to both writable and computed signals.

HELPFUL: By default, signals use referential equality (`===` comparison).
HELPFUL: By default, signals use referential equality ([`Object.is()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison).

### Reading without tracking dependencies

Expand Down
2 changes: 1 addition & 1 deletion adev/src/content/guide/templates/event-listeners.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Adding event listeners

Angular supports defining event listeners on an element in your template by specifying the event name inside parentheses along with a statement that runs even time the event occurs.
Angular supports defining event listeners on an element in your template by specifying the event name inside parentheses along with a statement that runs every time the event occurs.

## Listening to native events

Expand Down
Loading

0 comments on commit d1ba1a9

Please sign in to comment.