diff --git a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js index 2b072a6f2221329808dfebcfb5bdfe061423b7fc..8e690a7ddf6070270c8d06e4ede86290ce4a75eb 100644 --- a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js +++ b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js @@ -362,7 +362,9 @@ var p = this.storage_.get(propName); p.aboutToBeDeleted(); } - + this.storage_.clear(); + + return true; } /** * Subscribe to value change notifications of named property @@ -1176,6 +1178,7 @@ class PersistentStorage { */ static ConfigureBackend(storage) { PersistentStorage.Storage_ = storage; + } /** * private, use static functions! @@ -1337,6 +1340,13 @@ class PersistentStorage { this.write(); } + syncPeerHasChanged(eventSource) { + + this.write(); + } + propertyHasBeenReadPU(eventSource) { + // not needed + } // public required by the interface, use the static method instead! aboutToBeDeleted() { @@ -1438,6 +1448,7 @@ class Environment { prop = AppStorage.SetAndProp(key, tmp); this.props_.set(key, prop); + return true; } envProps(properties) { properties.forEach(property => { @@ -1702,20 +1713,17 @@ class DistributedStorage { * obsObj = ObservedObject.createNew([]) */ const Observed = function () { - let object_creation_ongoing__ = 0; return function Observed(target) { + const IS_PROXIED = Symbol('___is_proxied___'); const Observed = class extends target { constructor(...args) { - object_creation_ongoing__ += 1; super(...args); - object_creation_ongoing__ -= 1; - if (object_creation_ongoing__ == 0) { - return ObservedObject.createNew(this, null); - } - else { - return this; - } + let isProxied = this.IS_PROXIED; + Object.defineProperty(this, IS_PROXIED, { value: true }); + return isProxied + ? this + : ObservedObject.createNew(this, null); } }; return Observed; @@ -1846,13 +1854,21 @@ class SubscribableArrayHandler extends SubscribableHandler { */ get(target, property) { let ret = super.get(target, property); - if (this.arrFunctions.includes(property.toString()) && - typeof ret === "function" && target["length"] > 0) { + const prop = property.toString(); + if (this.arrFunctions.includes(prop) && typeof ret === "function" && + Reflect.get(target, "length") > 0) { const self = this; return function () { + if (!this || !ret) { + // Something has gone really wrong! + return; + } // execute original function with given arguments - ret.apply(this, arguments); - self.notifyObjectPropertyHasChanged(property.toString(), this[0]); + const val = ret.apply(this, arguments); + if (self) { + self.notifyObjectPropertyHasChanged(prop, this); + } + return val; }.bind(target); // bind "this" to target inside the function } return ret; @@ -1972,39 +1988,62 @@ class ObservedObject extends ExtendableProxy { * this rule applies for each individual object or array found in the recursive process * subscriber info will not be copied from the source object to its copy. * @param obj object, array of simple type data item to be deep copied + * @param variable Variable name of the object to be copied * @returns deep copied object, optionally wrapped inside an ObservedObject */ - static GetDeepCopyOfObject(obj) { - - if (obj === null || typeof obj !== 'object') { + static GetDeepCopyOfObject(obj, variable) { + if (!obj || typeof obj !== 'object') { return obj; } - let copy = Array.isArray(obj) ? [] : !obj.constructor ? {} : new obj.constructor(); - Object.setPrototypeOf(copy, Object.getPrototypeOf(obj)); - if (obj instanceof Set) { - for (let setKey of obj.keys()) { - copy.add(ObservedObject.GetDeepCopyOfObject(setKey)); + let stack = new Array(); + let copiedObjects = new Map(); + return GetDeepCopyOfObjectRecursive(obj); + function GetDeepCopyOfObjectRecursive(obj) { + if (!obj || typeof obj !== 'object') { + return obj; } - } - else if (obj instanceof Map) { - for (let mapKey of obj.keys()) { - copy.set(mapKey, ObservedObject.GetDeepCopyOfObject(obj.get(mapKey))); + const alreadyCopiedObject = copiedObjects.get(obj); + if (alreadyCopiedObject) { + let msg = `@Prop DeepCopyObject: Found reference to already copied object: Path ${variable ? variable : 'unknown variable'}`; + stack.forEach(stackItem => msg += ` - ${stackItem.name}`); + stateMgmtConsole.warn(msg); + return alreadyCopiedObject; } - } - else if (obj instanceof Object) { - for (let objKey of Object.keys(obj)) { - copy[objKey] = ObservedObject.GetDeepCopyOfObject(obj[objKey]); + let copy; + if (obj instanceof Set) { + copy = new Set(); + for (const setKey of obj.keys()) { + stack.push({ name: setKey }); + copiedObjects.set(obj, copy); + copy.add(GetDeepCopyOfObjectRecursive(setKey)); + stack.pop(); + } } - } - else if (obj instanceof Date) { - copy.setTime(obj.getTime()); - } - for (let key in obj) { - if (obj.hasOwnProperty(key)) { - copy[key] = ObservedObject.GetDeepCopyOfObject(obj[key]); + else if (obj instanceof Map) { + copy = new Map(); + for (const mapKey of obj.keys()) { + stack.push({ name: mapKey }); + copiedObjects.set(obj, copy); + copy.set(mapKey, GetDeepCopyOfObjectRecursive(obj.get(mapKey))); + stack.pop(); + } + } + else if (obj instanceof Date) { + copy = new Date(); + copy.setTime(obj.getTime()); + } + else if (obj instanceof Object) { + copy = Array.isArray(obj) ? [] : {}; + Object.setPrototypeOf(copy, Object.getPrototypeOf(obj)); + for (const objKey of Object.keys(obj)) { + stack.push({ name: objKey }); + copiedObjects.set(obj, copy); + Reflect.set(copy, objKey, GetDeepCopyOfObjectRecursive(obj[objKey])); + stack.pop(); + } } + return ObservedObject.IsObservedObject(obj) ? ObservedObject.createNew(copy, null) : copy; } - return ObservedObject.IsObservedObject(obj) ? ObservedObject.createNew(copy, null) : copy; } /** * Create a new ObservableObject and subscribe its owner to propertyHasChanged @@ -2088,7 +2127,6 @@ class ObservedPropertyAbstract extends SubscribedAbstractProperty { this.subscribers_.delete(subscriberId); } notifyHasChanged(newValue) { - this.subscribers_.forEach((subscribedId) => { var subscriber = SubscriberManager.Find(subscribedId); if (subscriber) { @@ -2111,7 +2149,6 @@ class ObservedPropertyAbstract extends SubscribedAbstractProperty { }); } notifyPropertyRead() { - this.subscribers_.forEach((subscribedId) => { var subscriber = SubscriberManager.Find(subscribedId); if (subscriber) { @@ -2302,7 +2339,6 @@ class ObservedPropertyObject extends ObservedPropertyObjectAbstract { return true; } get() { - this.notifyPropertyRead(); return this.wrappedValue_; } @@ -2974,11 +3010,10 @@ class ObservedPropertyAbstractPU extends ObservedPropertyAbstract { this.dependentElementIds_ = new Set(); } notifyPropertyRead() { - stateMgmtConsole.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: \ + stateMgmtConsole.error(`ObservedPropertyAbstractPU[${this.id__()}, '${this.info() || "unknown"}']: \ notifyPropertyRead, DO NOT USE with PU. Use notifyPropertryHasBeenReadPU`); } notifyPropertryHasBeenReadPU() { - this.subscribers_.forEach((subscribedId) => { var subscriber = SubscriberManager.Find(subscribedId); if (subscriber) { @@ -2990,7 +3025,6 @@ class ObservedPropertyAbstractPU extends ObservedPropertyAbstract { this.recordDependentUpdate(); } notifyPropertryHasChangedPU() { - this.subscribers_.forEach((subscribedId) => { var subscriber = SubscriberManager.Find(subscribedId); if (subscriber) { @@ -3201,7 +3235,7 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectAbstractPU { */ setValueInternal(newValue) { if (typeof newValue !== 'object') { - stateMgmtConsole.error(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`); + stateMgmtConsole.error(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`); return false; } if (newValue == this.wrappedValue_) { @@ -3231,8 +3265,7 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectAbstractPU { return this.wrappedValue_; } getUnmonitored() { - - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } set(newValue) { @@ -3310,7 +3343,7 @@ class ObservedPropertySimplePU extends ObservedPropertySimpleAbstractPU { } getUnmonitored() { - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } get() { @@ -3491,7 +3524,7 @@ class SynchedPropertyObjectOneWayPU extends ObservedPropertyObjectAbstractPU { this.source_.set(sourceChangedValue); } else { - stateMgmtConsole.error(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset from '${JSON.stringify(this.localCopyObservedObject)}' to '${JSON.stringify(sourceChangedValue)}' No source_. Internal error!`); + stateMgmtConsole.error(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset --- No source_. Internal error!`); } } /* @@ -3508,7 +3541,7 @@ class SynchedPropertyObjectOneWayPU extends ObservedPropertyObjectAbstractPU { stateMgmtConsole.error(`SynchedPropertyOneWayObjectPU[${this.id__()}]: setLocalValue new value must be an Object. Not setting.`); return false; } - // unsubscribe from old wappedValue ObservedOject + // unsubscribe from old wrappedValue ObservedOject ObservedObject.removeOwningProperty(this.localCopyObservedObject, this); if (newObservedObjectValue == undefined) { // case: newObservedObjectValue undefined @@ -3518,7 +3551,7 @@ class SynchedPropertyObjectOneWayPU extends ObservedPropertyObjectAbstractPU { // deep copy value // needed whenever newObservedObjectValue comes from source // not needed on a local set (aka when called from set() method) - let copy = needDeepCopy ? ObservedObject.GetDeepCopyOfObject(newObservedObjectValue) : newObservedObjectValue; + let copy = needDeepCopy ? ObservedObject.GetDeepCopyOfObject(newObservedObjectValue, this.info_) : newObservedObjectValue; if (ObservedObject.IsObservedObject(copy)) { // case: new ObservedObject this.localCopyObservedObject = copy; @@ -3603,13 +3636,11 @@ class SynchedPropertyObjectTwoWayPU extends ObservedPropertyObjectAbstractPU { this.notifyPropertryHasChangedPU(); } getUnmonitored() { - - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return (this.source_ ? this.source_.getUnmonitored() : undefined); } // get 'read through` from the ObservedProperty get() { - this.notifyPropertryHasBeenReadPU(); return this.getUnmonitored(); } @@ -3707,7 +3738,7 @@ class SynchedPropertySimpleOneWayPU extends ObservedPropertySimpleAbstractPU { } getUnmonitored() { - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } // get 'read through` from the ObservedProperty @@ -3875,8 +3906,7 @@ class SynchedPropertyNesedObjectPU extends ObservedPropertyObjectAbstractPU { this.notifyPropertryHasChangedPU(); } getUnmonitored() { - // - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.obsObject_; } // get 'read through` from the ObservedProperty diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_object.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_object.ts index a0f39441d7c220b405d23f3344441c03994d2013..90f58b6d4af39bb3372f8d51bc57ea7db43dd3fa 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_object.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_object.ts @@ -43,23 +43,21 @@ interface Type extends Function { * obsObj = ObservedObject.createNew([]) */ const Observed: (obj) => any = function () { - let object_creation_ongoing__ = 0; - return function Observed(target: any): any { - stateMgmtConsole.debug(`@Observed: define ${target.name} extended`); - const Observed = class extends target { - constructor(...args) { - object_creation_ongoing__ += 1; - super(...args); - object_creation_ongoing__ -= 1; - if (object_creation_ongoing__ == 0) { - return ObservedObject.createNew(this, null); - } else { - return this; + return function Observed(target: any): any { + const IS_PROXIED = Symbol('___is_proxied___'); + stateMgmtConsole.debug(`@Observed: define ${target.name} extended`); + const Observed = class extends target { + constructor(...args) { + super(...args); + let isProxied = this.IS_PROXIED; + Object.defineProperty(this, IS_PROXIED, {value: true}); + return isProxied + ? this + : ObservedObject.createNew(this, null); } - } - }; - return Observed; - } + }; + return Observed; + } }() @@ -198,29 +196,37 @@ class SubscribableArrayHandler extends SubscribableHandler { * @param property * @returns */ + public get(target: Object, property: PropertyKey): any { let ret = super.get(target, property); - if (this.arrFunctions.includes(property.toString()) && - typeof ret === "function" && target["length"] > 0) { - const self = this; - return function() { - // execute original function with given arguments - ret.apply(this, arguments); - self.notifyObjectPropertyHasChanged(property.toString(), this[0]); + const prop = property.toString(); + if (this.arrFunctions.includes(prop) && typeof ret === "function" && + Reflect.get(target, "length") > 0) { + const self = this; + return function () { + if (!this || !ret) { + // Something has gone really wrong! + return; + } + // execute original function with given arguments + const val = ret.apply(this, arguments); + if (self) { + self.notifyObjectPropertyHasChanged(prop, this); + } + return val; }.bind(target) // bind "this" to target inside the function } - + return ret; } } - class SubscribableDateHandler extends SubscribableHandler { constructor(owningProperty: IPropertySubscriber) { super(owningProperty); } - + /** * Get trap for Date type proxy * Functions that modify Date in-place are intercepted and replaced with a function @@ -246,7 +252,6 @@ class SubscribableDateHandler extends SubscribableHandler { } } - class ExtendableProxy { constructor(obj: Object, handler: SubscribableHandler) { return new Proxy(obj, handler); @@ -344,40 +349,65 @@ class ObservedObject extends ExtendableProxy { * this rule applies for each individual object or array found in the recursive process * subscriber info will not be copied from the source object to its copy. * @param obj object, array of simple type data item to be deep copied + * @param variable Variable name of the object to be copied * @returns deep copied object, optionally wrapped inside an ObservedObject */ - public static GetDeepCopyOfObject(obj: any): any { - stateMgmtConsole.debug(`GetDeepCopyOfObject obj ${JSON.stringify(obj)}`); - if (obj === null || typeof obj !== 'object') { + public static GetDeepCopyOfObject(obj: any, variable?: string): any { + if (!obj || typeof obj !== 'object') { + return obj; + } + + let stack = new Array<{ name: string}>(); + let copiedObjects = new Map(); + + return GetDeepCopyOfObjectRecursive(obj); + + function GetDeepCopyOfObjectRecursive(obj: any): any { + if (!obj || typeof obj !== 'object') { return obj; - } + } - let copy = Array.isArray(obj) ? [] : !obj.constructor ? {} : new obj.constructor(); - Object.setPrototypeOf(copy, Object.getPrototypeOf(obj)); + const alreadyCopiedObject = copiedObjects.get(obj); + if (alreadyCopiedObject) { + let msg = `@Prop DeepCopyObject: Found reference to already copied object: Path ${variable ? variable : 'unknown variable'}`; + stack.forEach(stackItem => msg += ` - ${stackItem.name}`) + stateMgmtConsole.warn(msg); + return alreadyCopiedObject; + } + let copy; if (obj instanceof Set) { - for (let setKey of obj.keys()) { - copy.add(ObservedObject.GetDeepCopyOfObject(setKey)); + copy = new Set(); + for (const setKey of obj.keys()) { + stack.push({ name: setKey }); + copiedObjects.set(obj, copy); + copy.add(GetDeepCopyOfObjectRecursive(setKey)); + stack.pop(); } } else if (obj instanceof Map) { - for (let mapKey of obj.keys()) { - copy.set(mapKey, ObservedObject.GetDeepCopyOfObject(obj.get(mapKey))); - } - } else if (obj instanceof Object) { - for (let objKey of Object.keys(obj)) { - copy[objKey] = ObservedObject.GetDeepCopyOfObject(obj[objKey]); + copy = new Map(); + for (const mapKey of obj.keys()) { + stack.push({ name: mapKey }); + copiedObjects.set(obj, copy); + copy.set(mapKey, GetDeepCopyOfObjectRecursive(obj.get(mapKey))); + stack.pop(); } } else if (obj instanceof Date) { + copy = new Date() copy.setTime(obj.getTime()); - } - - for (let key in obj) { - if (obj.hasOwnProperty(key)) { - copy[key] = ObservedObject.GetDeepCopyOfObject(obj[key]); + } else if (obj instanceof Object) { + copy = Array.isArray(obj) ? [] : {}; + Object.setPrototypeOf(copy, Object.getPrototypeOf(obj)); + for (const objKey of Object.keys(obj)) { + stack.push({ name: objKey }); + copiedObjects.set(obj, copy); + Reflect.set(copy, objKey, GetDeepCopyOfObjectRecursive(obj[objKey])); + stack.pop(); } } return ObservedObject.IsObservedObject(obj) ? ObservedObject.createNew(copy, null) : copy; } + } /** * Create a new ObservableObject and subscribe its owner to propertyHasChanged diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_property_abstract.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_property_abstract.ts index 084ea33622ba796cf64d2b7c97733f1310582277..3e534d2d5d249c3c1576c2c8b5fc18ef9bf24dd2 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_property_abstract.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/observed_property_abstract.ts @@ -91,7 +91,6 @@ abstract class ObservedPropertyAbstract extends SubscribedAbstractProperty } protected notifyHasChanged(newValue: T) { - stateMgmtConsole.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged, notifying.`); this.subscribers_.forEach((subscribedId) => { var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId) if (subscriber) { @@ -115,7 +114,6 @@ abstract class ObservedPropertyAbstract extends SubscribedAbstractProperty } protected notifyPropertyRead() { - stateMgmtConsole.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: propertyRead.`) this.subscribers_.forEach((subscribedId) => { var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId) if (subscriber) { diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/full_update/fu_observed_property_object.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/full_update/fu_observed_property_object.ts index 302662212c26c5613ed8ba2308ad7932c024ce76..8bdab969a26559372ba23b2d7f5bc96603a5ae34 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/full_update/fu_observed_property_object.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/full_update/fu_observed_property_object.ts @@ -89,7 +89,6 @@ class ObservedPropertyObject extends ObservedPropertyObjectAbs } public get(): T { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: get`); this.notifyPropertyRead(); return this.wrappedValue_; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts index 11368e09866de626920fabfaed91e68cfd68c752..057f393a5e256975d46302957027a4e23fd3f395 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts @@ -29,12 +29,11 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract } protected notifyPropertyRead() { - stateMgmtConsole.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: \ + stateMgmtConsole.error(`ObservedPropertyAbstractPU[${this.id__()}, '${this.info() || "unknown"}']: \ notifyPropertyRead, DO NOT USE with PU. Use notifyPropertryHasBeenReadPU`); } protected notifyPropertryHasBeenReadPU() { - stateMgmtConsole.debug(`ObservedPropertyAbstractPU[${this.id__()}, '${this.info() || "unknown"}']: propertyHasBeenReadPU.`) this.subscribers_.forEach((subscribedId) => { var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId) if (subscriber) { @@ -47,7 +46,6 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract } protected notifyPropertryHasChangedPU() { - stateMgmtConsole.debug(`ObservedPropertyAbstractPU[${this.id__()}, '${this.info() || "unknown"}']: notifyPropertryHasChangedPU.`) this.subscribers_.forEach((subscribedId) => { var subscriber: IPropertySubscriber = SubscriberManager.Find(subscribedId) if (subscriber) { diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_object.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_object.ts index ba78afdba09e5e0a5e0e48fd7bf6285159225ff0..e6ecd0b6b53369a21b040cba65e87cb31aa768bf 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_object.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_object.ts @@ -50,7 +50,7 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectA * @param eventSource */ syncPeerHasChanged(eventSource : ObservedPropertyAbstractPU) { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: syncPeerHasChanged peer '${eventSource.info()}'.`); + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}']: syncPeerHasChanged peer '${eventSource.info()}'.`); this.notifyPropertryHasChangedPU(); } @@ -60,7 +60,7 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectA * @param changedPropertyName */ public objectPropertyHasChangedPU(souceObject: ObservedObject, changedPropertyName : string) { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: \ + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}']: \ objectPropertyHasChangedPU: contained ObservedObject property '${changedPropertyName}' has changed.`) this.notifyPropertryHasChangedPU(); } @@ -82,27 +82,27 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectA */ private setValueInternal(newValue: T): boolean { if (typeof newValue !== 'object') { - stateMgmtConsole.error(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`); + stateMgmtConsole.error(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] new value is NOT an object. Application error. Ignoring set.`); return false; } if (newValue == this.wrappedValue_){ - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] newValue unchanged`); + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] newValue unchanged`); return false; } this.unsubscribeWrappedObject(); if (ObservedObject.IsObservedObject(newValue)) { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an ObservedObject already`); + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] new value is an ObservedObject already`); ObservedObject.addOwningProperty(newValue, this); this.wrappedValue_ = newValue; } else if (newValue instanceof SubscribableAbstract) { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an SubscribaleAbstract, subscribiung to it.`); + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] new value is an SubscribaleAbstract, subscribiung to it.`); this.wrappedValue_ = newValue; (this.wrappedValue_ as unknown as SubscribableAbstract).addOwningProperty(this); } else { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}'] new value is an Object, needs to be wrapped in an ObservedObject.`); + stateMgmtConsole.debug(`ObservedPropertyObjectPU[${this.id__()}, '${this.info() || "unknown"}'] new value is an Object, needs to be wrapped in an ObservedObject.`); this.wrappedValue_ = ObservedObject.createNew(newValue, this); } return true; @@ -115,8 +115,7 @@ class ObservedPropertyObjectPU extends ObservedPropertyObjectA } public getUnmonitored(): T { - stateMgmtConsole.debug(`ObservedPropertyObject[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`); - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_simple.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_simple.ts index a32d369de4884c53b85f5976891cec81963067bc..7e899d6cf51a4f8c4937de0419ceabb529879215 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_simple.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_simple.ts @@ -70,7 +70,7 @@ class ObservedPropertySimplePU extends ObservedPropertySimpleAbstractPU { public getUnmonitored(): T { stateMgmtConsole.debug(`ObservedPropertySimple[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`); - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_nested.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_nested.ts index 5389422b210bd961fcba1294cee293b86744d801..b6e2de659221381f59d30f0302a12abfd123a60e 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_nested.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_nested.ts @@ -66,8 +66,7 @@ class SynchedPropertyNesedObjectPU } public getUnmonitored(): C { - // stateMgmtConsole.debug(`SynchedPropertyNesedObject[${this.id()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`); - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.obsObject_; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_one_way.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_one_way.ts index 21b9f45b94c9a815f36614ecb19f427580236e99..6da66888f023c6147ba2f2d7073559650be9cfec 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_one_way.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_one_way.ts @@ -93,7 +93,7 @@ class SynchedPropertyObjectOneWayPU } this.resetLocalValue(this.source_.get(), /* needDeepCopy */ true); - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: constructor ready with localCopyObservedObject '${JSON.stringify(this.localCopyObservedObject)}'.`); + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: constructor ready with local copy.`); } /* @@ -148,15 +148,16 @@ class SynchedPropertyObjectOneWayPU } public getUnmonitored(): C { - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.localCopyObservedObject)}'.`); + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored.`); // unmonitored get access , no call to notifyPropertyRead ! return this.localCopyObservedObject; } // get 'read through` from the ObservedObject public get(): C { - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: get returning ${JSON.stringify(this.localCopyObservedObject)}.`) - this.notifyPropertryHasBeenReadPU() + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: get.`); + + this.notifyPropertryHasBeenReadPU(); return this.localCopyObservedObject; } @@ -164,11 +165,11 @@ class SynchedPropertyObjectOneWayPU // set 'writes through` to the ObservedObject public set(newValue: C): void { if (this.localCopyObservedObject == newValue) { - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value '${JSON.stringify(newValue)}'- ignoring.`); + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value - ignoring.`); return; } - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: set to newValue: '${JSON.stringify(newValue)}'.`); + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: set to newValue.`); if (this.resetLocalValue(newValue, /* needDeepCopy */ false)) { this.notifyPropertryHasChangedPU(); @@ -177,12 +178,12 @@ class SynchedPropertyObjectOneWayPU public reset(sourceChangedValue: C): void { - stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset from '${JSON.stringify(this.localCopyObservedObject)}' to '${JSON.stringify(sourceChangedValue)}'.`); + stateMgmtConsole.debug(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset.`); if (this.source_ !== undefined) { // if set causes an actual change, then, ObservedPropertyObject source_ will call syncPeerHasChanged this.source_.set(sourceChangedValue); } else { - stateMgmtConsole.error(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset from '${JSON.stringify(this.localCopyObservedObject)}' to '${JSON.stringify(sourceChangedValue)}' No source_. Internal error!`); + stateMgmtConsole.error(`SynchedPropertyObjectOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: reset --- No source_. Internal error!`); } } @@ -202,7 +203,7 @@ class SynchedPropertyObjectOneWayPU return false; } - // unsubscribe from old wappedValue ObservedOject + // unsubscribe from old wrappedValue ObservedOject ObservedObject.removeOwningProperty(this.localCopyObservedObject, this); @@ -215,7 +216,7 @@ class SynchedPropertyObjectOneWayPU // deep copy value // needed whenever newObservedObjectValue comes from source // not needed on a local set (aka when called from set() method) - let copy = needDeepCopy ? ObservedObject.GetDeepCopyOfObject(newObservedObjectValue) : newObservedObjectValue; + let copy = needDeepCopy ? ObservedObject.GetDeepCopyOfObject(newObservedObjectValue, this.info_) : newObservedObjectValue; if (ObservedObject.IsObservedObject(copy)) { // case: new ObservedObject diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_two_way.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_two_way.ts index f130214bf08fb24e3b5f891e236ab20bb4077bc9..4010f62cdac34fb919ff7ccb3542ec329ad717ea 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_two_way.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_object_two_way.ts @@ -82,14 +82,12 @@ class SynchedPropertyObjectTwoWayPU public getUnmonitored(): C { - stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${(this.source_ ? JSON.stringify(this.source_.getUnmonitored()) : "undefined")}' .`); - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return (this.source_ ? this.source_.getUnmonitored() : undefined); } // get 'read through` from the ObservedProperty public get(): C { - stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: get`) this.notifyPropertryHasBeenReadPU() return this.getUnmonitored(); } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_simple_one_way.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_simple_one_way.ts index 1c8e4f7ea93a380ecb3e3f2b9c09a7ec5076b5ae..8613ea268fe827fd26ad6ebc93f74fe64b2eab2a 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_simple_one_way.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_synced_property_simple_one_way.ts @@ -78,7 +78,7 @@ class SynchedPropertySimpleOneWayPU extends ObservedPropertySimpleAbstractPU< public getUnmonitored(): T { stateMgmtConsole.debug(`SynchedPropertySimpleOneWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${JSON.stringify(this.wrappedValue_)}' .`); - // unmonitored get access , no call to otifyPropertyRead ! + // unmonitored get access , no call to notifyPropertryHasBeenReadPU ! return this.wrappedValue_; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/environment.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/environment.ts index 84e56b0e39dea31f75c490b77373c4f38f0ad4ea..fb15d77fc6f5f886951d2092fa4d0f6ecac211e1 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/environment.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/environment.ts @@ -102,6 +102,7 @@ class Environment { prop = AppStorage.SetAndProp(key, tmp); this.props_.set(key, prop); stateMgmtConsole.debug(`Environment: envProp for '${key}' done.`); + return true; } private envProps(properties: { diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/local_storage.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/local_storage.ts index 7a1dcaaab970f3d191ec0491f52e1b5446a3ffde..c8f02c976f79188ba9bff67a94fe3ca225bc8ff2 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/local_storage.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/local_storage.ts @@ -349,6 +349,7 @@ class LocalStorage extends NativeLocalStorage { var p: ObservedPropertyAbstract = this.storage_.get(propName); p.aboutToBeDeleted(); } + this.storage_.clear(); stateMgmtConsole.debug(`${this.constructor.name}.deleteAll: success`); } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/persistent_storage.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/persistent_storage.ts index ac7e903c722a239a214b9eeb42044da155ea1301..d346c0f3c1787bfae97b562136ed57f442da6805 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/persistent_storage.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/sdk/persistent_storage.ts @@ -21,7 +21,8 @@ * since 9 */ -class PersistentStorage implements IMultiPropertiesChangeSubscriber { +class PersistentStorage implements IMultiPropertiesChangeSubscriber, + PropertyEventsReceiverPU { private static Storage_: IStorage; private static Instance_: PersistentStorage = undefined; @@ -38,6 +39,7 @@ class PersistentStorage implements IMultiPropertiesChangeSubscriber { */ public static ConfigureBackend(storage: IStorage): void { PersistentStorage.Storage_ = storage; + stateMgmtConsole.debug(`PersistentStorage backend configured`); } /** @@ -237,6 +239,15 @@ class PersistentStorage implements IMultiPropertiesChangeSubscriber { this.write(); } + public syncPeerHasChanged(eventSource: ObservedPropertyAbstractPU) { + stateMgmtConsole.debug(`PersistentStorage: sync peer ${eventSource.info()} has changed`); + this.write(); + } + + public propertyHasBeenReadPU(eventSource: ObservedPropertyAbstractPU) { + // not needed + } + // public required by the interface, use the static method instead! public aboutToBeDeleted(): void { stateMgmtConsole.debug("PersistentStorage: about to be deleted");