refactor(core): expose private setAlternateWeakRefImpl (#49466)

This commit adds the ability to override the `WeakRef` implementation used
by signals as a private API. This can be used in certain environments to
allow tests which use older browsers to still run, albeit without weak
references.

PR Close #49466
This commit is contained in:
Alex Rickabaugh
2023-03-20 11:46:38 -07:00
committed by Andrew Scott
parent 897a9e578d
commit 84a2ad7b01
6 changed files with 26 additions and 9 deletions
+1
View File
@@ -26,6 +26,7 @@ export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/r
export {allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, BypassType as ɵBypassType, getSanitizationBypassType as ɵgetSanitizationBypassType, SafeHtml as ɵSafeHtml, SafeResourceUrl as ɵSafeResourceUrl, SafeScript as ɵSafeScript, SafeStyle as ɵSafeStyle, SafeUrl as ɵSafeUrl, SafeValue as ɵSafeValue, unwrapSafeValue as ɵunwrapSafeValue} from './sanitization/bypass';
export {_sanitizeHtml as ɵ_sanitizeHtml} from './sanitization/html_sanitizer';
export {_sanitizeUrl as ɵ_sanitizeUrl} from './sanitization/url_sanitizer';
export {setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl} from './signals';
export {TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER} from './testability/testability';
export {escapeTransferStateContent as ɵescapeTransferStateContent, makeStateKey as ɵmakeStateKey, StateKey as ɵStateKey, TransferState as ɵTransferState, unescapeTransferStateContent as ɵunescapeTransferStateContent} from './transfer_state';
export {coerceToBoolean as ɵcoerceToBoolean} from './util/coercion';
+1
View File
@@ -13,3 +13,4 @@ export {setActiveConsumer} from './src/graph';
export {SettableSignal, signal} from './src/signal';
export {untracked} from './src/untracked';
export {Watch} from './src/watch';
export {setAlternateWeakRefImpl} from './src/weak_ref';
+2 -2
View File
@@ -8,7 +8,7 @@
import {createSignalFromFunction, defaultEquals, Signal, ValueEqualityFn} from './api';
import {Consumer, ConsumerId, consumerPollValueStatus, Edge, nextReactiveId, Producer, producerAccessed, ProducerId, producerNotifyConsumers, setActiveConsumer} from './graph';
import {WeakRef} from './weak_ref';
import {newWeakRef} from './weak_ref';
/**
* Create a computed `Signal` which derives a reactive value from an expression.
@@ -70,7 +70,7 @@ class ComputedImpl<T> implements Producer, Consumer {
private stale = true;
readonly id = nextReactiveId();
readonly ref = new WeakRef(this);
readonly ref = newWeakRef(this);
readonly producers = new Map<ProducerId, Edge>();
readonly consumers = new Map<ConsumerId, Edge>();
trackingVersion = 0;
+2 -2
View File
@@ -8,7 +8,7 @@
import {createSignalFromFunction, defaultEquals, Signal, ValueEqualityFn} from './api';
import {ConsumerId, Edge, nextReactiveId, Producer, producerAccessed, producerNotifyConsumers} from './graph';
import {WeakRef} from './weak_ref';
import {newWeakRef, WeakRef} from './weak_ref';
/**
* A `Signal` with a value that can be mutated via a setter interface.
@@ -41,7 +41,7 @@ class SettableSignalImpl<T> implements Producer {
constructor(private value: T, private equal: ValueEqualityFn<T>) {}
readonly id = nextReactiveId();
readonly ref = new WeakRef(this);
readonly ref = newWeakRef(this);
readonly consumers = new Map<ConsumerId, Edge>();
valueVersion = 0;
+2 -2
View File
@@ -7,7 +7,7 @@
*/
import {Consumer, consumerPollValueStatus, Edge, nextReactiveId, ProducerId, setActiveConsumer} from './graph';
import {WeakRef} from './weak_ref';
import {newWeakRef} from './weak_ref';
/**
* Watches a reactive expression and allows it to be scheduled to re-run
@@ -18,7 +18,7 @@ import {WeakRef} from './weak_ref';
*/
export class Watch implements Consumer {
readonly id = nextReactiveId();
readonly ref = new WeakRef(this);
readonly ref = newWeakRef(this);
readonly producers = new Map<ProducerId, Edge>();
trackingVersion = 0;
+18 -3
View File
@@ -9,15 +9,30 @@
import {global} from '../../util/global';
// `WeakRef` is not always defined in every TS environment where Angular is compiled. Instead,
// alias it as a local export by reading it off of the global context.
// read it off of the global context if available.
// tslint:disable-next-line: no-toplevel-property-access
let WeakRefImpl: WeakRefCtor|undefined = global['WeakRef'];
export interface WeakRef<T extends object> {
deref(): T|undefined;
}
export function newWeakRef<T extends object>(value: T): WeakRef<T> {
if (typeof ngDevMode !== 'undefined' && ngDevMode && WeakRefImpl === undefined) {
throw new Error(`Angular requires a browser which supports the 'WeakRef' API`);
}
return new WeakRefImpl!(value);
}
export interface WeakRefCtor {
new<T extends object>(value: T): WeakRef<T>;
}
// tslint:disable-next-line: no-toplevel-property-access
export const WeakRef: WeakRefCtor = global['WeakRef'];
/**
* Use an alternate implementation of `WeakRef` if a platform implementation isn't available.
*/
export function setAlternateWeakRefImpl(impl: WeakRefCtor) {
if (!WeakRefImpl) {
WeakRefImpl = impl;
}
}