@aurelia/runtime
Advanced tools
Comparing version 2.1.0-dev.202304270200 to 2.1.0-dev.202305021031
@@ -10,3 +10,3 @@ export { ExpressionKind, CallFunctionExpression, CustomExpression, BindingBehaviorExpression, ValueConverterExpression, AssignExpression, ConditionalExpression, AccessThisExpression, AccessScopeExpression, AccessMemberExpression, AccessKeyedExpression, CallScopeExpression, CallMemberExpression, BinaryExpression, UnaryExpression, PrimitiveLiteralExpression, ArrayLiteralExpression, ObjectLiteralExpression, TemplateExpression, TaggedTemplateExpression, ArrayBindingPattern, ObjectBindingPattern, BindingIdentifier, ForOfStatement, Interpolation, DestructuringAssignmentExpression, DestructuringAssignmentSingleExpression, DestructuringAssignmentRestExpression, ArrowFunction, astVisit, Unparser, type AnyBindingExpression, type BindingBehaviorInstance, type IsPrimary, type IsLiteral, type IsLeftHandSide, type IsUnary, type IsBinary, type IsConditional, type IsAssign, type IsValueConverter, type IsBindingBehavior, type IsAssignable, type IsExpression, type IsExpressionOrStatement, type IVisitor, type BinaryOperator, type BindingIdentifierOrPattern, type UnaryOperator, type IAstEvaluator, type ValueConverterInstance, } from './binding/ast'; | ||
export { CollectionLengthObserver, CollectionSizeObserver, } from './observation/collection-length-observer'; | ||
export { ComputedObserver, } from './observation/computed-observer'; | ||
export { ComputedObserver, type ComputedGetterFn, } from './observation/computed-observer'; | ||
export { IDirtyChecker, DirtyCheckProperty, DirtyCheckSettings, } from './observation/dirty-checker'; | ||
@@ -13,0 +13,0 @@ export { type IEffect, IObservation, Observation, type EffectRunFunc, } from './observation/observation'; |
@@ -27,3 +27,3 @@ import { IDisposable, IIndexable, IServiceLocator } from '@aurelia/kernel'; | ||
} | ||
export type InterceptorFunc<TInput = unknown, TOutput = unknown> = (value: TInput, coercionConfig: ICoercionConfiguration | null) => TOutput; | ||
export type InterceptorFunc<TInput = unknown, TOutput = unknown> = (value: TInput, coercionConfig?: ICoercionConfiguration) => TOutput; | ||
export interface IConnectable { | ||
@@ -127,2 +127,4 @@ observe(obj: object, key: PropertyKey): void; | ||
doNotCache?: boolean; | ||
useCallback?(callback: (newValue: TValue, oldValue: TValue) => void): boolean; | ||
useCoercer?(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration): boolean; | ||
} | ||
@@ -129,0 +131,0 @@ export type AccessorOrObserver = (IAccessor | IObserver) & { |
@@ -1,2 +0,2 @@ | ||
import { AccessorType, IObserver } from '../observation'; | ||
import { AccessorType, ICoercionConfiguration, IObserver, InterceptorFunc } from '../observation'; | ||
import type { ISubscriber, ICollectionSubscriber, ISubscriberCollection, IConnectable } from '../observation'; | ||
@@ -23,4 +23,7 @@ import type { IConnectableBinding } from '../binding/connectable'; | ||
constructor(obj: T, get: ComputedGetterFn<T>, set: undefined | ((v: unknown) => void), observerLocator: IObserverLocator, useProxy: boolean); | ||
init(value: unknown): void; | ||
getValue(): any; | ||
setValue(v: unknown): void; | ||
useCoercer(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration | undefined): boolean; | ||
useCallback(callback: (newValue: unknown, oldValue: unknown) => void): boolean; | ||
handleChange(): void; | ||
@@ -27,0 +30,0 @@ handleCollectionChange(): void; |
@@ -0,1 +1,2 @@ | ||
import { AccessorType, IAccessor, ISubscriberCollection } from '../observation'; | ||
import type { Constructable } from '@aurelia/kernel'; | ||
@@ -14,2 +15,10 @@ import type { InterceptorFunc } from '../observation'; | ||
export declare function observable(): PropertyDecorator; | ||
export interface SetterNotifier extends IAccessor, ISubscriberCollection { | ||
} | ||
export declare class SetterNotifier implements IAccessor { | ||
readonly type: AccessorType; | ||
constructor(obj: object, callbackKey: PropertyKey, set: InterceptorFunc | undefined, initialValue: unknown); | ||
getValue(): unknown; | ||
setValue(value: unknown): void; | ||
} | ||
//# sourceMappingURL=observable.d.ts.map |
export declare const rawKey = "__raw__"; | ||
export declare function wrap<T>(v: T): T; | ||
export declare function getProxy<T extends object>(obj: T): T; | ||
export declare function getRaw<T extends object>(obj: T): T; | ||
export declare function unwrap<T>(v: T): T; | ||
export declare const ProxyObservable: Readonly<{ | ||
@@ -3,0 +7,0 @@ getProxy: typeof getProxy; |
@@ -1,4 +0,4 @@ | ||
import { AccessorType } from '../observation'; | ||
import { AccessorType, ICoercionConfiguration, IObserver, InterceptorFunc } from '../observation'; | ||
import type { IIndexable } from '@aurelia/kernel'; | ||
import type { IAccessor, InterceptorFunc, ISubscriber, ISubscriberCollection } from '../observation'; | ||
import type { ISubscriber, ISubscriberCollection } from '../observation'; | ||
export interface SetterObserver extends ISubscriberCollection { | ||
@@ -10,3 +10,3 @@ } | ||
*/ | ||
export declare class SetterObserver implements IAccessor, ISubscriberCollection { | ||
export declare class SetterObserver implements IObserver, ISubscriberCollection { | ||
type: AccessorType; | ||
@@ -16,2 +16,4 @@ constructor(obj: IIndexable, key: PropertyKey); | ||
setValue(newValue: unknown): void; | ||
useCallback(callback: (newValue: unknown, oldValue: unknown) => void): boolean; | ||
useCoercer(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration | undefined): boolean; | ||
subscribe(subscriber: ISubscriber): void; | ||
@@ -21,10 +23,2 @@ start(): this; | ||
} | ||
export interface SetterNotifier extends IAccessor, ISubscriberCollection { | ||
} | ||
export declare class SetterNotifier implements IAccessor { | ||
readonly type: AccessorType; | ||
constructor(obj: object, callbackKey: PropertyKey, set: InterceptorFunc | undefined, initialValue: unknown); | ||
getValue(): unknown; | ||
setValue(value: unknown): void; | ||
} | ||
//# sourceMappingURL=setter-observer.d.ts.map |
{ | ||
"name": "@aurelia/runtime", | ||
"version": "2.1.0-dev.202304270200", | ||
"version": "2.1.0-dev.202305021031", | ||
"main": "dist/cjs/index.cjs", | ||
@@ -52,5 +52,5 @@ "module": "dist/esm/index.mjs", | ||
"dependencies": { | ||
"@aurelia/kernel": "2.1.0-dev.202304270200", | ||
"@aurelia/metadata": "2.1.0-dev.202304270200", | ||
"@aurelia/platform": "2.1.0-dev.202304270200" | ||
"@aurelia/kernel": "2.1.0-dev.202305021031", | ||
"@aurelia/metadata": "2.1.0-dev.202305021031", | ||
"@aurelia/platform": "2.1.0-dev.202305021031" | ||
}, | ||
@@ -57,0 +57,0 @@ "devDependencies": { |
@@ -104,2 +104,3 @@ export { | ||
ComputedObserver, | ||
type ComputedGetterFn, | ||
} from './observation/computed-observer'; | ||
@@ -106,0 +107,0 @@ export { |
@@ -33,3 +33,3 @@ import { DI, IDisposable, IIndexable, IServiceLocator } from '@aurelia/kernel'; | ||
export type InterceptorFunc<TInput = unknown, TOutput = unknown> = (value: TInput, coercionConfig: ICoercionConfiguration | null) => TOutput; | ||
export type InterceptorFunc<TInput = unknown, TOutput = unknown> = (value: TInput, coercionConfig?: ICoercionConfiguration) => TOutput; | ||
@@ -184,2 +184,4 @@ export interface IConnectable { | ||
doNotCache?: boolean; | ||
useCallback?(callback: (newValue: TValue, oldValue: TValue) => void): boolean; | ||
useCoercer?(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration): boolean; | ||
} | ||
@@ -186,0 +188,0 @@ |
import { | ||
AccessorType, | ||
ICoercionConfiguration, | ||
IObserver, | ||
InterceptorFunc, | ||
} from '../observation'; | ||
@@ -51,2 +53,11 @@ import { subscriberCollection } from './subscriber-collection'; | ||
/** @internal */ | ||
private _callback?: (newValue: unknown, oldValue: unknown) => void = void 0; | ||
/** @internal */ | ||
private _coercer?: InterceptorFunc = void 0; | ||
/** @internal */ | ||
private _coercionConfig?: ICoercionConfiguration = void 0; | ||
/** | ||
@@ -81,2 +92,7 @@ * The getter this observer is wrapping | ||
public init(value: unknown) { | ||
this._value = value; | ||
this._isDirty = false; | ||
} | ||
public getValue() { | ||
@@ -96,3 +112,6 @@ if (this.subs.count === 0) { | ||
if (isFunction(this.$set)) { | ||
if (v !== this._value) { | ||
if (this._coercer !== void 0) { | ||
v = this._coercer.call(null, v, this._coercionConfig); | ||
} | ||
if (!areEqual(v, this._value)) { | ||
// setting running true as a form of batching | ||
@@ -113,2 +132,13 @@ this._isRunning = true; | ||
public useCoercer(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration | undefined): boolean { | ||
this._coercer = coercer; | ||
this._coercionConfig = coercionConfig; | ||
return true; | ||
} | ||
public useCallback(callback: (newValue: unknown, oldValue: unknown) => void) { | ||
this._callback = callback; | ||
return true; | ||
} | ||
public handleChange(): void { | ||
@@ -155,2 +185,5 @@ this._isDirty = true; | ||
if (!areEqual(newValue, oldValue)) { | ||
// todo: probably should set is running here too | ||
// to prevent depth first notification | ||
this._callback?.(newValue, oldValue); | ||
this.subs.notify(this._value, oldValue); | ||
@@ -157,0 +190,0 @@ } |
@@ -1,4 +0,3 @@ | ||
import { IObserver } from '../observation'; | ||
import { SetterNotifier } from './setter-observer'; | ||
import { safeString, def, createError } from '../utilities-objects'; | ||
import { AccessorType, IAccessor, IObserver, ISubscriberCollection } from '../observation'; | ||
import { safeString, def, createError, isFunction, areEqual } from '../utilities-objects'; | ||
import { currentConnectable } from './connectable-switcher'; | ||
@@ -10,2 +9,3 @@ | ||
import type { SetterObserver } from './setter-observer'; | ||
import { subscriberCollection } from './subscriber-collection'; | ||
@@ -163,2 +163,59 @@ export interface IObservableDefinition { | ||
type ChangeHandlerCallback = (this: object, value: unknown, oldValue: unknown) => void; | ||
export interface SetterNotifier extends IAccessor, ISubscriberCollection {} | ||
export class SetterNotifier implements IAccessor { | ||
public readonly type: AccessorType = AccessorType.Observer; | ||
/** @internal */ | ||
private _value: unknown = void 0; | ||
/** @internal */ | ||
private _oldValue: unknown = void 0; | ||
/** @internal */ | ||
private readonly cb?: ChangeHandlerCallback; | ||
/** @internal */ | ||
private readonly _obj: object; | ||
/** @internal */ | ||
private readonly _setter: InterceptorFunc | undefined; | ||
/** @internal */ | ||
private readonly _hasSetter: boolean; | ||
public constructor( | ||
obj: object, | ||
callbackKey: PropertyKey, | ||
set: InterceptorFunc | undefined, | ||
initialValue: unknown, | ||
) { | ||
this._obj = obj; | ||
this._setter = set; | ||
this._hasSetter = isFunction(set); | ||
const callback = (obj as IIndexable)[callbackKey as string]; | ||
this.cb = isFunction(callback) ? callback as ChangeHandlerCallback : void 0; | ||
this._value = initialValue; | ||
} | ||
public getValue(): unknown { | ||
return this._value; | ||
} | ||
public setValue(value: unknown): void { | ||
if (this._hasSetter) { | ||
value = this._setter!(value); | ||
} | ||
if (!areEqual(value, this._value)) { | ||
this._oldValue = this._value; | ||
this._value = value; | ||
this.cb?.call(this._obj, this._value, this._oldValue); | ||
// this._value might have been updated during the callback | ||
// we only want to notify subscribers with the latest values | ||
value = this._oldValue; | ||
this._oldValue = this._value; | ||
this.subs.notify(this._value, value); | ||
} | ||
} | ||
} | ||
subscriberCollection(SetterNotifier); | ||
/* | ||
@@ -165,0 +222,0 @@ | typescript | babel |
@@ -34,7 +34,5 @@ import { IIndexable } from '@aurelia/kernel'; | ||
/** @internal */ | ||
export function wrap<T>(v: T): T { | ||
return canWrap(v) ? getProxy(v) : v; | ||
} | ||
/** @internal */ | ||
export function getProxy<T extends object>(obj: T): T { | ||
@@ -45,3 +43,2 @@ // deepscan-disable-next-line | ||
/** @internal */ | ||
export function getRaw<T extends object>(obj: T): T { | ||
@@ -51,3 +48,2 @@ // todo: get in a weakmap if null/undef | ||
} | ||
/** @internal */ | ||
export function unwrap<T>(v: T): T { | ||
@@ -54,0 +50,0 @@ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions |
@@ -1,9 +0,7 @@ | ||
import { AccessorType } from '../observation'; | ||
import { AccessorType, ICoercionConfiguration, IObserver, InterceptorFunc } from '../observation'; | ||
import { subscriberCollection } from './subscriber-collection'; | ||
import { areEqual, def, isFunction } from '../utilities-objects'; | ||
import { areEqual, def, objectAssign } from '../utilities-objects'; | ||
import type { IIndexable } from '@aurelia/kernel'; | ||
import type { | ||
IAccessor, | ||
InterceptorFunc, | ||
ISubscriber, | ||
@@ -19,3 +17,3 @@ ISubscriberCollection, | ||
*/ | ||
export class SetterObserver implements IAccessor, ISubscriberCollection { | ||
export class SetterObserver implements IObserver, ISubscriberCollection { | ||
// todo(bigopon): tweak the flag based on typeof obj (array/set/map/iterator/proxy etc...) | ||
@@ -29,2 +27,9 @@ public type: AccessorType = AccessorType.Observer; | ||
/** @internal */ | ||
private _callback?: (newValue: unknown, oldValue: unknown) => void = void 0; | ||
/** @internal */ | ||
private _coercer?: InterceptorFunc = void 0; | ||
/** @internal */ | ||
private _coercionConfig?: ICoercionConfiguration = void 0; | ||
/** @internal */ private readonly _obj: IIndexable; | ||
@@ -46,2 +51,5 @@ /** @internal */ private readonly _key: PropertyKey; | ||
public setValue(newValue: unknown): void { | ||
if (this._coercer !== void 0) { | ||
newValue = this._coercer.call(void 0, newValue, this._coercionConfig); | ||
} | ||
if (this._observing) { | ||
@@ -53,2 +61,3 @@ if (areEqual(newValue, this._value)) { | ||
this._value = newValue; | ||
this._callback?.(newValue, oV); | ||
this.subs.notify(newValue, oV); | ||
@@ -62,6 +71,20 @@ } else { | ||
// This wasn't visible in vCurrent due to connect-queue always doing a delayed update, so in many cases it didn't matter whether bind updated the target or not. | ||
this._obj[this._key] = newValue; | ||
this._value = this._obj[this._key] = newValue; | ||
this._callback?.(newValue, oV); | ||
} | ||
} | ||
public useCallback(callback: (newValue: unknown, oldValue: unknown) => void): boolean { | ||
this._callback = callback; | ||
this.start(); | ||
return true; | ||
} | ||
public useCoercer(coercer: InterceptorFunc, coercionConfig?: ICoercionConfiguration | undefined): boolean { | ||
this._coercer = coercer; | ||
this._coercionConfig = coercionConfig; | ||
this.start(); | ||
return true; | ||
} | ||
public subscribe(subscriber: ISubscriber): void { | ||
@@ -85,3 +108,3 @@ if (this._observing === false) { | ||
configurable: true, | ||
get: (/* Setter Observer */) => this.getValue(), | ||
get: objectAssign((/* Setter Observer */) => this.getValue(), { getObserver: () => this }), | ||
set: (/* Setter Observer */value) => { | ||
@@ -111,59 +134,3 @@ this.setValue(value); | ||
type ChangeHandlerCallback = (this: object, value: unknown, oldValue: unknown) => void; | ||
export interface SetterNotifier extends IAccessor, ISubscriberCollection {} | ||
export class SetterNotifier implements IAccessor { | ||
public readonly type: AccessorType = AccessorType.Observer; | ||
/** @internal */ | ||
private _value: unknown = void 0; | ||
/** @internal */ | ||
private _oldValue: unknown = void 0; | ||
/** @internal */ | ||
private readonly cb?: ChangeHandlerCallback; | ||
/** @internal */ | ||
private readonly _obj: object; | ||
/** @internal */ | ||
private readonly _setter: InterceptorFunc | undefined; | ||
/** @internal */ | ||
private readonly _hasSetter: boolean; | ||
public constructor( | ||
obj: object, | ||
callbackKey: PropertyKey, | ||
set: InterceptorFunc | undefined, | ||
initialValue: unknown, | ||
) { | ||
this._obj = obj; | ||
this._setter = set; | ||
this._hasSetter = isFunction(set); | ||
const callback = (obj as IIndexable)[callbackKey as string]; | ||
this.cb = isFunction(callback) ? callback as ChangeHandlerCallback : void 0; | ||
this._value = initialValue; | ||
} | ||
public getValue(): unknown { | ||
return this._value; | ||
} | ||
public setValue(value: unknown): void { | ||
if (this._hasSetter) { | ||
value = this._setter!(value, null); | ||
} | ||
if (!areEqual(value, this._value)) { | ||
this._oldValue = this._value; | ||
this._value = value; | ||
this.cb?.call(this._obj, this._value, this._oldValue); | ||
// this._value might have been updated during the callback | ||
// we only want to notify subscribers with the latest values | ||
oV = this._oldValue; | ||
this._oldValue = this._value; | ||
this.subs.notify(this._value, oV); | ||
} | ||
} | ||
} | ||
subscriberCollection(SetterObserver); | ||
subscriberCollection(SetterNotifier); | ||
@@ -170,0 +137,0 @@ // a reusable variable for `.flush()` methods of observers |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1649887
34997
+ Added@aurelia/kernel@2.1.0-dev.202305021031(transitive)
+ Added@aurelia/metadata@2.1.0-dev.202305021031(transitive)
+ Added@aurelia/platform@2.1.0-dev.202305021031(transitive)
- Removed@aurelia/kernel@2.1.0-dev.202304270200(transitive)
- Removed@aurelia/metadata@2.1.0-dev.202304270200(transitive)
- Removed@aurelia/platform@2.1.0-dev.202304270200(transitive)