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;
}
}