diff --git a/packages/runtime-html/src/observation/observer-locator.ts b/packages/runtime-html/src/observation/observer-locator.ts index c769c4e50e..1e99452c8d 100644 --- a/packages/runtime-html/src/observation/observer-locator.ts +++ b/packages/runtime-html/src/observation/observer-locator.ts @@ -117,7 +117,7 @@ export class TargetObserverLocator implements ITargetObserverLocator { case 'css': return new StyleAttributeAccessor(scheduler, flags, obj as HTMLElement); case 'model': - return new SetterObserver(lifecycle, flags, obj as Node & IIndexable, propertyName); + return new SetterObserver(flags, obj as Node & IIndexable, propertyName); case 'role': return new DataAttributeAccessor(scheduler, flags, obj as HTMLElement, propertyName); default: diff --git a/packages/runtime/src/observation/binding-context.ts b/packages/runtime/src/observation/binding-context.ts index 601d8e00b9..639b5a2356 100644 --- a/packages/runtime/src/observation/binding-context.ts +++ b/packages/runtime/src/observation/binding-context.ts @@ -21,7 +21,11 @@ const enum RuntimeError { const marker = Object.freeze({}); /** @internal */ -export class InternalObserversLookup { +export class InternalObserversLookup implements ObserversLookup { + [x: string]: PropertyObserver; + [y: number]: PropertyObserver; + + // @ts-expect-error public getOrCreate( this: { [key: string]: PropertyObserver }, lifecycle: ILifecycle, @@ -30,7 +34,7 @@ export class InternalObserversLookup { key: string, ): PropertyObserver { if (this[key] === void 0) { - this[key] = new SetterObserver(lifecycle, flags, obj, key); + this[key] = new SetterObserver(flags, obj, key); } return this[key]; } diff --git a/packages/runtime/src/observation/observer-locator.ts b/packages/runtime/src/observation/observer-locator.ts index b561376956..2407b25b42 100644 --- a/packages/runtime/src/observation/observer-locator.ts +++ b/packages/runtime/src/observation/observer-locator.ts @@ -248,7 +248,7 @@ export class ObserverLocator implements IObserverLocator { return createComputedObserver(flags, this, this.dirtyChecker, this.lifecycle, obj, propertyName, descriptor); } - return new SetterObserver(this.lifecycle, flags, obj, propertyName); + return new SetterObserver(flags, obj, propertyName); } } diff --git a/packages/runtime/src/observation/setter-observer.ts b/packages/runtime/src/observation/setter-observer.ts index 04856a4785..2aaf2e4c65 100644 --- a/packages/runtime/src/observation/setter-observer.ts +++ b/packages/runtime/src/observation/setter-observer.ts @@ -22,7 +22,6 @@ export class SetterObserver { public type: AccessorType = AccessorType.Obj; public constructor( - public readonly lifecycle: ILifecycle, flags: LifecycleFlags, public readonly obj: IIndexable, public readonly propertyKey: string, @@ -59,6 +58,14 @@ export class SetterObserver { } public subscribe(subscriber: ISubscriber): void { + if (this.observing === false) { + this.start(); + } + + this.addSubscriber(subscriber); + } + + public start(): this { if (this.observing === false) { this.observing = true; this.currentValue = this.obj[this.propertyKey]; @@ -81,7 +88,20 @@ export class SetterObserver { Reporter.write(1, this.propertyKey, this.obj); } } + return this; + } - this.addSubscriber(subscriber); + public stop(): this { + if (this.observing) { + Reflect.defineProperty(this.obj, this.propertyKey, { + enumerable: true, + configurable: true, + writable: true, + value: this.currentValue, + }); + this.observing = false; + // todo(bigopon/fred): add .removeAllSubscribers() + } + return this; } }