Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: migrate core to prettier formatting #55488

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 7 additions & 2 deletions .ng-dev/format.mts
Expand Up @@ -18,7 +18,7 @@ export const format: FormatConfig = {
'packages/benchpress/**/*.{js,ts}',
'packages/common/**/*.{js,ts}',
'packages/compiler/**/*.{js,ts}',
'packages/core/primitives/**/*.{js,ts}',
'packages/core/**/*.{js,ts}',
'packages/docs/**/*.{js,ts}',
'packages/elements/**/*.{js,ts}',
'packages/examples/**/*.{js,ts}',
Expand All @@ -40,6 +40,11 @@ export const format: FormatConfig = {
// not be modified.
'!third_party/**',
'!.yarn/**',
// Do not format the locale files which are checked-in for Google3, but generated using
// the `generate-locales-tool` from `packages/common/locales`.
'!packages/core/src/i18n/locale_en.ts',
'!packages/common/locales/closure-locale.ts',
'!packages/common/src/i18n/currencies.ts',
],
},
'clang-format': {
Expand Down Expand Up @@ -77,7 +82,7 @@ export const format: FormatConfig = {
'!packages/benchpress/**/*.{js,ts}',
'!packages/common/**/*.{js,ts}',
'!packages/compiler/**/*.{js,ts}',
'!packages/core/primitives/**/*.{js,ts}',
'!packages/core/**/*.{js,ts}',
'!packages/docs/**/*.{js,ts}',
'!packages/elements/**/*.{js,ts}',
'!packages/examples/**/*.{js,ts}',
Expand Down
2 changes: 1 addition & 1 deletion goldens/public-api/core/index.md
Expand Up @@ -1205,7 +1205,7 @@ export class NgProbeToken {

// @public
export class NgZone {
constructor({ enableLongStackTrace, shouldCoalesceEventChangeDetection, shouldCoalesceRunChangeDetection }: {
constructor({ enableLongStackTrace, shouldCoalesceEventChangeDetection, shouldCoalesceRunChangeDetection, }: {
enableLongStackTrace?: boolean | undefined;
shouldCoalesceEventChangeDetection?: boolean | undefined;
shouldCoalesceRunChangeDetection?: boolean | undefined;
Expand Down
26 changes: 19 additions & 7 deletions packages/core/rxjs-interop/src/output_from_observable.ts
Expand Up @@ -6,7 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/

import {assertInInjectionContext, DestroyRef, inject, OutputOptions, OutputRef, OutputRefSubscription, ɵRuntimeError, ɵRuntimeErrorCode} from '@angular/core';
import {
assertInInjectionContext,
DestroyRef,
inject,
OutputOptions,
OutputRef,
OutputRefSubscription,
ɵRuntimeError,
ɵRuntimeErrorCode,
} from '@angular/core';
import {Observable} from 'rxjs';

import {takeUntilDestroyed} from './take_until_destroyed';
Expand All @@ -31,15 +40,16 @@ class OutputFromObservableRef<T> implements OutputRef<T> {
subscribe(callbackFn: (value: T) => void): OutputRefSubscription {
if (this.destroyed) {
throw new ɵRuntimeError(
ɵRuntimeErrorCode.OUTPUT_REF_DESTROYED,
ngDevMode &&
'Unexpected subscription to destroyed `OutputRef`. ' +
'The owning directive/component is destroyed.');
ɵRuntimeErrorCode.OUTPUT_REF_DESTROYED,
ngDevMode &&
'Unexpected subscription to destroyed `OutputRef`. ' +
'The owning directive/component is destroyed.',
);
}

// Stop yielding more values when the directive/component is already destroyed.
const subscription = this.source.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
next: value => callbackFn(value),
next: (value) => callbackFn(value),
});

return {
Expand Down Expand Up @@ -73,7 +83,9 @@ class OutputFromObservableRef<T> implements OutputRef<T> {
* @developerPreview
*/
export function outputFromObservable<T>(
observable: Observable<T>, opts?: OutputOptions): OutputRef<T> {
observable: Observable<T>,
opts?: OutputOptions,
): OutputRef<T> {
ngDevMode && assertInInjectionContext(outputFromObservable);
return new OutputFromObservableRef<T>(observable);
}
4 changes: 2 additions & 2 deletions packages/core/rxjs-interop/src/output_to_observable.ts
Expand Up @@ -20,13 +20,13 @@ import {Observable} from 'rxjs';
export function outputToObservable<T>(ref: OutputRef<T>): Observable<T> {
const destroyRef = ɵgetOutputDestroyRef(ref);

return new Observable<T>(observer => {
return new Observable<T>((observer) => {
// Complete the observable upon directive/component destroy.
// Note: May be `undefined` if an `EventEmitter` is declared outside
// of an injection context.
destroyRef?.onDestroy(() => observer.complete());

const subscription = ref.subscribe(v => observer.next(v));
const subscription = ref.subscribe((v) => observer.next(v));
return () => subscription.unsubscribe();
});
}
2 changes: 1 addition & 1 deletion packages/core/rxjs-interop/src/take_until_destroyed.ts
Expand Up @@ -26,7 +26,7 @@ export function takeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperator
destroyRef = inject(DestroyRef);
}

const destroyed$ = new Observable<void>(observer => {
const destroyed$ = new Observable<void>((observer) => {
const unregisterFn = destroyRef!.onDestroy(observer.next.bind(observer));
return unregisterFn;
});
Expand Down
38 changes: 23 additions & 15 deletions packages/core/rxjs-interop/src/to_observable.ts
Expand Up @@ -6,7 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/

import {assertInInjectionContext, DestroyRef, effect, inject, Injector, Signal, untracked} from '@angular/core';
import {
assertInInjectionContext,
DestroyRef,
effect,
inject,
Injector,
Signal,
untracked,
} from '@angular/core';
import {Observable, ReplaySubject} from 'rxjs';

/**
Expand All @@ -33,24 +41,24 @@ export interface ToObservableOptions {
*
* @developerPreview
*/
export function toObservable<T>(
source: Signal<T>,
options?: ToObservableOptions,
): Observable<T> {
export function toObservable<T>(source: Signal<T>, options?: ToObservableOptions): Observable<T> {
!options?.injector && assertInInjectionContext(toObservable);
const injector = options?.injector ?? inject(Injector);
const subject = new ReplaySubject<T>(1);

const watcher = effect(() => {
let value: T;
try {
value = source();
} catch (err) {
untracked(() => subject.error(err));
return;
}
untracked(() => subject.next(value));
}, {injector, manualCleanup: true});
const watcher = effect(
() => {
let value: T;
try {
value = source();
} catch (err) {
untracked(() => subject.error(err));
return;
}
untracked(() => subject.next(value));
},
{injector, manualCleanup: true},
);

injector.get(DestroyRef).onDestroy(() => {
watcher.destroy();
Expand Down
75 changes: 48 additions & 27 deletions packages/core/rxjs-interop/src/to_signal.ts
Expand Up @@ -6,7 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/

import {assertInInjectionContext, assertNotInReactiveContext, computed, DestroyRef, inject, Injector, signal, Signal, WritableSignal, ɵRuntimeError, ɵRuntimeErrorCode} from '@angular/core';
import {
assertInInjectionContext,
assertNotInReactiveContext,
computed,
DestroyRef,
inject,
Injector,
signal,
Signal,
WritableSignal,
ɵRuntimeError,
ɵRuntimeErrorCode,
} from '@angular/core';
import {Observable, Subscribable} from 'rxjs';

/**
Expand Down Expand Up @@ -61,23 +73,27 @@ export interface ToSignalOptions {
}

// Base case: no options -> `undefined` in the result type.
export function toSignal<T>(source: Observable<T>|Subscribable<T>): Signal<T|undefined>;
export function toSignal<T>(source: Observable<T> | Subscribable<T>): Signal<T | undefined>;
// Options with `undefined` initial value and no `requiredSync` -> `undefined`.
export function toSignal<T>(
source: Observable<T>|Subscribable<T>,
options: ToSignalOptions&{initialValue?: undefined, requireSync?: false}): Signal<T|undefined>;
source: Observable<T> | Subscribable<T>,
options: ToSignalOptions & {initialValue?: undefined; requireSync?: false},
): Signal<T | undefined>;
// Options with `null` initial value -> `null`.
export function toSignal<T>(
source: Observable<T>|Subscribable<T>,
options: ToSignalOptions&{initialValue?: null, requireSync?: false}): Signal<T|null>;
source: Observable<T> | Subscribable<T>,
options: ToSignalOptions & {initialValue?: null; requireSync?: false},
): Signal<T | null>;
// Options with `undefined` initial value and `requiredSync` -> strict result type.
export function toSignal<T>(
source: Observable<T>|Subscribable<T>,
options: ToSignalOptions&{initialValue?: undefined, requireSync: true}): Signal<T>;
source: Observable<T> | Subscribable<T>,
options: ToSignalOptions & {initialValue?: undefined; requireSync: true},
): Signal<T>;
// Options with a more specific initial value type.
export function toSignal<T, const U extends T>(
source: Observable<T>|Subscribable<T>,
options: ToSignalOptions&{initialValue: U, requireSync?: false}): Signal<T|U>;
source: Observable<T> | Subscribable<T>,
options: ToSignalOptions & {initialValue: U; requireSync?: false},
): Signal<T | U>;

/**
* Get the current value of an `Observable` as a reactive `Signal`.
Expand All @@ -104,28 +120,31 @@ export function toSignal<T, const U extends T>(
* @developerPreview
*/
export function toSignal<T, U = undefined>(
source: Observable<T>|Subscribable<T>,
options?: ToSignalOptions&{initialValue?: U}): Signal<T|U> {
source: Observable<T> | Subscribable<T>,
options?: ToSignalOptions & {initialValue?: U},
): Signal<T | U> {
ngDevMode &&
assertNotInReactiveContext(
toSignal,
'Invoking `toSignal` causes new subscriptions every time. ' +
'Consider moving `toSignal` outside of the reactive context and read the signal value where needed.');
assertNotInReactiveContext(
toSignal,
'Invoking `toSignal` causes new subscriptions every time. ' +
'Consider moving `toSignal` outside of the reactive context and read the signal value where needed.',
);

const requiresCleanup = !options?.manualCleanup;
requiresCleanup && !options?.injector && assertInInjectionContext(toSignal);
const cleanupRef =
requiresCleanup ? options?.injector?.get(DestroyRef) ?? inject(DestroyRef) : null;
const cleanupRef = requiresCleanup
? options?.injector?.get(DestroyRef) ?? inject(DestroyRef)
: null;

// Note: T is the Observable value type, and U is the initial value type. They don't have to be
// the same - the returned signal gives values of type `T`.
let state: WritableSignal<State<T|U>>;
let state: WritableSignal<State<T | U>>;
if (options?.requireSync) {
// Initially the signal is in a `NoValue` state.
state = signal({kind: StateKind.NoValue});
} else {
// If an initial value was passed, use it. Otherwise, use `undefined` as the initial value.
state = signal<State<T|U>>({kind: StateKind.Value, value: options?.initialValue as U});
state = signal<State<T | U>>({kind: StateKind.Value, value: options?.initialValue as U});
}

// Note: This code cannot run inside a reactive context (see assertion above). If we'd support
Expand All @@ -135,8 +154,8 @@ export function toSignal<T, U = undefined>(
// subscription. Additional context (related to async pipe):
// https://github.com/angular/angular/pull/50522.
const sub = source.subscribe({
next: value => state.set({kind: StateKind.Value, value}),
error: error => {
next: (value) => state.set({kind: StateKind.Value, value}),
error: (error) => {
if (options?.rejectErrors) {
// Kick the error back to RxJS. It will be caught and rethrown in a macrotask, which causes
// the error to end up as an uncaught exception.
Expand All @@ -150,8 +169,9 @@ export function toSignal<T, U = undefined>(

if (ngDevMode && options?.requireSync && state().kind === StateKind.NoValue) {
throw new ɵRuntimeError(
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.');
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.',
);
}

// Unsubscribe when the current context is destroyed, if requested.
Expand All @@ -170,8 +190,9 @@ export function toSignal<T, U = undefined>(
// This shouldn't really happen because the error is thrown on creation.
// TODO(alxhub): use a RuntimeError when we finalize the error semantics
throw new ɵRuntimeError(
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.');
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.',
);
}
});
}
Expand All @@ -196,4 +217,4 @@ interface ErrorState {
error: unknown;
}

type State<T> = NoValueState|ValueState<T>|ErrorState;
type State<T> = NoValueState | ValueState<T> | ErrorState;