• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 * Copyright (c) 2021 Huawei Device Co., Ltd.
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 */
29/*
30 * Copyright (c) 2021 Huawei Device Co., Ltd.
31 * Licensed under the Apache License, Version 2.0 (the "License");
32 * you may not use this file except in compliance with the License.
33 * You may obtain a copy of the License at
34 *
35 *     http://www.apache.org/licenses/LICENSE-2.0
36 *
37 * Unless required by applicable law or agreed to in writing, software
38 * distributed under the License is distributed on an "AS IS" BASIS,
39 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
40 * See the License for the specific language governing permissions and
41 * limitations under the License.
42 */
43/*
44 * Copyright (c) 2021 Huawei Device Co., Ltd.
45 * Licensed under the Apache License, Version 2.0 (the "License");
46 * you may not use this file except in compliance with the License.
47 * You may obtain a copy of the License at
48 *
49 *     http://www.apache.org/licenses/LICENSE-2.0
50 *
51 * Unless required by applicable law or agreed to in writing, software
52 * distributed under the License is distributed on an "AS IS" BASIS,
53 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
54 * See the License for the specific language governing permissions and
55 * limitations under the License.
56 */
57/**
58 *
59 * LocalStorage
60 *
61 * Class implements a Map of ObservableObjectBase UI state variables.
62 * Instances can be created to manage UI state within a limited "local"
63 * access, and life cycle as defined by the app.
64 * AppStorage singleton is sub-class of LocalStorage for
65 * UI state of app-wide access and same life cycle as the app.
66 *
67 * @since 9
68 */
69 class LocalStorage extends NativeLocalStorage {
70    /**
71     * Construct new instance of LocalStorage
72     * initialzie with all properties and their values that Object.keys(params) returns
73     * Property values must not be undefined.
74     * @param initializingProperties Object containing keys and values. @see set() for valid values
75     *
76     * @since 9
77     */
78    constructor(initializingProperties = {}) {
79        super();
80
81        this.storage_ = new Map();
82        if (Object.keys(initializingProperties).length) {
83            this.initializeProps(initializingProperties);
84        }
85    }
86    /**
87     * clear storage and init with given properties
88     * @param initializingProperties
89     *
90     * not a public / sdk function
91     */
92    initializeProps(initializingProperties = {}) {
93
94        this.storage_.clear();
95        Object.keys(initializingProperties).filter((propName) => initializingProperties[propName] != undefined).forEach((propName) => this.addNewPropertyInternal(propName, initializingProperties[propName]));
96    }
97    /**
98     * Use before deleting owning Ability, window, or service UI
99     * (letting it go out of scope).
100     *
101     * This method orderly closes down a LocalStorage instance by calling @see clear().
102     * This requires that no property is left with one or more subscribers.
103     * @see clear() and @see delete()
104     * @returns true if all properties could be removed from storage
105     */
106    aboutToBeDeleted() {
107        return this.clear();
108    }
109    /**
110     * Check if LocalStorage has a property with given name
111     * return true if prooperty with given name exists
112     * same as ES6 Map.prototype.has()
113     * @param propName searched property
114     * @returns true if property with such name exists in LocalStorage
115     *
116     * @since 9
117     */
118    has(propName) {
119        return this.storage_.has(propName);
120    }
121    /**
122     * Provide names of all properties in LocalStorage
123     * same as ES6 Map.prototype.keys()
124     * @returns return a Map Iterator
125     *
126     * @since 9
127    */
128    keys() {
129        return this.storage_.keys();
130    }
131    /**
132     * Returns number of properties in LocalStorage
133     * same as Map.prototype.size()
134     * @param propName
135     * @returns return number of properties
136     *
137     * @since 9
138     */
139    size() {
140        return this.storage_.size;
141    }
142    /**
143     * Returns value of given property
144     * return undefined if no property with this name
145     * @param propName
146     * @returns property value if found or undefined
147     *
148     * @since 9
149     */
150    get(propName) {
151        var p = this.storage_.get(propName);
152        return (p) ? p.get() : undefined;
153    }
154    /**
155     * Set value of given property in LocalStorage
156     * Methosd sets nothing and returns false if property with this name does not exist
157     * or if newValue is `undefined` or `null` (`undefined`, `null` value are not allowed for state variables).
158     * @param propName
159     * @param newValue must be of type T and must not be undefined or null
160     * @returns true on success, i.e. when above conditions are satisfied, otherwise false
161     *
162     * @since 9
163     */
164    set(propName, newValue) {
165        if (newValue == undefined) {
166            stateMgmtConsole.warn(`${this.constructor.name}: set('${propName}') with newValue == undefined not allowed.`);
167            return false;
168        }
169        var p = this.storage_.get(propName);
170        if (p == undefined) {
171            stateMgmtConsole.warn(`${this.constructor.name}: set: no property ${propName} error.`);
172            return false;
173        }
174        p.set(newValue);
175        return true;
176    }
177    /**
178     * Set value of given property, if it exists, @see set() .
179     * Add property if no property with given name and initialize with given value.
180     * Do nothing and return false if newValuue is undefined or null
181     * (undefined, null value is not allowed for state variables)
182     * @param propName
183     * @param newValue must be of type T and must not be undefined or null
184     * @returns true on success, i.e. when above conditions are satisfied, otherwise false
185     *
186     * @since 9
187     */
188    setOrCreate(propName, newValue) {
189        if (newValue == undefined) {
190            stateMgmtConsole.warn(`${this.constructor.name}: setOrCreate('${propName}') with newValue == undefined not allowed.`);
191            return false;
192        }
193        var p = this.storage_.get(propName);
194        if (p) {
195
196            p.set(newValue);
197        }
198        else {
199
200            this.addNewPropertyInternal(propName, newValue);
201        }
202        return true;
203    }
204    /**
205     * Internal use helper function to create and initialize a new property.
206     * caller needs to be all the checking beforehand
207     * @param propName
208     * @param value
209     *
210     * Not a public / sdk method.
211     */
212    addNewPropertyInternal(propName, value) {
213        const newProp = (typeof value === "object") ?
214            new ObservedPropertyObject(value, undefined, propName)
215            : new ObservedPropertySimple(value, undefined, propName);
216        this.storage_.set(propName, newProp);
217        return newProp;
218    }
219    /**
220     * create and return a two-way sync "(link") to named property
221     * @param propName name of source property in LocalStorage
222     * @param linkUser IPropertySubscriber to be notified when source changes,
223     * @param subscribersName optional, the linkUser (subscriber) uses this name for the property
224     *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
225     * @returns  SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as its source.
226     *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
227     *           return undefiend if named property does not already exist in LocalStorage
228     *           Apps can use SDK functions of base class SubscribedPropertyAbstract<S>
229     *           return undefiend if named property does not already exist in LocalStorage
230     *
231     * @since 9
232     */
233    link(propName, linkUser, subscribersName) {
234        var p = this.storage_.get(propName);
235        if (p == undefined) {
236            stateMgmtConsole.warn(`${this.constructor.name}: link: no property ${propName} error.`);
237            return undefined;
238        }
239        let linkResult = p.createLink(linkUser, propName);
240        linkResult.setInfo(subscribersName);
241        return linkResult;
242    }
243    /**
244     * Like @see link(), but will create and initialize a new source property in LocalStorge if missing
245     * @param propName name of source property in LocalStorage
246     * @param defaultValue value to be used for initializing if new creating new property in LocalStorage
247     *        default value must be of type S, must not be undefined or null.
248     * @param linkUser IPropertySubscriber to be notified when return 'link' changes,
249     * @param subscribersName the linkUser (subscriber) uses this name for the property
250     *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
251     * @returns SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as  its source.
252     *          Apps can use SDK functions of base class SubscribedAbstractProperty<S>
253     *
254     * @since 9
255     */
256    setAndLink(propName, defaultValue, linkUser, subscribersName) {
257        var p = this.storage_.get(propName);
258        if (!p) {
259            this.setOrCreate(propName, defaultValue);
260        }
261        return this.link(propName, linkUser, subscribersName);
262    }
263    /**
264     * create and return a one-way sync ('prop') to named property
265     * @param propName name of source property in LocalStorage
266     * @param propUser IPropertySubscriber to be notified when source changes,
267     * @param subscribersName the linkUser (subscriber) uses this name for the property
268     *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
269     * @returns  SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as  its source.
270     *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
271     *           return undefiend if named property does not already exist in LocalStorage.
272     *           Apps can use SDK functions of base class SubscribedPropertyAbstract<S>
273     *           return undefiend if named property does not already exist in LocalStorage.
274     * @since 9
275     */
276    prop(propName, propUser, subscribersName) {
277        var p = this.storage_.get(propName);
278        if (p == undefined) {
279            stateMgmtConsole.warn(`${this.constructor.name}: prop: no property ${propName} error.`);
280            return undefined;
281        }
282        let propResult = p.createProp(propUser, propName);
283        propResult.setInfo(subscribersName);
284        return propResult;
285    }
286    /**
287     * Like @see prop(), will create and initialize a new source property in LocalStorage if missing
288     * @param propName name of source property in LocalStorage
289     * @param defaultValue value to be used for initializing if new creating new property in LocalStorage.
290     *        default value must be of type S, must not be undefined or null.
291     * @param propUser IPropertySubscriber to be notified when returned 'prop' changes,
292     * @param subscribersName the propUser (subscriber) uses this name for the property
293     *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
294     * @returns  SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source.
295     *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
296     * @since 9
297     */
298    setAndProp(propName, defaultValue, propUser, subscribersName) {
299        var p = this.storage_.get(propName);
300        if (!p) {
301            this.setOrCreate(propName, defaultValue);
302        }
303        return this.prop(propName, propUser, subscribersName);
304    }
305    /**
306     * Delete property from StorageBase
307     * Use with caution:
308     * Before deleting a prop from LocalStorage all its subscribers need to
309     * unsubscribe from the property.
310     * This method fails and returns false if given property still has subscribers
311     * Another reason for failing is unkmown property.
312     *
313     * Developer advise:
314     * Subscribers are created with @see link(), @see prop()
315     * and also via @LocalStorageLink and @LocalStorageProp state variable decorators.
316     * That means as long as their is a @Component instance that uses such decorated variable
317     * or a sync relationship with a SubscribedAbstractProperty variable the property can nit
318     * (and also should not!) be deleted from LocalStorage.
319     *
320     * @param propName
321     * @returns false if method failed
322     *
323     * @since 9
324    */
325    delete(propName) {
326        var p = this.storage_.get(propName);
327        if (p) {
328            if (p.numberOfSubscrbers()) {
329                stateMgmtConsole.error(`${this.constructor.name}: Attempt to delete property ${propName} that has \
330          ${p.numberOfSubscrbers()} subscribers. Subscribers need to unsubscribe before prop deletion.`);
331                return false;
332            }
333            p.aboutToBeDeleted();
334            this.storage_.delete(propName);
335            return true;
336        }
337        else {
338            stateMgmtConsole.warn(`${this.constructor.name}: Attempt to delete unknown property ${propName}.`);
339            return false;
340        }
341    }
342    /**
343     * delete all properties from the LocalStorage instance
344     * @see delete().
345     * precondition is that there are no subscribers.
346     * method returns false and deletes no poperties if there is any property
347     * that still has subscribers
348     *
349     * @since 9
350     */
351    clear() {
352        for (let propName of this.keys()) {
353            var p = this.storage_.get(propName);
354            if (p.numberOfSubscrbers()) {
355                stateMgmtConsole.error(`${this.constructor.name}.deleteAll: Attempt to delete property ${propName} that \
356          has ${p.numberOfSubscrbers()} subscribers. Subscribers need to unsubscribe before prop deletion.
357          Any @Component instance with a @StorageLink/Prop or @LocalStorageLink/Prop is a subscriber.`);
358                return false;
359            }
360        }
361        for (let propName of this.keys()) {
362            var p = this.storage_.get(propName);
363            p.aboutToBeDeleted();
364        }
365        this.storage_.clear();
366        return true;
367    }
368    /**
369     * Subscribe to value change notifications of named property
370     * Any object implementing ISinglePropertyChangeSubscriber interface
371     * and registerign itself to SubscriberManager can register
372     * Caution: do remember to unregister, otherwise the property will block
373     * cleanup, @see delete() and @see clear()
374     *
375     * @param propName property in LocalStorage to subscribe to
376     * @param subscriber object that implements ISinglePropertyChangeSubscriber interface
377     * @returns false if named property does not exist
378     *
379     * @since 9
380     */
381    subscribeToChangesOf(propName, subscriber) {
382        var p = this.storage_.get(propName);
383        if (p) {
384            p.subscribeMe(subscriber);
385            return true;
386        }
387        return false;
388    }
389    /**
390     * inverse of @see subscribeToChangesOf
391     * @param propName property in LocalStorage to subscribe to
392     * @param subscriberId id of the subscrber passed to @see subscribeToChangesOf
393     * @returns false if named property does not exist
394     *
395     * @since 9
396     */
397    unsubscribeFromChangesOf(propName, subscriberId) {
398        var p = this.storage_.get(propName);
399        if (p) {
400            p.unlinkSuscriber(subscriberId);
401            return true;
402        }
403        return false;
404    }
405    /**
406     * return number of subscribers to named property
407     *  useful for debug purposes
408     *
409     * Not a public / sdk function
410    */
411    numberOfSubscrbersTo(propName) {
412        var p = this.storage_.get(propName);
413        if (p) {
414            return p.numberOfSubscrbers();
415        }
416        return undefined;
417    }
418    __createSync(storagePropName, defaultValue, factoryFunc) {
419        let p = this.storage_.get(storagePropName);
420        if (p == undefined) {
421            // property named 'storagePropName' not yet in storage
422            // add new property to storage
423            if (defaultValue === undefined) {
424                stateMgmtConsole.error(`${this.constructor.name}.__createSync(${storagePropName}, non-existing property and undefined default value. ERROR.`);
425                return undefined;
426            }
427            p = this.addNewPropertyInternal(storagePropName, defaultValue);
428        }
429        return factoryFunc(p);
430    }
431}
432/*
433 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
434 * Licensed under the Apache License, Version 2.0 (the "License");
435 * you may not use this file except in compliance with the License.
436 * You may obtain a copy of the License at
437 *
438 *     http://www.apache.org/licenses/LICENSE-2.0
439 *
440 * Unless required by applicable law or agreed to in writing, software
441 * distributed under the License is distributed on an "AS IS" BASIS,
442 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
443 * See the License for the specific language governing permissions and
444 * limitations under the License.
445 */
446/**
447 *
448 * AppStorage
449 *
450 * Class implements a Map of ObservableObjectBase UI state variables.
451 * AppStorage singleton is sub-class of @see LocalStorage for
452 * UI state of app-wide access and same life cycle as the app.
453 *
454 * @since 7
455 */
456class AppStorage extends LocalStorage {
457    /** singleton class, app can not create instances
458     *
459     * not a public / sdk function
460    */
461    constructor(initializingProperties) {
462        super(initializingProperties);
463    }
464    /**
465     * create and initialize singleton
466     * initialzie with all properties and their values that Object.keys(params) returns
467     * Property values must not be undefined.
468     *
469     * not a public / sdk function
470     */
471    static CreateSingleton(initializingPropersties) {
472        if (!AppStorage.Instance_) {
473
474            AppStorage.Instance_ = new AppStorage(initializingPropersties);
475        }
476        else {
477            stateMgmtConsole.error("AppStorage.CreateNewInstance(..): instance exists already, internal error!");
478        }
479    }
480    /**
481    * create and return a two-way sync "(link") to named property
482    *
483    * Same as @see LocalStorage.link()
484    *
485    * @param propName name of source property in AppStorage
486     * @param linkUser IPropertySubscriber to be notified when source changes,
487     * @param subscribersName the linkUser (subscriber) uses this name for the property
488     *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
489     * @returns  SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as its source.
490     *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
491     *           return undefiend if named property does not already exist in AppStorage
492     *
493     * @since 7
494     */
495    static Link(key, linkUser, subscribersName) {
496        return AppStorage.GetOrCreate().link(key, linkUser, subscribersName);
497    }
498    /**
499    * Like @see link(), but will create and initialize a new source property in LocalStorge if missing
500    *
501    * Same as @see LocalStorage.setAndLink()
502    *
503    * @param propName name of source property in AppStorage
504    * @param defaultValue value to be used for initializing if new creating new property in AppStorage
505    *        default value must be of type S, must not be undefined or null.
506    * @param linkUser IPropertySubscriber to be notified when return 'link' changes,
507    * @param subscribersName the linkUser (subscriber) uses this name for the property
508    *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
509    * @returns SynchedPropertyTwoWay{Simple|Object| object with given LocalStoage prop as  its source.
510    *          Apps can use SDK functions of base class SubscribedAbstractProperty<S>
511    *
512    * @since 7
513    */
514    static SetAndLink(key, defaultValue, linkUser, subscribersName) {
515        return AppStorage.GetOrCreate().setAndLink(key, defaultValue, linkUser, subscribersName);
516    }
517    /**
518   * create and return a one-way sync ('prop') to named property
519   *
520   * Same as @see LocalStorage.prop()
521   *
522   * @param propName name of source property in AppStorage
523   * @param propUser IPropertySubscriber to be notified when source changes,
524   * @param subscribersName the linkUser (subscriber) uses this name for the property
525   *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
526   * @returns  SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as  its source.
527   *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
528   *           return undefiend if named property does not already exist in AppStorage.
529   * @since 7
530   */
531    static Prop(propName, propUser, subscribersName) {
532        return AppStorage.GetOrCreate().prop(propName, propUser, subscribersName);
533    }
534    /**
535   * Like @see prop(), will create and initialize a new source property in AppStorage if missing
536   *
537   * Same as @see LocalStorage.setAndProp()
538   *
539   * @param propName name of source property in AppStorage
540   * @param defaultValue value to be used for initializing if new creating new property in AppStorage.
541   *        default value must be of type S, must not be undefined or null.
542   * @param propUser IPropertySubscriber to be notified when returned 'prop' changes,
543   * @param subscribersName the propUser (subscriber) uses this name for the property
544   *      this name will be used in propertyChange(propName) callback of IMultiPropertiesChangeSubscriber
545   * @returns  SynchedPropertyOneWay{Simple|Object| object with given LocalStoage prop as its source.
546   *           Apps can use SDK functions of base class SubscribedAbstractProperty<S>
547   *
548   * @since 7
549   */
550    static SetAndProp(key, defaultValue, propUser, subscribersName) {
551        return AppStorage.GetOrCreate().setAndProp(key, defaultValue, propUser, subscribersName);
552    }
553    /**
554     * Check if AppStorge has a property with given name
555     * return true if prooperty with given name exists
556     * same as ES6 Map.prototype.has()
557     *
558     * Same as @see LocalStorage.has()
559     *
560     * @param propName searched property
561     * @returns true if property with such name exists in AppStorage
562     *
563     * @since 7
564     */
565    static Has(key) {
566        return AppStorage.GetOrCreate().has(key);
567    }
568    /**
569    * Returns value of given property
570    * return undefined if no property with this name
571    *
572    *
573    * @Same as see LocalStorage.get()
574    *
575    * @param propName
576    * @returns property value if found or undefined
577    *
578    */
579    static Get(key) {
580        return AppStorage.GetOrCreate().get(key);
581    }
582    /**
583    * Set value of given property in AppStorage
584    * Methosd sets nothing and returns false if property with this name does not exist
585    * or if newValue is `undefined` or `null` (`undefined`, `null` value are not allowed for state variables).
586    *
587    * Same as @see LocalStorage.set
588    *
589    * @param propName
590    * @param newValue must be of type T and must not be undefined or null
591    * @returns true on success, i.e. when above conditions are satisfied, otherwise false
592    *
593    * @since 7
594    */
595    static Set(key, newValue) {
596        return AppStorage.GetOrCreate().set(key, newValue);
597    }
598    /**
599   * Set value of given property, if it exists, @see set() .
600   * Add property if no property with given name and initialize with given value.
601   * Do nothing and return false if newValuue is undefined or null
602   * (undefined, null value is not allowed for state variables)
603   *
604   * @see LocalStorage.setOrCreate()
605   *
606   * @param propName
607   * @param newValue must be of type T and must not be undefined or null
608   * @returns true on success, i.e. when above conditions are satisfied, otherwise false
609   *
610   * @since 7
611   */
612    static SetOrCreate(key, newValue) {
613        AppStorage.GetOrCreate().setOrCreate(key, newValue);
614    }
615    /**
616     * Delete property from StorageBase
617     * Use with caution:
618     * Before deleting a prop from AppStorage all its subscribers need to
619     * unsubscribe from the property.
620     * This method fails and returns false if given property still has subscribers
621     * Another reason for failing is unkmown property.
622     *
623     * Developer advise:
624     * Subscribers are created with @see link(), @see prop()
625     * and also via @LocalStorageLink and @LocalStorageProp state variable decorators.
626     * That means as long as their is a @Component instance that uses such decorated variable
627     * or a sync relationship with a SubscribedAbstractProperty variable the property can nit
628     * (and also should not!) be deleted from AppStorage.
629     *
630     * Same as @see LocalStorage.delete()
631     *
632     * @param propName
633     * @returns false if method failed
634     *
635     * @since 7
636    */
637    static Delete(key) {
638        return AppStorage.GetOrCreate().delete(key);
639    }
640    /**
641    * Provide names of all properties in AppStorage
642    * same as ES6 Map.prototype.keys()
643    *
644    * Same as @see LocalStorage.keys()
645    *
646    * @returns return a Map Iterator
647    *
648    * @since 7
649   */
650    static Keys() {
651        return AppStorage.GetOrCreate().keys();
652    }
653    /**
654     * Returns number of properties in AppStorage
655     * same as Map.prototype.size()
656     *
657     * Same as @see LocalStorage.size()
658     *
659     * @param propName
660     * @returns return number of properties
661     *
662     * @since 7
663     */
664    static Size() {
665        return AppStorage.GetOrCreate().size();
666    }
667    /**
668     * delete all properties from the AppStorage
669     *
670     * @see delete(), same as @see LocalStorage.clear()
671     *
672     * precondition is that there are no subscribers.
673     * method returns false and deletes no poperties if there is any property
674     * that still has subscribers
675     *
676     * @since 7
677     */
678    static Clear() {
679        return AppStorage.GetOrCreate().clear();
680    }
681    /**
682     * Same as @see Clear().
683     *
684     * @since 7, depreciated, used Clear() instead!
685     *
686     */
687    static StaticClear() {
688        return AppStorage.Clear();
689    }
690    /**
691    * not a public / sdk function
692    */
693    static AboutToBeDeleted() {
694        AppStorage.GetOrCreate().aboutToBeDeleted();
695    }
696    /**
697     * return number of subscribers to named property
698     * useful for debug purposes
699     *
700     * not a public / sdk function
701    */
702    static NumberOfSubscribersTo(propName) {
703        return AppStorage.GetOrCreate().numberOfSubscrbersTo(propName);
704    }
705    /**
706    * Subscribe to value change notifications of named property
707    * Any object implementing ISinglePropertyChangeSubscriber interface
708    * and registerign itself to SubscriberManager can register
709    * Caution: do remember to unregister, otherwise the property will block
710    * cleanup, @see delete() and @see clear()
711    *
712    * Same as @see LocalStorage.subscribeToChangesOf()
713    *
714    * @param propName property in AppStorage to subscribe to
715    * @param subscriber object that implements ISinglePropertyChangeSubscriber interface
716    * @returns false if named property does not exist
717    *
718    * @since 7
719    */
720    static SubscribeToChangesOf(propName, subscriber) {
721        return AppStorage.GetOrCreate().subscribeToChangesOf(propName, subscriber);
722    }
723    /**
724     * inverse of @see SubscribeToChangesOf,
725     * same as @see LocalStorage.subscribeToChangesOf()
726     *
727     * @param propName property in AppStorage to subscribe to
728     * @param subscriberId id of the subscrber passed to @see subscribeToChangesOf
729     * @returns false if named property does not exist
730     *
731     * @since 7
732     */
733    static UnsubscribeFromChangesOf(propName, subscriberId) {
734        return AppStorage.GetOrCreate().unsubscribeFromChangesOf(propName, subscriberId);
735    }
736    /**
737     * Unimplemenrted, currently all properties of AppStorage are mutable.
738     *
739     * @since 7, depreciated
740     */
741    static IsMutable(key) {
742        return true;
743    }
744    /**
745     * not a public / sdk function
746     */
747    static __CreateSync(storagePropName, defaultValue, factoryFunc) {
748        return AppStorage.GetOrCreate().__createSync(storagePropName, defaultValue, factoryFunc);
749    }
750    /**
751     * not a public / sdk function
752     */
753    static GetOrCreate() {
754        if (!AppStorage.Instance_) {
755            stateMgmtConsole.warn("AppStorage instance missing. Use AppStorage.CreateInstance(initObj). Creating instance without any initialization.");
756            AppStorage.Instance_ = new AppStorage({});
757        }
758        return AppStorage.Instance_;
759    }
760}
761// instance functions below:
762// Should all be protected, but TS lang does not allow access from static member to protected member
763AppStorage.Instance_ = undefined;
764/*
765 * Copyright (c) 2022 Huawei Device Co., Ltd.
766 * Licensed under the Apache License, Version 2.0 (the "License");
767 * you may not use this file except in compliance with the License.
768 * You may obtain a copy of the License at
769 *
770 *     http://www.apache.org/licenses/LICENSE-2.0
771 *
772 * Unless required by applicable law or agreed to in writing, software
773 * distributed under the License is distributed on an "AS IS" BASIS,
774 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
775 * See the License for the specific language governing permissions and
776 * limitations under the License.
777 */
778/**
779 * Singleton class SubscriberManager implements IPropertySubscriberLookup
780 * public API to manage IPropertySubscriber
781 */
782class SubscriberManager {
783    /**
784     * SubscriberManager is a singleton created by the framework
785     * do not use
786     *
787     * internal method
788     */
789    constructor() {
790        this.subscriberById_ = new Map();
791
792    }
793    /**
794      * check subscriber is known
795      * same as ES6 Map.prototype.has()
796      *
797      * @since 9
798      */
799    static Has(id) {
800        return SubscriberManager.GetInstance().has(id);
801    }
802    /**
803     *
804     * retrieve subscriber by id
805     * same as ES6 Map.prototype.get()
806     *
807     *  @since 9
808     */
809    static Find(id) {
810        return SubscriberManager.GetInstance().get(id);
811    }
812    /**
813     * unregister a subscriber
814     * same as ES6 Map.prototype.delete()
815     * @return boolean success or failure to delete
816     *
817     *  @since 9
818     */
819    static Delete(id) {
820        return SubscriberManager.GetInstance().delete(id);
821    }
822    /**
823    * add a new subscriber.
824    * The subscriber must have a new (unused) id (@see MakeId() )
825    * for add() to succeed.
826    * same as Map.prototype.set()
827    *
828    *  @since 9
829    */
830    static Add(newSubsriber) {
831        return SubscriberManager.GetInstance().add(newSubsriber);
832    }
833    /**
834    *
835    * @returns a globally unique id to be assigned to a IPropertySubscriber objet
836    * Use MakeId() to assign a IPropertySubscriber object an id before calling @see add() .
837    *
838    *  @since 9
839   */
840    static MakeId() {
841        return SubscriberManager.GetInstance().makeId();
842    }
843    /**
844     * Check number of registered Subscriber / registered IDs.
845     * @returns number of registered unique ids.
846     *
847     *  @since 9
848     */
849    static NumberOfSubscribers() {
850        return SubscriberManager.GetInstance().numberOfSubscribers();
851    }
852    /**
853     *
854     * internal (non-SDK) methods below
855     *
856    */
857    /**
858   * Get singleton, create it on first call
859   * @returns SubscriberManager singleton
860   *
861   * internal function
862   * This function will be removed soon, use static functions instead!
863   * Note: Fnction gets used by transpiler output for both full update and partial update
864   */
865    static Get() {
866        if (!SubscriberManager.instance_) {
867            SubscriberManager.instance_ = new SubscriberManager();
868        }
869        return SubscriberManager.instance_;
870    }
871    /**
872     * Get singleton, create it on first call
873     * @returns SubscriberManager singleton
874     *
875     * internal function
876     */
877    static GetInstance() {
878        if (!SubscriberManager.instance_) {
879            SubscriberManager.instance_ = new SubscriberManager();
880        }
881        return SubscriberManager.instance_;
882    }
883    /**
884     * for debug purposes dump all known subscriber's info to comsole
885     *
886     * not a public / sdk function
887     */
888    static DumpSubscriberInfo() {
889        SubscriberManager.GetInstance().dumpSubscriberInfo();
890    }
891    /**
892     * not a public / sdk function
893     * @see Has
894     */
895    has(id) {
896        return this.subscriberById_.has(id);
897    }
898    /**
899     * not a public / sdk function
900     * @see Get
901     */
902    get(id) {
903        return this.subscriberById_.get(id);
904    }
905    /**
906   * not a public / sdk function
907   * @see Delete
908   */
909    delete(id) {
910        if (!this.has(id)) {
911            stateMgmtConsole.warn(`SubscriberManager.delete unknown id ${id} `);
912            return false;
913        }
914        return this.subscriberById_.delete(id);
915    }
916    /**
917   * not a public / sdk function
918   * @see Add
919   */
920    add(newSubsriber) {
921        if (this.has(newSubsriber.id__())) {
922            return false;
923        }
924        this.subscriberById_.set(newSubsriber.id__(), newSubsriber);
925        return true;
926    }
927    /**
928     * Method for testing purposes
929     * @returns number of subscribers
930     *
931     * not a public / sdk function
932     */
933    numberOfSubscribers() {
934        return this.subscriberById_.size;
935    }
936    /**
937     * for debug purposes dump all known subscriber's info to comsole
938     *
939     * not a public / sdk function
940     */
941    dumpSubscriberInfo() {
942
943        for (let [id, subscriber] of this.subscriberById_) {
944
945        }
946
947    }
948    /**
949     *
950     * @returns a globally unique id to be assigned to a Subscriber
951     */
952    makeId() {
953        return ViewStackProcessor.MakeUniqueId();
954    }
955}
956/*
957 * Copyright (c) 2022 Huawei Device Co., Ltd.
958 * Licensed under the Apache License, Version 2.0 (the "License");
959 * you may not use this file except in compliance with the License.
960 * You may obtain a copy of the License at
961 *
962 *     http://www.apache.org/licenses/LICENSE-2.0
963 *
964 * Unless required by applicable law or agreed to in writing, software
965 * distributed under the License is distributed on an "AS IS" BASIS,
966 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
967 * See the License for the specific language governing permissions and
968 * limitations under the License.
969 */
970/**
971 *
972 *   SubscribedAbstractProperty is base class of ObservedPropertyAbstract
973 *   and includes these 3 functions that are part of the SDK.
974 *
975 *   SubscribedAbstractProperty<T> is the return type of
976 *   - AppStorage static functions Link(), Prop(), SetAndLink(), and SetAndProp()
977 *   - LocalStorage methods link(), prop(), setAndLink(), and setAndProp()
978 *
979 *   'T' can be boolean, string, number or custom class.
980 *
981 * Main functions
982 *   @see get() reads the linked AppStorage/LocalStorage property value,
983 *   @see set(newValue) write a new value to the synched AppStorage/LocalStorage property value
984 *   @see aboutToBeDeleted() ends the sync relationship with the AppStorage/LocalStorage property
985 *        The app must call this function before the SubscribedAbstractProperty<T> object
986 *        goes out of scope.
987 *
988 * @since 7
989*/
990class SubscribedAbstractProperty {
991}
992/*
993 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
994 * Licensed under the Apache License, Version 2.0 (the "License");
995 * you may not use this file except in compliance with the License.
996 * You may obtain a copy of the License at
997 *
998 *     http://www.apache.org/licenses/LICENSE-2.0
999 *
1000 * Unless required by applicable law or agreed to in writing, software
1001 * distributed under the License is distributed on an "AS IS" BASIS,
1002 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1003 * See the License for the specific language governing permissions and
1004 * limitations under the License.
1005 */
1006/**
1007 *
1008 * SubscriableAbstract
1009 *
1010 * This class is part of the SDK.
1011 * @since 9
1012 *
1013 * SubscriableAbstract is an abstract class that manages subscribers
1014 * to value changes. These subscribers are the implementation of
1015 * @State, @Link, @Provide, @Consume decorated variables inside the
1016 * framework. Each using @State, @Link, etc., decorated varibale in
1017 * a @Component will make its own subscription. When the component
1018 * is created the subscription is added, and before the component
1019 * is deleted it unsubscribes
1020 *
1021 * An application may extend SubscriableAbstract for a custom class
1022 * that manages state data. @State, @Link, @Provide, @Consume
1023 * decorated variables can hold an Object that is instance of
1024 * SubscribaleAbstract.
1025 *
1026 * About lifecycle: It is legal use for two @Components with two @State
1027 * decorated variables to share the same SubscribaleAbstract object.
1028 * Each such decorated variable implementation makes its own
1029 * subscription to the SubscribaleAbstract object. Hence, when both variables
1030 * have unsubscribed the SubscribaleAbstract custom class may do its own
1031 * de-initilialization, e.g. release held external resources.
1032 *
1033 * How to extend:
1034 * A subclass manages the get and set to one or several properties on its own.
1035 * The subclass needs to notify all relevant value changes to the framework for the
1036 * UI to be updated. Notification should only be given for class properties that
1037 * are used to generate the UI.
1038 *
1039 * A subclass must call super() in its constructor to let this base class
1040 * initialize itself.
1041 *
1042 * A subclass must call 'notifyPropertyHasChanged*(' after the relevant property
1043 * has changes. The framework will notify all dependent components to re-render.
1044 *
1045 * A sub-class may overwrite the 'addOwningProperty' function to add own
1046 * functionality, but it must call super.addowningOwningProperty(..). E.g.
1047 * the sub-class could connect to external resources upon the first subscriber.
1048 *
1049 * A sub-class may also overwrite the 'removeOwningProperty' function or
1050 * 'removeOwningPropertyById' function to add own functionality,
1051 * but it must call super.removeOwningProperty(..).
1052 * E.g. the sub-class could release held external resources upon loosing the
1053 * last subscriber.
1054 *
1055 */
1056class SubscribaleAbstract {
1057    /**
1058     * make sure to call super() from subclass constructor!
1059     *
1060     * @since 9
1061     */
1062    constructor() {
1063        this.owningProperties_ = new Set();
1064
1065    }
1066    /**
1067    * A subsclass must call this function whenever one of its properties has
1068     * changed that is used to construct the UI.
1069     * @param propName name of the change property
1070     * @param newValue the property value after the change
1071     *
1072     * @since 9
1073     */
1074    notifyPropertyHasChanged(propName, newValue) {
1075
1076        this.owningProperties_.forEach((subscribedId) => {
1077            var owningProperty = SubscriberManager.Find(subscribedId);
1078            if (owningProperty) {
1079                if ('objectPropertyHasChangedPU' in owningProperty) {
1080                    // PU code path
1081                    owningProperty.objectPropertyHasChangedPU(this, propName);
1082                }
1083                // FU code path
1084                if ('hasChanged' in owningProperty) {
1085                    owningProperty.hasChanged(newValue);
1086                }
1087                if ('propertyHasChanged' in owningProperty) {
1088                    owningProperty.propertyHasChanged(propName);
1089                }
1090            }
1091            else {
1092                stateMgmtConsole.error(`SubscribaleAbstract: notifyHasChanged: unknown subscriber.'${subscribedId}' error!.`);
1093            }
1094        });
1095    }
1096    /**
1097     * Method used by the framework to add subscribing decorated variables
1098     * Subclass may overwrite this function but must call the function of the base
1099     * class from its own implementation.
1100     * @param subscriber new subscriber that implements ISinglePropertyChangeSubscriber
1101     * and/or IMultiPropertiesChangeSubscriber interfaces
1102     *
1103     * @since 9
1104     */
1105    addOwningProperty(subscriber) {
1106
1107        this.owningProperties_.add(subscriber.id__());
1108    }
1109    /**
1110     * Method used by the framework to ubsubscribing decorated variables
1111     * Subclass may overwrite this function but must call the function of the base
1112     * class from its own implementation.
1113     * @param subscriber subscriber that implements ISinglePropertyChangeSubscriber
1114     * and/or IMultiPropertiesChangeSubscriber interfaces
1115     *
1116     * @since 9
1117     */
1118    removeOwningProperty(property) {
1119        return this.removeOwningPropertyById(property.id__());
1120    }
1121    /**
1122     * Same as @see removeOwningProperty() but by Subscriber id.
1123     * @param subscriberId
1124    *
1125    * @since 9
1126     */
1127    removeOwningPropertyById(subscriberId) {
1128
1129        this.owningProperties_.delete(subscriberId);
1130    }
1131}
1132/*
1133 * Copyright (c) 2021 Huawei Device Co., Ltd.
1134 * Licensed under the Apache License, Version 2.0 (the "License");
1135 * you may not use this file except in compliance with the License.
1136 * You may obtain a copy of the License at
1137 *
1138 *     http://www.apache.org/licenses/LICENSE-2.0
1139 *
1140 * Unless required by applicable law or agreed to in writing, software
1141 * distributed under the License is distributed on an "AS IS" BASIS,
1142 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1143 * See the License for the specific language governing permissions and
1144 * limitations under the License.
1145 */
1146/**
1147 * PersistentStorage
1148 *
1149 * Keeps current values of select AppStorage property properties persisted to file.
1150 *
1151 * since 9
1152 */
1153class PersistentStorage {
1154    /**
1155     * all following methods are framework internal
1156     */
1157    constructor() {
1158        this.links_ = new Map();
1159        this.id_ = SubscriberManager.MakeId();
1160        SubscriberManager.Add(this);
1161    }
1162    /**
1163     *
1164     * @param storage method to be used by the framework to set the backend
1165     * this is to be done during startup
1166     *
1167     * internal function, not part of the SDK
1168     *
1169     */
1170    static ConfigureBackend(storage) {
1171        PersistentStorage.Storage_ = storage;
1172    }
1173    /**
1174     * private, use static functions!
1175     */
1176    static GetOrCreate() {
1177        if (PersistentStorage.Instance_) {
1178            // already initialized
1179            return PersistentStorage.Instance_;
1180        }
1181        PersistentStorage.Instance_ = new PersistentStorage();
1182        return PersistentStorage.Instance_;
1183    }
1184    /**
1185     *
1186     * internal function, not part of the SDK
1187     */
1188    static AboutToBeDeleted() {
1189        if (!PersistentStorage.Instance_) {
1190            return;
1191        }
1192        PersistentStorage.GetOrCreate().aboutToBeDeleted();
1193        PersistentStorage.Instance_ = undefined;
1194    }
1195    /**
1196     * Add property 'key' to AppStorage properties whose current value will be
1197     * persistemt.
1198     * If AppStorage does not include this property it will be added and initializes
1199     * with given value
1200     *
1201     * @since 9
1202     *
1203     * @param key property name
1204     * @param defaultValue If AppStorage does not include this property it will be initialized with this value
1205     *
1206     */
1207    static PersistProp(key, defaultValue) {
1208        PersistentStorage.GetOrCreate().persistProp(key, defaultValue);
1209    }
1210    /**
1211     * Reverse of @see PersistProp
1212     * @param key no longer persist the property named key
1213     *
1214     * @since 9
1215     */
1216    static DeleteProp(key) {
1217        PersistentStorage.GetOrCreate().deleteProp(key);
1218    }
1219    /**
1220     * Persist given AppStorage properties with given names.
1221     * If a property does not exist in AppStorage, add it and initialize it with given value
1222     * works as @see PersistProp for multiple properties.
1223     *
1224     * @param properties
1225     *
1226     * @since 9
1227     *
1228     */
1229    static PersistProps(properties) {
1230        PersistentStorage.GetOrCreate().persistProps(properties);
1231    }
1232    /**
1233     * Inform persisted AppStorage property names
1234     * @returns array of AppStorage keys
1235     *
1236     * @since 9
1237     */
1238    static Keys() {
1239        let result = [];
1240        const it = PersistentStorage.GetOrCreate().keys();
1241        let val = it.next();
1242        while (!val.done) {
1243            result.push(val.value);
1244            val = it.next();
1245        }
1246        return result;
1247    }
1248    /**
1249      * This methid offers a way to force writing the property value with given
1250      * key to persistent storage.
1251      * In the general case this is unnecessary as the framework observed changes
1252      * and triggers writing to disk by itself. For nested objects (e.g. array of
1253      * objects) however changes of a property of a property as not observed. This
1254      * is the case where the application needs to signal to the framework.
1255      *
1256      * @param key property that has changed
1257      *
1258      * @since 9
1259      *
1260      */
1261    static NotifyHasChanged(propName) {
1262
1263        PersistentStorage.Storage_.set(propName, PersistentStorage.GetOrCreate().links_.get(propName).get());
1264    }
1265    keys() {
1266        return this.links_.keys();
1267    }
1268    persistProp(propName, defaultValue) {
1269        if (this.persistProp1(propName, defaultValue)) {
1270            // persist new prop
1271
1272            PersistentStorage.Storage_.set(propName, this.links_.get(propName).get());
1273        }
1274    }
1275    // helper function to persist a property
1276    // does everything except writing prop to disk
1277    persistProp1(propName, defaultValue) {
1278        if (defaultValue == null || defaultValue == undefined) {
1279            stateMgmtConsole.error(`PersistentStorage: persistProp for ${propName} called with 'null' or 'undefined' default value!`);
1280            return false;
1281        }
1282        if (this.links_.get(propName)) {
1283            stateMgmtConsole.warn(`PersistentStorage: persistProp: ${propName} is already persisted`);
1284            return false;
1285        }
1286        let link = AppStorage.Link(propName, this);
1287        if (link) {
1288
1289            this.links_.set(propName, link);
1290        }
1291        else {
1292            let newValue = PersistentStorage.Storage_.get(propName);
1293            let returnValue;
1294            if (!newValue) {
1295
1296                returnValue = defaultValue;
1297            }
1298            else {
1299                returnValue = newValue;
1300            }
1301            link = AppStorage.SetAndLink(propName, returnValue, this);
1302            this.links_.set(propName, link);
1303
1304        }
1305        return true;
1306    }
1307    persistProps(properties) {
1308        properties.forEach(property => this.persistProp1(property.key, property.defaultValue));
1309        this.write();
1310    }
1311    deleteProp(propName) {
1312        let link = this.links_.get(propName);
1313        if (link) {
1314            link.aboutToBeDeleted();
1315            this.links_.delete(propName);
1316            PersistentStorage.Storage_.delete(propName);
1317
1318        }
1319        else {
1320            stateMgmtConsole.warn(`PersistentStorage: '${propName}' is not a persisted property warning.`);
1321        }
1322    }
1323    write() {
1324        this.links_.forEach((link, propName, map) => {
1325
1326            PersistentStorage.Storage_.set(propName, link.get());
1327        });
1328    }
1329    propertyHasChanged(info) {
1330
1331        this.write();
1332    }
1333    syncPeerHasChanged(eventSource) {
1334
1335        this.write();
1336    }
1337    // public required by the interface, use the static method instead!
1338    aboutToBeDeleted() {
1339
1340        this.links_.forEach((val, key, map) => {
1341
1342            val.aboutToBeDeleted();
1343        });
1344        this.links_.clear();
1345        SubscriberManager.Delete(this.id__());
1346        PersistentStorage.Storage_.clear();
1347    }
1348    id__() {
1349        return this.id_;
1350    }
1351}
1352PersistentStorage.Instance_ = undefined;
1353;
1354/*
1355 * Copyright (c) 2021 Huawei Device Co., Ltd.
1356 * Licensed under the Apache License, Version 2.0 (the "License");
1357 * you may not use this file except in compliance with the License.
1358 * You may obtain a copy of the License at
1359 *
1360 *     http://www.apache.org/licenses/LICENSE-2.0
1361 *
1362 * Unless required by applicable law or agreed to in writing, software
1363 * distributed under the License is distributed on an "AS IS" BASIS,
1364 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365 * See the License for the specific language governing permissions and
1366 * limitations under the License.
1367 */
1368/**
1369 * Environment
1370 *
1371 * Injects device properties ("environment") into AppStorage
1372 *
1373 */
1374class Environment {
1375    constructor() {
1376        this.props_ = new Map();
1377        Environment.EnvBackend_.onValueChanged(this.onValueChanged.bind(this));
1378    }
1379    static GetOrCreate() {
1380        if (Environment.Instance_) {
1381            // already initialized
1382            return Environment.Instance_;
1383        }
1384        Environment.Instance_ = new Environment();
1385        return Environment.Instance_;
1386    }
1387    static ConfigureBackend(envBackend) {
1388        Environment.EnvBackend_ = envBackend;
1389    }
1390    static AboutToBeDeleted() {
1391        if (!Environment.Instance_) {
1392            return;
1393        }
1394        Environment.GetOrCreate().aboutToBeDeleted();
1395        Environment.Instance_ = undefined;
1396    }
1397    static EnvProp(key, value) {
1398        return Environment.GetOrCreate().envProp(key, value);
1399    }
1400    static EnvProps(props) {
1401        Environment.GetOrCreate().envProps(props);
1402    }
1403    static Keys() {
1404        return Environment.GetOrCreate().keys();
1405    }
1406    envProp(key, value) {
1407        let prop = AppStorage.Prop(key);
1408        if (prop) {
1409            stateMgmtConsole.warn(`Environment: envProp '${key}': Property already exists in AppStorage. Not using environment property.`);
1410            return false;
1411        }
1412        let tmp;
1413        switch (key) {
1414            case "accessibilityEnabled":
1415                tmp = Environment.EnvBackend_.getAccessibilityEnabled();
1416                break;
1417            case "colorMode":
1418                tmp = Environment.EnvBackend_.getColorMode();
1419                break;
1420            case "fontScale":
1421                tmp = Environment.EnvBackend_.getFontScale();
1422                break;
1423            case "fontWeightScale":
1424                tmp = Environment.EnvBackend_.getFontWeightScale().toFixed(2);
1425                break;
1426            case "layoutDirection":
1427                tmp = Environment.EnvBackend_.getLayoutDirection();
1428                break;
1429            case "languageCode":
1430                tmp = Environment.EnvBackend_.getLanguageCode();
1431                break;
1432            default:
1433                tmp = value;
1434        }
1435        prop = AppStorage.SetAndProp(key, tmp);
1436        this.props_.set(key, prop);
1437
1438    }
1439    envProps(properties) {
1440        properties.forEach(property => {
1441            this.envProp(property.key, property.defaultValue);
1442
1443        });
1444    }
1445    keys() {
1446        let result = [];
1447        const it = this.props_.keys();
1448        let val = it.next();
1449        while (!val.done) {
1450            result.push(val.value);
1451            val = it.next();
1452        }
1453        return result;
1454    }
1455    onValueChanged(key, value) {
1456        let ok = AppStorage.Set(key, value);
1457        if (ok) {
1458
1459        }
1460        else {
1461            stateMgmtConsole.warn(`Environment: onValueChanged: error changing ${key}! See results above.`);
1462        }
1463    }
1464    aboutToBeDeleted() {
1465        this.props_.forEach((val, key, map) => {
1466            val.aboutToBeDeleted();
1467            AppStorage.Delete(key);
1468        });
1469    }
1470}
1471Environment.Instance_ = undefined;
1472/*
1473 * Copyright (c) 2022 Huawei Device Co., Ltd.
1474 * Licensed under the Apache License, Version 2.0 (the "License");
1475 * you may not use this file except in compliance with the License.
1476 * You may obtain a copy of the License at
1477 *
1478 *     http://www.apache.org/licenses/LICENSE-2.0
1479 *
1480 * Unless required by applicable law or agreed to in writing, software
1481 * distributed under the License is distributed on an "AS IS" BASIS,
1482 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1483 * See the License for the specific language governing permissions and
1484 * limitations under the License.
1485 */
1486/**
1487 * state mgmt library uses its own class for logging
1488* allows to remap separately from other use of aceConsole
1489*
1490* everything in this file is framework internal
1491*/
1492class stateMgmtConsole {
1493    static log(...args) {
1494        aceConsole.log(...args);
1495    }
1496    static debug(...args) {
1497        aceConsole.debug(...args);
1498    }
1499    static info(...args) {
1500        aceConsole.info(...args);
1501    }
1502    static warn(...args) {
1503        aceConsole.warn(...args);
1504    }
1505    static error(...args) {
1506        aceConsole.error(...args);
1507    }
1508}
1509class stateMgmtTrace {
1510    static scopedTrace(codeBlock, arg1, ...args) {
1511        aceTrace.begin(arg1, ...args);
1512        let result = codeBlock();
1513        aceTrace.end();
1514        return result;
1515    }
1516}
1517/*
1518 * Copyright (c) 2022 Huawei Device Co., Ltd.
1519 * Licensed under the Apache License, Version 2.0 (the "License");
1520 * you may not use this file except in compliance with the License.
1521 * You may obtain a copy of the License at
1522 *
1523 *     http://www.apache.org/licenses/LICENSE-2.0
1524 *
1525 * Unless required by applicable law or agreed to in writing, software
1526 * distributed under the License is distributed on an "AS IS" BASIS,
1527 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1528 * See the License for the specific language governing permissions and
1529 * limitations under the License.
1530 */
1531class DistributedStorage {
1532    constructor(sessionId, notifier) {
1533        this.links_ = new Map();
1534        this.id_ = SubscriberManager.MakeId();
1535        SubscriberManager.Add(this);
1536        this.aviliable_ = false;
1537        this.notifier_ = notifier;
1538    }
1539    keys() {
1540        let result = [];
1541        const it = this.links_.keys();
1542        let val = it.next();
1543        while (!val.done) {
1544            result.push(val.value);
1545            val = it.next();
1546        }
1547        return result;
1548    }
1549    distributeProp(propName, defaultValue) {
1550        if (this.link(propName, defaultValue)) {
1551
1552        }
1553    }
1554    distributeProps(properties) {
1555        properties.forEach(property => this.link(property.key, property.defaultValue));
1556    }
1557    link(propName, defaultValue) {
1558        if (defaultValue == null || defaultValue == undefined) {
1559            stateMgmtConsole.error(`DistributedStorage: linkProp for ${propName} called with 'null' or 'undefined' default value!`);
1560            return false;
1561        }
1562        if (this.links_.get(propName)) {
1563            stateMgmtConsole.warn(`DistributedStorage: linkProp: ${propName} is already exist`);
1564            return false;
1565        }
1566        let link = AppStorage.Link(propName, this);
1567        if (link) {
1568
1569            this.links_.set(propName, link);
1570            this.setDistributedProp(propName, defaultValue);
1571        }
1572        else {
1573            let returnValue = defaultValue;
1574            if (this.aviliable_) {
1575                let newValue = this.getDistributedProp(propName);
1576                if (newValue == null) {
1577
1578                    this.setDistributedProp(propName, defaultValue);
1579                }
1580                else {
1581                    returnValue = newValue;
1582                }
1583            }
1584            link = AppStorage.SetAndLink(propName, returnValue, this);
1585            this.links_.set(propName, link);
1586
1587        }
1588        return true;
1589    }
1590    deleteProp(propName) {
1591        let link = this.links_.get(propName);
1592        if (link) {
1593            link.aboutToBeDeleted();
1594            this.links_.delete(propName);
1595            if (this.aviliable_) {
1596                this.storage_.delete(propName);
1597            }
1598        }
1599        else {
1600            stateMgmtConsole.warn(`DistributedStorage: '${propName}' is not a distributed property warning.`);
1601        }
1602    }
1603    write(key) {
1604        let link = this.links_.get(key);
1605        if (link) {
1606            this.setDistributedProp(key, link.get());
1607        }
1608    }
1609    // public required by the interface, use the static method instead!
1610    aboutToBeDeleted() {
1611
1612        this.links_.forEach((val, key, map) => {
1613
1614            val.aboutToBeDeleted();
1615        });
1616        this.links_.clear();
1617        SubscriberManager.Delete(this.id__());
1618    }
1619    id__() {
1620        return this.id_;
1621    }
1622    propertyHasChanged(info) {
1623
1624        this.write(info);
1625    }
1626    onDataOnChange(propName) {
1627        let link = this.links_.get(propName);
1628        let newValue = this.getDistributedProp(propName);
1629        if (link && newValue != null) {
1630
1631            link.set(newValue);
1632        }
1633    }
1634    onConnected(status) {
1635
1636        if (!this.aviliable_) {
1637            this.syncProp();
1638            this.aviliable_ = true;
1639        }
1640        if (this.notifier_ != null) {
1641            this.notifier_(status);
1642        }
1643    }
1644    syncProp() {
1645        this.links_.forEach((val, key) => {
1646            let newValue = this.getDistributedProp(key);
1647            if (newValue == null) {
1648                this.setDistributedProp(key, val.get());
1649            }
1650            else {
1651                val.set(newValue);
1652            }
1653        });
1654    }
1655    setDistributedProp(key, value) {
1656        if (!this.aviliable_) {
1657            stateMgmtConsole.warn(`DistributedStorage is not aviliable`);
1658            return;
1659        }
1660        stateMgmtConsole.error(`DistributedStorage value is object ${key}-${JSON.stringify(value)}`);
1661        if (typeof value == 'object') {
1662            this.storage_.set(key, JSON.stringify(value));
1663            return;
1664        }
1665        this.storage_.set(key, value);
1666    }
1667    getDistributedProp(key) {
1668        let value = this.storage_.get(key);
1669        if (typeof value == 'string') {
1670            try {
1671                let returnValue = JSON.parse(value);
1672                return returnValue;
1673            }
1674            finally {
1675                return value;
1676            }
1677        }
1678        return value;
1679    }
1680}
1681;
1682/*
1683 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
1684 * Licensed under the Apache License, Version 2.0 (the "License");
1685 * you may not use this file except in compliance with the License.
1686 * You may obtain a copy of the License at
1687 *
1688 *     http://www.apache.org/licenses/LICENSE-2.0
1689 *
1690 * Unless required by applicable law or agreed to in writing, software
1691 * distributed under the License is distributed on an "AS IS" BASIS,
1692 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1693 * See the License for the specific language governing permissions and
1694 * limitations under the License.
1695 */
1696var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
1697    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1698    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1699    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1700    return c > 3 && r && Object.defineProperty(target, key, r), r;
1701};
1702/**
1703* @Observed class decorator
1704*
1705* usage:
1706*    @Observed class ClassA { ... }
1707*
1708* Causes every instance of decorated clss to be automatically wrapped inside an ObservedObject.
1709*
1710* Implemented by extending the decroaetd class by class named 'ObservableObjectClass'.
1711*
1712* It is permisstable to decorate the base and the extended class like thisNote: I
1713*   @Observed class ClassA { ...}
1714*   @Observed class ClassB extends ClassA { ... }
1715* and use
1716*   a = new ClassA();
1717*   b = new ClassB();
1718* Only one ES6 Proxy is added.
1719*
1720*
1721* Take note the decorator implementation extends the prototype chain.
1722*
1723* The prototype chain of a in above example is
1724*  - ObservableObjectClass prototype
1725*  - ClassA prototype
1726*  - Object prototype
1727*
1728* Snd the prototype chain of b is
1729*  - ObservableObjectClass prototype
1730*  - ClassB prototype
1731*  - ObservableObjectClass prototype
1732*  - ClassA prototype
1733*  - Object prototype
1734*
1735* The @Observed decorator is public, part of the SDK, starting from API 9.
1736*
1737*/
1738// define just once to get just one Symbol
1739const __IS_OBSERVED_PROXIED = Symbol("_____is_observed_proxied__");
1740function Observed(constructor_, _) {
1741
1742    let ObservedClass = class extends constructor_ {
1743        constructor(...args) {
1744            super(...args);
1745
1746            let isProxied = Reflect.has(this, __IS_OBSERVED_PROXIED);
1747            Object.defineProperty(this, __IS_OBSERVED_PROXIED, {
1748                value: true,
1749                enumerable: false,
1750                configurable: false,
1751                writable: false
1752            });
1753            if (isProxied) {
1754
1755                return this;
1756            }
1757            else {
1758
1759                return ObservedObject.createNewInternal(this, undefined);
1760            }
1761        }
1762    };
1763    return ObservedClass;
1764}
1765// force tsc to generate the __decorate data structure needed for @Observed
1766// tsc will not generate unless the @Observed class decorator is used at least once
1767let __IGNORE_FORCE_decode_GENERATION__ = class __IGNORE_FORCE_decode_GENERATION__ {
1768};
1769__IGNORE_FORCE_decode_GENERATION__ = __decorate([
1770    Observed
1771], __IGNORE_FORCE_decode_GENERATION__);
1772/**
1773 * class ObservedObject and supporting Handler classes,
1774 * Extends from ES6 Proxy. In adding to 'get' and 'set'
1775 * the clasess manage subscribers that receive notification
1776 * about proxies object being 'read' or 'changed'.
1777 *
1778 * These classes are framework internal / non-SDK
1779 *
1780 */
1781class SubscribableHandler {
1782    constructor(owningProperty) {
1783        this.owningProperties_ = new Set();
1784        if (owningProperty) {
1785            this.addOwningProperty(owningProperty);
1786        }
1787
1788    }
1789    addOwningProperty(subscriber) {
1790        if (subscriber) {
1791
1792            this.owningProperties_.add(subscriber.id__());
1793        }
1794        else {
1795            stateMgmtConsole.warn(`SubscribableHandler: addOwningProperty: undefined subscriber. - Internal error?`);
1796        }
1797    }
1798    /*
1799        the inverse function of createOneWaySync or createTwoWaySync
1800      */
1801    removeOwningProperty(property) {
1802        return this.removeOwningPropertyById(property.id__());
1803    }
1804    removeOwningPropertyById(subscriberId) {
1805
1806        this.owningProperties_.delete(subscriberId);
1807    }
1808    notifyObjectPropertyHasChanged(propName, newValue) {
1809
1810        this.owningProperties_.forEach((subscribedId) => {
1811            var owningProperty = SubscriberManager.Find(subscribedId);
1812            if (owningProperty) {
1813                if ('objectPropertyHasChangedPU' in owningProperty) {
1814                    // PU code path
1815                    owningProperty.objectPropertyHasChangedPU(this, propName);
1816                }
1817                // FU code path
1818                if ('hasChanged' in owningProperty) {
1819                    owningProperty.hasChanged(newValue);
1820                }
1821                if ('propertyHasChanged' in owningProperty) {
1822                    owningProperty.propertyHasChanged(propName);
1823                }
1824            }
1825            else {
1826                stateMgmtConsole.warn(`SubscribableHandler: notifyObjectPropertyHasChanged: unknown subscriber.'${subscribedId}' error!.`);
1827            }
1828        });
1829    }
1830    notifyObjectPropertyHasBeenRead(propName) {
1831
1832        this.owningProperties_.forEach((subscribedId) => {
1833            var owningProperty = SubscriberManager.Find(subscribedId);
1834            if (owningProperty) {
1835                // PU code path
1836                if ('objectPropertyHasBeenReadPU' in owningProperty) {
1837                    owningProperty.objectPropertyHasBeenReadPU(this, propName);
1838                }
1839            }
1840        });
1841    }
1842    has(target, property) {
1843
1844        return (property === ObservedObject.__IS_OBSERVED_OBJECT) ? true : Reflect.has(target, property);
1845    }
1846    get(target, property, receiver) {
1847
1848        return (property === ObservedObject.__OBSERVED_OBJECT_RAW_OBJECT) ? target : Reflect.get(target, property, receiver);
1849    }
1850    set(target, property, newValue) {
1851        switch (property) {
1852            case SubscribableHandler.SUBSCRIBE:
1853                // assignment obsObj[SubscribableHandler.SUBSCRCRIBE] = subscriber
1854                this.addOwningProperty(newValue);
1855                return true;
1856                break;
1857            case SubscribableHandler.UNSUBSCRIBE:
1858                // assignment obsObj[SubscribableHandler.UNSUBSCRCRIBE] = subscriber
1859                this.removeOwningProperty(newValue);
1860                return true;
1861                break;
1862            default:
1863                if (Reflect.get(target, property) == newValue) {
1864                    return true;
1865                }
1866
1867                Reflect.set(target, property, newValue);
1868                this.notifyObjectPropertyHasChanged(property.toString(), newValue);
1869                return true;
1870                break;
1871        }
1872        // unreachable
1873        return false;
1874    }
1875}
1876SubscribableHandler.SUBSCRIBE = Symbol("_____subscribe__");
1877SubscribableHandler.UNSUBSCRIBE = Symbol("_____unsubscribe__");
1878class SubscribableDateHandler extends SubscribableHandler {
1879    constructor(owningProperty) {
1880        super(owningProperty);
1881    }
1882    /**
1883     * Get trap for Date type proxy
1884     * Functions that modify Date in-place are intercepted and replaced with a function
1885     * that executes the original function and notifies the handler of a change.
1886     * @param target Original Date object
1887     * @param property
1888     * @returns
1889     */
1890    get(target, property) {
1891        const dateSetFunctions = new Set(["setFullYear", "setMonth", "setDate", "setHours", "setMinutes", "setSeconds",
1892            "setMilliseconds", "setTime", "setUTCFullYear", "setUTCMonth", "setUTCDate", "setUTCHours", "setUTCMinutes",
1893            "setUTCSeconds", "setUTCMilliseconds"]);
1894        let ret = super.get(target, property);
1895        if (typeof ret === "function" && property.toString() && dateSetFunctions.has(property.toString())) {
1896            const self = this;
1897            return function () {
1898                // execute original function with given arguments
1899                let result = ret.apply(this, arguments);
1900                self.notifyObjectPropertyHasChanged(property.toString(), this);
1901                return result;
1902            }.bind(target); // bind "this" to target inside the function
1903        }
1904        else if (typeof ret === "function") {
1905            ret = ret.bind(target);
1906        }
1907        return ret;
1908    }
1909}
1910class ExtendableProxy {
1911    constructor(obj, handler) {
1912        return new Proxy(obj, handler);
1913    }
1914}
1915class ObservedObject extends ExtendableProxy {
1916    /**
1917     * To create a new ObservableObject use CreateNew function
1918     *
1919     * constructor create a new ObservableObject and subscribe its owner to propertyHasChanged
1920     * notifications
1921     * @param obj  raw Object, if obj is a ObservableOject throws an error
1922     * @param objectOwner
1923     */
1924    constructor(obj, handler, objectOwningProperty) {
1925        super(obj, handler);
1926        if (ObservedObject.IsObservedObject(obj)) {
1927            stateMgmtConsole.error("ObservableOject constructor: INTERNAL ERROR: after jsObj is observedObject already");
1928        }
1929        if (objectOwningProperty != undefined) {
1930            this[SubscribableHandler.SUBSCRIBE] = objectOwningProperty;
1931        }
1932    } // end of constructor
1933    /**
1934     * Factory function for ObservedObjects /
1935     *  wrapping of objects for proxying
1936     *
1937     * @param rawObject unproxied Object or ObservedObject
1938     * @param objOwner owner of this Object to sign uop for propertyChange
1939     *          notifications
1940     * @returns the rawObject if object is already an ObservedObject,
1941     *          otherwise the newly created ObservedObject
1942     */
1943    static createNew(rawObject, owningProperty) {
1944        if (rawObject === null || rawObject === undefined) {
1945            stateMgmtConsole.error(`ObservedObject.CreateNew, input object must not be null or undefined.`);
1946            return rawObject;
1947        }
1948        if (ObservedObject.IsObservedObject(rawObject)) {
1949            ObservedObject.addOwningProperty(rawObject, owningProperty);
1950            return rawObject;
1951        }
1952        return ObservedObject.createNewInternal(rawObject, owningProperty);
1953    }
1954    static createNewInternal(rawObject, owningProperty) {
1955        let proxiedObject = new ObservedObject(rawObject, Array.isArray(rawObject) ? new class extends SubscribableHandler {
1956            constructor(owningProperty) {
1957                super(owningProperty);
1958                // In-place array modification functions
1959                // splice is also in-place modifying function, but we need to handle separately
1960                this.inPlaceModifications = new Set(["copyWithin", "fill", "reverse", "sort"]);
1961            }
1962            get(target, property, receiver) {
1963                let ret = super.get(target, property, receiver);
1964                if (ret && typeof ret === "function") {
1965                    const self = this;
1966                    const prop = property.toString();
1967                    // prop is the function name here
1968                    if (prop == "splice") {
1969                        // 'splice' self modifies the array, returns deleted array items
1970                        // means, alike other self-modifying functions, splice does not return the array itself.
1971                        return function () {
1972                            const result = ret.apply(target, arguments);
1973                            // prop is the function name here
1974                            // and result is the function return value
1975                            // functinon modifies none or more properties
1976                            self.notifyObjectPropertyHasChanged(prop, target);
1977                            return result;
1978                        }.bind(proxiedObject);
1979                    }
1980                    if (self.inPlaceModifications.has(prop)) {
1981                        // in place modfication function result == target, the raw array modified
1982
1983                        return function () {
1984                            const result = ret.apply(target, arguments);
1985                            // 'result' is the unproxied object
1986                            // functinon modifies none or more properties
1987                            self.notifyObjectPropertyHasChanged(prop, result);
1988                            // returning the 'proxiedObject' ensures that when chain calls also 2nd function call
1989                            // operates on the proxied object.
1990                            return proxiedObject;
1991                        }.bind(proxiedObject);
1992                    }
1993                    // binding the proxiedObject ensures that modifying functions like push() operate on the
1994                    // proxied array and each array change is notified.
1995                    return ret.bind(proxiedObject);
1996                }
1997                return ret;
1998            }
1999        }(owningProperty) // SubscribableArrayHandlerAnonymous
2000            : (rawObject instanceof Date)
2001                ? new SubscribableDateHandler(owningProperty)
2002                : new SubscribableHandler(owningProperty), owningProperty);
2003        return proxiedObject;
2004    }
2005    /*
2006      Return the unproxied object 'inside' the ObservedObject / the ES6 Proxy
2007      no set observation, no notification of changes!
2008      Use with caution, do not store any references
2009    */
2010    static GetRawObject(obj) {
2011        return !ObservedObject.IsObservedObject(obj) ? obj : obj[ObservedObject.__OBSERVED_OBJECT_RAW_OBJECT];
2012    }
2013    /**
2014     *
2015     * @param obj anything
2016     * @returns true if the parameter is an Object wrpped with a ObservedObject
2017     * Note: Since ES6 Proying is transparent, 'instance of' will not work. Use
2018     * this static function instead.
2019     */
2020    static IsObservedObject(obj) {
2021        return (obj && (typeof obj === "object") && Reflect.has(obj, ObservedObject.__IS_OBSERVED_OBJECT));
2022    }
2023    /**
2024     * add a subscriber to given ObservedObject
2025     * due to the proxy nature this static method approach needs to be used instead of a member
2026     * function
2027     * @param obj
2028     * @param subscriber
2029     * @returns false if given object is not an ObservedObject
2030     */
2031    static addOwningProperty(obj, subscriber) {
2032        if (!ObservedObject.IsObservedObject(obj) || subscriber == undefined) {
2033            return false;
2034        }
2035        obj[SubscribableHandler.SUBSCRIBE] = subscriber;
2036        return true;
2037    }
2038    /**
2039     * remove a subscriber to given ObservedObject
2040     * due to the proxy nature this static method approach needs to be used instead of a member
2041     * function
2042     * @param obj
2043     * @param subscriber
2044     * @returns false if given object is not an ObservedObject
2045     */
2046    static removeOwningProperty(obj, subscriber) {
2047        if (!ObservedObject.IsObservedObject(obj)) {
2048            return false;
2049        }
2050        obj[SubscribableHandler.UNSUBSCRIBE] = subscriber;
2051        return true;
2052    }
2053    /**
2054     * Utility function for debugging the prototype chain of given Object
2055     * The given object can be any Object, it is not required to be an ObservedObject
2056     * @param object
2057     * @returns multi-line string containing info about the prototype chain
2058     * on class in class hiararchy per line
2059     */
2060    static tracePrototypeChainOfObject(object) {
2061        let proto = Object.getPrototypeOf(object);
2062        let result = "";
2063        let sepa = "";
2064        while (proto) {
2065            result += `${sepa}${ObservedObject.tracePrototype(proto)}`;
2066            proto = Object.getPrototypeOf(proto);
2067            sepa = ",\n";
2068        }
2069        return result;
2070    }
2071    /**
2072     * Utility function for debugging all functions of given Prototype.
2073     * @returns string containing containing names of all functions and members of given Prototype
2074     */
2075    static tracePrototype(proto) {
2076        if (!proto) {
2077            return "";
2078        }
2079        let result = `${proto.constructor && proto.constructor.name ? proto.constructor.name : '<no class>'}: `;
2080        let sepa = "";
2081        for (let name of Object.getOwnPropertyNames(proto)) {
2082            result += `${sepa}${name}`;
2083            sepa = ", ";
2084        }
2085        ;
2086        return result;
2087    }
2088    /**
2089     * @Observed  decorator extends the decorated class. This function returns the prototype of the decorated class
2090     * @param proto
2091     * @returns prototype of the @Observed decorated class or 'proto' parameter if not  @Observed decorated
2092     */
2093    static getPrototypeOfObservedClass(proto) {
2094        return (proto.constructor && proto.constructor.name == "ObservedClass")
2095            ? Object.getPrototypeOf(proto.constructor.prototype)
2096            : proto;
2097    }
2098}
2099ObservedObject.__IS_OBSERVED_OBJECT = Symbol("_____is_observed_object__");
2100ObservedObject.__OBSERVED_OBJECT_RAW_OBJECT = Symbol("_____raw_object__");
2101/*
2102 * Copyright (c) 2021 Huawei Device Co., Ltd.
2103 * Licensed under the Apache License, Version 2.0 (the "License");
2104 * you may not use this file except in compliance with the License.
2105 * You may obtain a copy of the License at
2106 *
2107 *     http://www.apache.org/licenses/LICENSE-2.0
2108 *
2109 * Unless required by applicable law or agreed to in writing, software
2110 * distributed under the License is distributed on an "AS IS" BASIS,
2111 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2112 * See the License for the specific language governing permissions and
2113 * limitations under the License.
2114 */
2115/*
2116   manage subscriptions to a property
2117   managing the property is left to sub
2118   classes
2119   Extended by ObservedProperty, SyncedPropertyOneWay
2120   and SyncedPropertyTwoWay
2121*/
2122class ObservedPropertyAbstract extends SubscribedAbstractProperty {
2123    constructor(subscribeMe, info) {
2124        super();
2125        this.subscribers_ = new Set();
2126        this.id_ = SubscriberManager.MakeId();
2127        SubscriberManager.Add(this);
2128        if (subscribeMe) {
2129            this.subscribers_.add(subscribeMe.id__());
2130        }
2131        if (info) {
2132            this.info_ = info;
2133        }
2134    }
2135    aboutToBeDeleted() {
2136        SubscriberManager.Delete(this.id__());
2137    }
2138    id__() {
2139        return this.id_;
2140    }
2141    info() {
2142        return this.info_;
2143    }
2144    setInfo(propName) {
2145        if (propName && propName != "") {
2146            this.info_ = propName;
2147        }
2148    }
2149    // Partial Update "*PU" classes will overwrite
2150    getUnmonitored() {
2151        return this.get();
2152    }
2153    subscribeMe(subscriber) {
2154
2155        this.subscribers_.add(subscriber.id__());
2156    }
2157    /*
2158      the inverse function of createOneWaySync or createTwoWaySync
2159    */
2160    unlinkSuscriber(subscriberId) {
2161        this.subscribers_.delete(subscriberId);
2162    }
2163    notifyHasChanged(newValue) {
2164
2165        this.subscribers_.forEach((subscribedId) => {
2166            var subscriber = SubscriberManager.Find(subscribedId);
2167            if (subscriber) {
2168                // FU code path
2169                if ('hasChanged' in subscriber) {
2170                    subscriber.hasChanged(newValue);
2171                }
2172                if ('propertyHasChanged' in subscriber) {
2173                    subscriber.propertyHasChanged(this.info_);
2174                }
2175                // PU code path, only used for ObservedPropertySimple/Object stored inside App/LocalStorage
2176                // ObservedPropertySimplePU/ObjectPU  used in all other PU cases, has its own notifyPropertyHasChangedPU()
2177                if ('syncPeerHasChanged' in subscriber) {
2178                    subscriber.syncPeerHasChanged(this);
2179                }
2180            }
2181            else {
2182                stateMgmtConsole.warn(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged: unknown subscriber ID '${subscribedId}' error!`);
2183            }
2184        });
2185    }
2186    notifyPropertyRead() {
2187
2188        this.subscribers_.forEach((subscribedId) => {
2189            var subscriber = SubscriberManager.Find(subscribedId);
2190            if (subscriber) {
2191                if ('propertyRead' in subscriber) {
2192                    subscriber.propertyRead(this.info_);
2193                }
2194            }
2195        });
2196    }
2197    /*
2198    return numebr of subscribers to this property
2199    mostly useful for unit testin
2200    */
2201    numberOfSubscrbers() {
2202        return this.subscribers_.size;
2203    }
2204    /**
2205     * provide a factory function that creates a SynchedPropertyXXXX of choice
2206     * that uses 'this' as source
2207     * @param factoryFunc
2208     * @returns
2209     */
2210    createSync(factoryFunc) {
2211        return factoryFunc(this);
2212    }
2213    /**
2214     * depreciated SDK function, not used anywhere by the framework
2215     */
2216    createTwoWaySync(subscribeMe, info) {
2217        stateMgmtConsole.warn("Using depreciated method 'createTwoWaySync'!");
2218        return this.createLink(subscribeMe, info);
2219    }
2220    /**
2221     * depreciated SDK function, not used anywhere by the framework
2222     */
2223    createOneWaySync(subscribeMe, info) {
2224        stateMgmtConsole.warn("Using depreciated method 'createOneWaySync' !");
2225        return this.createProp(subscribeMe, info);
2226    }
2227    /**
2228     * factory function for concrete 'object' or 'simple' ObservedProperty object
2229     * depending if value is Class object
2230     * or simple type (boolean | number | string)
2231     * @param value
2232     * @param owningView
2233     * @param thisPropertyName
2234     * @returns either
2235     */
2236    static CreateObservedObject(value, owningView, thisPropertyName) {
2237        return (typeof value === "object") ?
2238            new ObservedPropertyObject(value, owningView, thisPropertyName)
2239            : new ObservedPropertySimple(value, owningView, thisPropertyName);
2240    }
2241}
2242/*
2243 * Copyright (c) 2021 Huawei Device Co., Ltd.
2244 * Licensed under the Apache License, Version 2.0 (the "License");
2245 * you may not use this file except in compliance with the License.
2246 * You may obtain a copy of the License at
2247 *
2248 *     http://www.apache.org/licenses/LICENSE-2.0
2249 *
2250 * Unless required by applicable law or agreed to in writing, software
2251 * distributed under the License is distributed on an "AS IS" BASIS,
2252 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2253 * See the License for the specific language governing permissions and
2254 * limitations under the License.
2255 */
2256/**
2257 * ObservedPropertyObjectAbstract
2258 *
2259 * all definitions in this file are framework internal
2260 *
2261 * common base class of ObservedPropertyObject and
2262 * SyncedObjectPropertyTwoWay
2263 * adds the createObjectLink to the ObservedPropertyAbstract base
2264 */
2265class ObservedPropertyObjectAbstract extends ObservedPropertyAbstract {
2266    constructor(owningView, thisPropertyName) {
2267        super(owningView, thisPropertyName);
2268    }
2269}
2270/*
2271 * Copyright (c) 2021 Huawei Device Co., Ltd.
2272 * Licensed under the Apache License, Version 2.0 (the "License");
2273 * you may not use this file except in compliance with the License.
2274 * You may obtain a copy of the License at
2275 *
2276 *     http://www.apache.org/licenses/LICENSE-2.0
2277 *
2278 * Unless required by applicable law or agreed to in writing, software
2279 * distributed under the License is distributed on an "AS IS" BASIS,
2280 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2281 * See the License for the specific language governing permissions and
2282 * limitations under the License.
2283 */
2284/**
2285 *
2286 * ObservedPropertySimpleAbstract
2287 *
2288 * all definitions in this file are framework internal
2289 */
2290class ObservedPropertySimpleAbstract extends ObservedPropertyAbstract {
2291    constructor(owningView, propertyName) {
2292        super(owningView, propertyName);
2293    }
2294}
2295/*
2296 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2297 * Licensed under the Apache License, Version 2.0 (the "License");
2298 * you may not use this file except in compliance with the License.
2299 * You may obtain a copy of the License at
2300 *
2301 *     http://www.apache.org/licenses/LICENSE-2.0
2302 *
2303 * Unless required by applicable law or agreed to in writing, software
2304 * distributed under the License is distributed on an "AS IS" BASIS,
2305 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2306 * See the License for the specific language governing permissions and
2307 * limitations under the License.
2308 */
2309/**
2310 * ObservedPropertyObject
2311 *
2312 * all definitions in this file are framework internal
2313 *
2314 * class that holds an actual property value of type T
2315 * uses its base class to manage subscribers to this
2316 * property.
2317*/
2318class ObservedPropertyObject extends ObservedPropertyObjectAbstract {
2319    constructor(value, owningView, propertyName) {
2320        super(owningView, propertyName);
2321        this.setValueInternal(value);
2322    }
2323    aboutToBeDeleted(unsubscribeMe) {
2324        this.unsubscribeFromOwningProperty();
2325        if (unsubscribeMe) {
2326            this.unlinkSuscriber(unsubscribeMe.id__());
2327        }
2328        super.aboutToBeDeleted();
2329    }
2330    // notification from ObservedObject value one of its
2331    // props has chnaged. Implies the ObservedProperty has changed
2332    // Note: this function gets called when in this case:
2333    //       thisProp.aObsObj.aProp = 47  a object prop gets changed
2334    // It is NOT called when
2335    //    thisProp.aObsObj = new ClassA
2336    hasChanged(newValue) {
2337
2338        this.notifyHasChanged(this.wrappedValue_);
2339    }
2340    unsubscribeFromOwningProperty() {
2341        if (this.wrappedValue_) {
2342            if (this.wrappedValue_ instanceof SubscribaleAbstract) {
2343                this.wrappedValue_.removeOwningProperty(this);
2344            }
2345            else {
2346                ObservedObject.removeOwningProperty(this.wrappedValue_, this);
2347            }
2348        }
2349    }
2350    /*
2351      actually update this.wrappedValue_
2352      called needs to do value change check
2353      and also notify with this.aboutToChange();
2354    */
2355    setValueInternal(newValue) {
2356        if (typeof newValue !== 'object') {
2357
2358            return false;
2359        }
2360        this.unsubscribeFromOwningProperty();
2361        if (ObservedObject.IsObservedObject(newValue)) {
2362
2363            ObservedObject.addOwningProperty(newValue, this);
2364            this.wrappedValue_ = newValue;
2365        }
2366        else if (newValue instanceof SubscribaleAbstract) {
2367
2368            this.wrappedValue_ = newValue;
2369            this.wrappedValue_.addOwningProperty(this);
2370        }
2371        else {
2372
2373            this.wrappedValue_ = ObservedObject.createNew(newValue, this);
2374        }
2375        return true;
2376    }
2377    get() {
2378
2379        this.notifyPropertyRead();
2380        return this.wrappedValue_;
2381    }
2382    set(newValue) {
2383        if (this.wrappedValue_ == newValue) {
2384
2385            return;
2386        }
2387
2388        this.setValueInternal(newValue);
2389        this.notifyHasChanged(newValue);
2390    }
2391    /**
2392     * These functions are used
2393     *   LocalStorage.link  (also in partial update config)
2394     *   (FU)View.initializeConsumeinitializeConsume
2395     */
2396    createLink(subscribeOwner, linkPropName) {
2397        return new SynchedPropertyObjectTwoWay(this, subscribeOwner, linkPropName);
2398    }
2399    createProp(subscribeOwner, linkPropName) {
2400        throw new Error("Creating a 'Prop' property is unsupported for Object type property value.");
2401    }
2402}
2403/*
2404 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2405 * Licensed under the Apache License, Version 2.0 (the "License");
2406 * you may not use this file except in compliance with the License.
2407 * You may obtain a copy of the License at
2408 *
2409 *     http://www.apache.org/licenses/LICENSE-2.0
2410 *
2411 * Unless required by applicable law or agreed to in writing, software
2412 * distributed under the License is distributed on an "AS IS" BASIS,
2413 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2414 * See the License for the specific language governing permissions and
2415 * limitations under the License.
2416 */
2417/**
2418 * ObservedPropertySimple
2419 *
2420 * all definitions in this file are framework internal
2421 */
2422class ObservedPropertySimple extends ObservedPropertySimpleAbstract {
2423    constructor(value, owningView, propertyName) {
2424        super(owningView, propertyName);
2425        if (typeof value === "object") {
2426            throw new SyntaxError("ObservedPropertySimple value must not be an object");
2427        }
2428        this.setValueInternal(value);
2429    }
2430    aboutToBeDeleted(unsubscribeMe) {
2431        if (unsubscribeMe) {
2432            this.unlinkSuscriber(unsubscribeMe.id__());
2433        }
2434        super.aboutToBeDeleted();
2435    }
2436    hasChanged(newValue) {
2437
2438        this.notifyHasChanged(this.wrappedValue_);
2439    }
2440    /*
2441      actually update this.wrappedValue_
2442      called needs to do value change check
2443      and also notify with this.aboutToChange();
2444    */
2445    setValueInternal(newValue) {
2446
2447        this.wrappedValue_ = newValue;
2448    }
2449    get() {
2450
2451        this.notifyPropertyRead();
2452        return this.wrappedValue_;
2453    }
2454    set(newValue) {
2455        if (this.wrappedValue_ == newValue) {
2456
2457            return;
2458        }
2459
2460        this.setValueInternal(newValue);
2461        this.notifyHasChanged(newValue);
2462    }
2463    /**
2464   * These functions are meant for use in connection with the App Stoage and
2465   * business logic implementation.
2466   * the created Link and Prop will update when 'this' property value
2467   * changes.
2468   */
2469    createLink(subscribeOwner, linkPropName) {
2470        return ((subscribeOwner !== undefined) && ("rerender" in subscribeOwner)) ?
2471            new SynchedPropertySimpleTwoWayPU(this, subscribeOwner, linkPropName) :
2472            new SynchedPropertySimpleTwoWay(this, subscribeOwner, linkPropName);
2473    }
2474    createProp(subscribeOwner, linkPropName) {
2475        return new SynchedPropertySimpleOneWaySubscribing(this, subscribeOwner, linkPropName);
2476    }
2477}
2478/*
2479 * Copyright (c) 2021 Huawei Device Co., Ltd.
2480 * Licensed under the Apache License, Version 2.0 (the "License");
2481 * you may not use this file except in compliance with the License.
2482 * You may obtain a copy of the License at
2483 *
2484 *     http://www.apache.org/licenses/LICENSE-2.0
2485 *
2486 * Unless required by applicable law or agreed to in writing, software
2487 * distributed under the License is distributed on an "AS IS" BASIS,
2488 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2489 * See the License for the specific language governing permissions and
2490 * limitations under the License.
2491 */
2492/**
2493 * SynchedPropertyObjectTwoWay
2494 *
2495 * all definitions in this file are framework internal
2496 */
2497class SynchedPropertyObjectTwoWay extends ObservedPropertyObjectAbstract {
2498    constructor(linkSource, owningChildView, thisPropertyName) {
2499        super(owningChildView, thisPropertyName);
2500        this.changeNotificationIsOngoing_ = false;
2501        this.linkedParentProperty_ = linkSource;
2502        if (this.linkedParentProperty_) {
2503            // register to the parent property
2504            this.linkedParentProperty_.subscribeMe(this);
2505        }
2506        // register to the ObservedObject
2507        ObservedObject.addOwningProperty(this.getObject(), this);
2508    }
2509    /*
2510    like a destructor, need to call this before deleting
2511    the property.
2512    */
2513    aboutToBeDeleted() {
2514        if (this.linkedParentProperty_) {
2515            // unregister from parent of this link
2516            this.linkedParentProperty_.unlinkSuscriber(this.id__());
2517            // unregister from the ObservedObject
2518            ObservedObject.removeOwningProperty(this.getObject(), this);
2519        }
2520        super.aboutToBeDeleted();
2521    }
2522    getObject() {
2523        this.notifyPropertyRead();
2524        return (this.linkedParentProperty_ ? this.linkedParentProperty_.get() : undefined);
2525    }
2526    setObject(newValue) {
2527        if (this.linkedParentProperty_) {
2528            this.linkedParentProperty_.set(newValue);
2529        }
2530    }
2531    // this object is subscriber to ObservedObject
2532    // will call this cb function when property has changed
2533    hasChanged(newValue) {
2534        if (!this.changeNotificationIsOngoing_) {
2535
2536            this.notifyHasChanged(this.getObject());
2537        }
2538    }
2539    // get 'read through` from the ObservedProperty
2540    get() {
2541
2542        return this.getObject();
2543    }
2544    // set 'writes through` to the ObservedProperty
2545    set(newValue) {
2546        if (this.getObject() == newValue) {
2547
2548            return;
2549        }
2550
2551        ObservedObject.removeOwningProperty(this.getObject(), this);
2552        // the purpose of the changeNotificationIsOngoing_ is to avoid
2553        // circular notifications @Link -> source @State -> other but alos same @Link
2554        this.changeNotificationIsOngoing_ = true;
2555        this.setObject(newValue);
2556        ObservedObject.addOwningProperty(this.getObject(), this);
2557        this.notifyHasChanged(newValue);
2558        this.changeNotificationIsOngoing_ = false;
2559    }
2560    /**
2561   * These functions are meant for use in connection with the App Stoage and
2562   * business logic implementation.
2563   * the created Link and Prop will update when 'this' property value
2564   * changes.
2565   */
2566    createLink(subscribeOwner, linkPropName) {
2567        return new SynchedPropertyObjectTwoWay(this, subscribeOwner, linkPropName);
2568    }
2569    createProp(subscribeOwner, linkPropName) {
2570        throw new Error("Creating a 'Prop' property is unsupported for Object type property value.");
2571    }
2572}
2573/*
2574 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2575 * Licensed under the Apache License, Version 2.0 (the "License");
2576 * you may not use this file except in compliance with the License.
2577 * You may obtain a copy of the License at
2578 *
2579 *     http://www.apache.org/licenses/LICENSE-2.0
2580 *
2581 * Unless required by applicable law or agreed to in writing, software
2582 * distributed under the License is distributed on an "AS IS" BASIS,
2583 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2584 * See the License for the specific language governing permissions and
2585 * limitations under the License.
2586 */
2587/**
2588 * SynchedPropertySimpleOneWay
2589 *
2590 * all definitions in this file are framework internal
2591 */
2592class SynchedPropertySimpleOneWay extends ObservedPropertySimpleAbstract {
2593    constructor(value, subscribeMe, info) {
2594        super(subscribeMe, info);
2595        // add a test here that T is a simple type
2596        this.wrappedValue_ = value;
2597    }
2598    /*
2599      like a destructor, need to call this before deleting
2600      the property.
2601    */
2602    aboutToBeDeleted() {
2603        super.aboutToBeDeleted();
2604    }
2605    // get 'read through` from the ObservedProperty
2606    get() {
2607
2608        this.notifyPropertyRead();
2609        return this.wrappedValue_;
2610    }
2611    set(newValue) {
2612        if (this.wrappedValue_ == newValue) {
2613
2614            return;
2615        }
2616
2617        this.wrappedValue_ = newValue;
2618        this.notifyHasChanged(newValue);
2619    }
2620    /**
2621     * These functions are meant for use in connection with the App Stoage and
2622     * business logic implementation.
2623     * the created Link and Prop will update when 'this' property value
2624     * changes.
2625     */
2626    createLink(subscribeOwner, linkPropName) {
2627        throw new Error("Can not create a 'Link' from a 'Prop' property. ");
2628    }
2629    createProp(subscribeOwner, linkPropName) {
2630        throw new Error("Method not supported, create a SynchedPropertySimpleOneWaySubscribing from, where to create a Prop.");
2631    }
2632}
2633/*
2634  This exrension of SynchedPropertySimpleOneWay needs to be used for AppStorage
2635  because it needs to be notified about the source property changing
2636  ( there is no re-render process as in Views to update the wrappedValue )
2637*/
2638class SynchedPropertySimpleOneWaySubscribing extends SynchedPropertySimpleOneWay {
2639    constructor(linkedProperty, subscribeMe, info) {
2640        super(linkedProperty.get(), subscribeMe, info);
2641        this.linkedParentProperty_ = linkedProperty;
2642        this.linkedParentProperty_.subscribeMe(this);
2643    }
2644    aboutToBeDeleted() {
2645        // unregister from parent of this prop
2646        this.linkedParentProperty_.unlinkSuscriber(this.id__());
2647        super.aboutToBeDeleted();
2648    }
2649    hasChanged(newValue) {
2650
2651        this.set(newValue);
2652    }
2653    /**
2654     * These functions are meant for use in connection with the App Stoage and
2655     * business logic implementation.
2656     * the created Link and Prop will update when 'this' property value
2657     * changes.
2658     */
2659    createLink(subscribeOwner, linkPropName) {
2660        throw new Error("Can not create a 'Link' from a 'Prop' property. ");
2661    }
2662    createProp(subscribeOwner, propPropName) {
2663        return new SynchedPropertySimpleOneWaySubscribing(this, subscribeOwner, propPropName);
2664    }
2665}
2666/*
2667 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2668 * Licensed under the Apache License, Version 2.0 (the "License");
2669 * you may not use this file except in compliance with the License.
2670 * You may obtain a copy of the License at
2671 *
2672 *     http://www.apache.org/licenses/LICENSE-2.0
2673 *
2674 * Unless required by applicable law or agreed to in writing, software
2675 * distributed under the License is distributed on an "AS IS" BASIS,
2676 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2677 * See the License for the specific language governing permissions and
2678 * limitations under the License.
2679 */
2680/**
2681 * SynchedPropertySimpleTwoWay
2682 *
2683 * all definitions in this file are framework internal
2684 */
2685class SynchedPropertySimpleTwoWay extends ObservedPropertySimpleAbstract {
2686    constructor(source, owningView, owningViewPropNme) {
2687        super(owningView, owningViewPropNme);
2688        this.changeNotificationIsOngoing_ = false;
2689        this.source_ = source;
2690        this.source_.subscribeMe(this);
2691    }
2692    /*
2693    like a destructor, need to call this before deleting
2694    the property.
2695  */
2696    aboutToBeDeleted() {
2697        if (this.source_) {
2698            this.source_.unlinkSuscriber(this.id__());
2699            this.source_ = undefined;
2700        }
2701        super.aboutToBeDeleted();
2702    }
2703    // this object is subscriber to  SynchedPropertySimpleTwoWay
2704    // will call this cb function when property has changed
2705    // a set (newValue) is not done because get reads through for the source_
2706    hasChanged(newValue) {
2707        if (!this.changeNotificationIsOngoing_) {
2708
2709            this.notifyHasChanged(newValue);
2710        }
2711    }
2712    // get 'read through` from the ObservedProperty
2713    get() {
2714
2715        if (!this.source_) {
2716            stateMgmtConsole.error(`SynchedPropertySimpleTwoWay[${this.id__()}IP, '${this.info() || "unknown"}'] source_ is undefined: get value is undefined.`);
2717            return undefined;
2718        }
2719        this.notifyPropertyRead();
2720        return this.source_.get();
2721    }
2722    // set 'writes through` to the ObservedProperty
2723    set(newValue) {
2724        if (!this.source_) {
2725            stateMgmtConsole.error(`SynchedPropertySimpleTwoWay[${this.id__()}IP, '${this.info() || "unknown"}'] source_ is undefined: set '${newValue}' ignoring.`);
2726            return;
2727        }
2728        if (this.source_.get() == newValue) {
2729
2730            return;
2731        }
2732
2733        // the source_ ObservedProeprty will call: this.hasChanged(newValue);
2734        // the purpose of the changeNotificationIsOngoing_ is to avoid
2735        // circular notifications @Link -> source @State -> other but alos same @Link
2736        this.changeNotificationIsOngoing_ = true;
2737        this.source_.set(newValue);
2738        this.notifyHasChanged(newValue);
2739        this.changeNotificationIsOngoing_ = false;
2740    }
2741    /**
2742  * These functions are meant for use in connection with the App Stoage and
2743  * business logic implementation.
2744  * the created Link and Prop will update when 'this' property value
2745  * changes.
2746  */
2747    createLink(subscribeOwner, linkPropName) {
2748        return new SynchedPropertySimpleTwoWay(this, subscribeOwner, linkPropName);
2749    }
2750    createProp(subscribeOwner, propPropName) {
2751        return new SynchedPropertySimpleOneWaySubscribing(this, subscribeOwner, propPropName);
2752    }
2753}
2754/*
2755 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2756 * Licensed under the Apache License, Version 2.0 (the "License");
2757 * you may not use this file except in compliance with the License.
2758 * You may obtain a copy of the License at
2759 *
2760 *     http://www.apache.org/licenses/LICENSE-2.0
2761 *
2762 * Unless required by applicable law or agreed to in writing, software
2763 * distributed under the License is distributed on an "AS IS" BASIS,
2764 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2765 * See the License for the specific language governing permissions and
2766 * limitations under the License.
2767 */
2768/**
2769 * SynchedPropertyNesedObject
2770 *
2771 * all definitions in this file are framework internal
2772 */
2773class SynchedPropertyNesedObject extends ObservedPropertyObjectAbstract {
2774    /**
2775     * Construct a Property of a su component that links to a variable of parent view that holds an ObservedObject
2776     * example
2777     *   this.b.$a with b of type PC and a of type C, or
2778     *   this.$b[5] with this.b of type PC and array item b[5] of type C;
2779     *
2780     * @param subscribeMe
2781     * @param propName
2782     */
2783    constructor(obsObject, owningChildView, propertyName) {
2784        super(owningChildView, propertyName);
2785        this.obsObject_ = obsObject;
2786        // register to the ObservedObject
2787        ObservedObject.addOwningProperty(this.obsObject_, this);
2788    }
2789    /*
2790    like a destructor, need to call this before deleting
2791    the property.
2792    */
2793    aboutToBeDeleted() {
2794        // unregister from the ObservedObject
2795        ObservedObject.removeOwningProperty(this.obsObject_, this);
2796        super.aboutToBeDeleted();
2797    }
2798    // this object is subscriber to ObservedObject
2799    // will call this cb function when property has changed
2800    hasChanged(newValue) {
2801
2802        this.notifyHasChanged(this.obsObject_);
2803    }
2804    // get 'read through` from the ObservedProperty
2805    get() {
2806
2807        this.notifyPropertyRead();
2808        return this.obsObject_;
2809    }
2810    // set 'writes through` to the ObservedProperty
2811    set(newValue) {
2812        if (this.obsObject_ == newValue) {
2813
2814            return;
2815        }
2816
2817        // unsubscribe from the old value ObservedObject
2818        ObservedObject.removeOwningProperty(this.obsObject_, this);
2819        this.obsObject_ = newValue;
2820        // subscribe to the new value ObservedObject
2821        ObservedObject.addOwningProperty(this.obsObject_, this);
2822        // notify value change to subscribing View
2823        this.notifyHasChanged(this.obsObject_);
2824    }
2825    /**
2826   * These functions are meant for use in connection with the App Stoage and
2827   * business logic implementation.
2828   * the created Link and Prop will update when 'this' property value
2829   * changes.
2830   */
2831    createLink(subscribeOwner, linkPropName) {
2832        throw new Error("Method not supported for property linking to a nested objects.");
2833    }
2834    createProp(subscribeOwner, linkPropName) {
2835        throw new Error("Creating a 'Prop' proerty is unsuppoeted for Object type prperty value.");
2836    }
2837}
2838/*
2839 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2840 * Licensed under the Apache License, Version 2.0 (the "License");
2841 * you may not use this file except in compliance with the License.
2842 * You may obtain a copy of the License at
2843 *
2844 *     http://www.apache.org/licenses/LICENSE-2.0
2845 *
2846 * Unless required by applicable law or agreed to in writing, software
2847 * distributed under the License is distributed on an "AS IS" BASIS,
2848 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2849 * See the License for the specific language governing permissions and
2850 * limitations under the License.
2851 */
2852// Nativeview
2853// implemented in C++  for release
2854// and in utest/view_native_mock.ts for testing
2855class View extends NativeViewFullUpdate {
2856    /**
2857     * Create a View
2858     *
2859     * 1. option: top level View, specify
2860     *    - compilerAssignedUniqueChildId must specify
2861     *    - parent=undefined
2862     *    - localStorage  must provide if @LocalSTorageLink/Prop variables are used
2863     *      in this View or descendant Views.
2864     *
2865     * 2. option: not a top level View
2866     *    - compilerAssignedUniqueChildId must specify
2867     *    - parent must specify
2868     *    - localStorage do not specify, will inherit from parent View.
2869     *
2870     * @param compilerAssignedUniqueChildId Tw
2871     * @param parent
2872     * @param localStorage
2873     */
2874    constructor(compilerAssignedUniqueChildId, parent, localStorage) {
2875        super(compilerAssignedUniqueChildId, parent);
2876        this.propsUsedForRender = new Set();
2877        this.isRenderingInProgress = false;
2878        this.watchedProps = new Map();
2879        // my LocalStorge instance, shared with ancestor Views.
2880        // create a default instance on demand if none is initialized
2881        this.localStoragebackStore_ = undefined;
2882        this.id_ = SubscriberManager.MakeId();
2883        this.providedVars_ = parent ? new Map(parent.providedVars_)
2884            : new Map();
2885        this.localStoragebackStore_ = undefined;
2886        if (parent) {
2887            // this View is not a top-level View
2888
2889            this.setCardId(parent.getCardId());
2890            this.localStorage_ = parent.localStorage_;
2891        }
2892        else if (localStorage) {
2893            this.localStorage_ = localStorage;
2894
2895        }
2896        SubscriberManager.Add(this);
2897
2898    }
2899    get localStorage_() {
2900        if (!this.localStoragebackStore_) {
2901
2902            this.localStoragebackStore_ = new LocalStorage({ /* emty */});
2903        }
2904        return this.localStoragebackStore_;
2905    }
2906    set localStorage_(instance) {
2907        if (!instance) {
2908            // setting to undefined not allowed
2909            return;
2910        }
2911        if (this.localStoragebackStore_) {
2912            stateMgmtConsole.error(`${this.constructor.name} is setting LocalStorage instance twice`);
2913        }
2914        this.localStoragebackStore_ = instance;
2915    }
2916    // globally unique id, this is different from compilerAssignedUniqueChildId!
2917    id__() {
2918        return this.id_;
2919    }
2920    // temporary function, do not use, it will be removed soon!
2921    // prupsoe is to allow eDSL transpiler to fix a bug that
2922    // relies on this method
2923    id() {
2924        return this.id__();
2925    }
2926    propertyHasChanged(info) {
2927        if (info) {
2928            // need to sync container instanceId to switch instanceId in C++ side.
2929            this.syncInstanceId();
2930            if (this.propsUsedForRender.has(info)) {
2931
2932                this.markNeedUpdate();
2933            }
2934            else {
2935
2936            }
2937            let cb = this.watchedProps.get(info);
2938            if (cb) {
2939
2940                cb.call(this, info);
2941            }
2942            this.restoreInstanceId();
2943        } // if info avail.
2944    }
2945    propertyRead(info) {
2946
2947        if (info && (info != "unknown") && this.isRenderingInProgress) {
2948            this.propsUsedForRender.add(info);
2949        }
2950    }
2951    // for test purposes
2952    propertiesNeededToRender() {
2953        return this.propsUsedForRender;
2954    }
2955    aboutToRender() {
2956
2957        // reset
2958        this.propsUsedForRender = new Set();
2959        this.isRenderingInProgress = true;
2960    }
2961    aboutToContinueRender() {
2962        // do not reset
2963        this.isRenderingInProgress = true;
2964    }
2965    onRenderDone() {
2966        this.isRenderingInProgress = false;
2967
2968    }
2969    /**
2970     * Function to be called from the constructor of the sub component
2971     * to register a @Watch varibale
2972     * @param propStr name of the variable. Note from @Provide and @Consume this is
2973     *      the variable name and not the alias!
2974     * @param callback application defined member function of sub-class
2975     */
2976    declareWatch(propStr, callback) {
2977        this.watchedProps.set(propStr, callback);
2978    }
2979    /**
2980     * This View @Provide's a variable under given name
2981     * Call this function from the constructor of the sub class
2982     * @param providedPropName either the variable name or the alias defined as
2983     *        decorator param
2984     * @param store the backing store object for this variable (not the get/set variable!)
2985     */
2986    addProvidedVar(providedPropName, store) {
2987        if (this.providedVars_.has(providedPropName)) {
2988            throw new ReferenceError(`${this.constructor.name}: duplicate @Provide property with name ${providedPropName}.
2989      Property with this name is provided by one of the ancestor Views already.`);
2990        }
2991        this.providedVars_.set(providedPropName, store);
2992    }
2993    /**
2994     * Method for the sub-class to call from its constructor for resolving
2995     *       a @Consume variable and initializing its backing store
2996     *       with the yncedPropertyTwoWay<T> object created from the
2997     *       @Provide variable's backing store.
2998     * @param providedPropName the name of the @Provide'd variable.
2999     *     This is either the @Consume decortor parameter, or variable name.
3000     * @param consumeVarName the @Consume variable name (not the
3001     *            @Consume decortor parameter)
3002     * @returns initiaizing value of the @Consume backing store
3003     */
3004    initializeConsume(providedPropName, consumeVarName) {
3005        let providedVarStore = this.providedVars_.get(providedPropName);
3006        if (providedVarStore === undefined) {
3007            throw new ReferenceError(`${this.constructor.name}: missing @Provide property with name ${providedPropName}.
3008     Fail to resolve @Consume(${providedPropName}).`);
3009        }
3010        return providedVarStore.createLink(this, consumeVarName);
3011    }
3012}
3013/*
3014 * Copyright (c) 2022 Huawei Device Co., Ltd.
3015 * Licensed under the Apache License, Version 2.0 (the "License");
3016 * you may not use this file except in compliance with the License.
3017 * You may obtain a copy of the License at
3018 *
3019 *     http://www.apache.org/licenses/LICENSE-2.0
3020 *
3021 * Unless required by applicable law or agreed to in writing, software
3022 * distributed under the License is distributed on an "AS IS" BASIS,
3023 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3024 * See the License for the specific language governing permissions and
3025 * limitations under the License.
3026 */
3027/*
3028 * Copyright (c) 2022 Huawei Device Co., Ltd.
3029 * Licensed under the Apache License, Version 2.0 (the "License");
3030 * you may not use this file except in compliance with the License.
3031 * You may obtain a copy of the License at
3032 *
3033 *     http://www.apache.org/licenses/LICENSE-2.0
3034 *
3035 * Unless required by applicable law or agreed to in writing, software
3036 * distributed under the License is distributed on an "AS IS" BASIS,
3037 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3038 * See the License for the specific language governing permissions and
3039 * limitations under the License.
3040 */
3041/**
3042 * ObservedPropertyAbstractPU aka ObservedPropertyAbstract for partial update
3043 *
3044 * all definitions in this file are framework internal
3045 */
3046class ObservedPropertyAbstractPU extends ObservedPropertyAbstract {
3047    constructor(subscribingView, viewName) {
3048        super(subscribingView, viewName);
3049        this.dependentElementIds_ = new Set();
3050    }
3051    notifyPropertyRead() {
3052        stateMgmtConsole.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: \
3053        notifyPropertyRead, DO NOT USE with PU. Use notifyPropertyHasBeenReadPU`);
3054    }
3055    notifyPropertyHasBeenReadPU() {
3056
3057        this.subscribers_.forEach((subscribedId) => {
3058            var subscriber = SubscriberManager.Find(subscribedId);
3059            if (subscriber) {
3060                if ('propertyHasBeenReadPU' in subscriber) {
3061                    subscriber.propertyHasBeenReadPU(this);
3062                }
3063            }
3064        });
3065        this.recordDependentUpdate();
3066    }
3067    notifyPropertyHasChangedPU() {
3068
3069        this.subscribers_.forEach((subscribedId) => {
3070            var subscriber = SubscriberManager.Find(subscribedId);
3071            if (subscriber) {
3072                if ('viewPropertyHasChanged' in subscriber) {
3073                    subscriber.viewPropertyHasChanged(this.info_, this.dependentElementIds_);
3074                }
3075                else if ('syncPeerHasChanged' in subscriber) {
3076                    subscriber.syncPeerHasChanged(this);
3077                }
3078                else {
3079                    stateMgmtConsole.warn(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyPropertryHasChangedPU: unknown subscriber ID '${subscribedId}' error!`);
3080                }
3081            }
3082        });
3083    }
3084    markDependentElementsDirty(view) {
3085        // TODO ace-ets2bundle, framework, compilated apps need to update together
3086        // this function will be removed after a short transiition periode
3087        stateMgmtConsole.warn(`markDependentElementsDirty no longer supported. App will work ok, but
3088        please update your ace-ets2bundle and recompile your application!`);
3089    }
3090    /**
3091     * factory function for concrete 'object' or 'simple' ObservedProperty object
3092     * depending if value is Class object
3093     * or simple type (boolean | number | string)
3094     * @param value
3095     * @param owningView
3096     * @param thisPropertyName
3097     * @returns either
3098     */
3099    static CreateObservedObject(value, owningView, thisPropertyName) {
3100        return (typeof value === "object") ?
3101            new ObservedPropertyObject(value, owningView, thisPropertyName)
3102            : new ObservedPropertySimple(value, owningView, thisPropertyName);
3103    }
3104    /**
3105     * during 'get' access recording take note of the created component and its elmtId
3106     * and add this component to the list of components who are dependent on this property
3107     */
3108    recordDependentUpdate() {
3109        const elmtId = ViewStackProcessor.GetElmtIdToAccountFor();
3110        if (elmtId < 0) {
3111            // not access recording
3112            return;
3113        }
3114
3115        this.dependentElementIds_.add(elmtId);
3116    }
3117    purgeDependencyOnElmtId(rmElmtId) {
3118
3119        this.dependentElementIds_.delete(rmElmtId);
3120    }
3121    SetPropertyUnchanged() {
3122        // function to be removed
3123        // keep it here until transpiler is updated.
3124    }
3125    // FIXME check, is this used from AppStorage.
3126    // unified Appstorage, what classes to use, and the API
3127    createLink(subscribeOwner, linkPropName) {
3128        throw new Error("Can not create a AppStorage 'Link' from a @State property. ");
3129    }
3130    createProp(subscribeOwner, linkPropName) {
3131        throw new Error("Can not create a AppStorage 'Prop' from a @State property. ");
3132    }
3133    /*
3134      Below empty functions required to keep as long as this class derives from FU version
3135      ObservedPropertyAbstract. Need to overwrite these functions to do nothing for PU
3136      */
3137    notifyHasChanged(_) {
3138        stateMgmtConsole.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: \
3139          notifyHasChanged, DO NOT USE with PU. Use syncPeerHasChanged() or objectPropertyHasChangedPU()`);
3140    }
3141    hasChanged(_) {
3142        // unused for PU
3143        // need to overwrite impl of base class with empty function.
3144    }
3145    propertyHasChanged(_) {
3146        // unused for PU
3147        // need to overwrite impl of base class with empty function.
3148    }
3149    propertyRead(_) {
3150        // unused for PU
3151        // need to overwrite impl of base class with empty function.
3152    }
3153}
3154/*
3155 * Copyright (c) 2021 Huawei Device Co., Ltd.
3156 * Licensed under the Apache License, Version 2.0 (the "License");
3157 * you may not use this file except in compliance with the License.
3158 * You may obtain a copy of the License at
3159 *
3160 *     http://www.apache.org/licenses/LICENSE-2.0
3161 *
3162 * Unless required by applicable law or agreed to in writing, software
3163 * distributed under the License is distributed on an "AS IS" BASIS,
3164 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3165 * See the License for the specific language governing permissions and
3166 * limitations under the License.
3167 */
3168/**
3169 * ObservedPropertyObjectAbstractPU
3170 *
3171 * common bbase class of ObservedPropertyObjectPU and
3172 * SyncedObjectPropertyTwoWayPU
3173 * adds the createObjectLink to the ObservedPropertyAbstract base
3174 *
3175 * all definitions in this file are framework internal
3176 */
3177class ObservedPropertyObjectAbstractPU extends ObservedPropertyAbstractPU {
3178    constructor(owningView, thisPropertyName) {
3179        super(owningView, thisPropertyName);
3180    }
3181}
3182/*
3183 * Copyright (c) 2021 Huawei Device Co., Ltd.
3184 * Licensed under the Apache License, Version 2.0 (the "License");
3185 * you may not use this file except in compliance with the License.
3186 * You may obtain a copy of the License at
3187 *
3188 *     http://www.apache.org/licenses/LICENSE-2.0
3189 *
3190 * Unless required by applicable law or agreed to in writing, software
3191 * distributed under the License is distributed on an "AS IS" BASIS,
3192 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3193 * See the License for the specific language governing permissions and
3194 * limitations under the License.
3195 */
3196/**
3197 * ObservedPropertySimpleAbstractPU
3198 *
3199 * all definitions in this file are framework internal
3200 */
3201class ObservedPropertySimpleAbstractPU extends ObservedPropertyAbstractPU {
3202    constructor(owningView, propertyName) {
3203        super(owningView, propertyName);
3204    }
3205}
3206/*
3207 * Copyright (c) 2022 Huawei Device Co., Ltd.
3208 * Licensed under the Apache License, Version 2.0 (the "License");
3209 * you may not use this file except in compliance with the License.
3210 * You may obtain a copy of the License at
3211 *
3212 *     http://www.apache.org/licenses/LICENSE-2.0
3213 *
3214 * Unless required by applicable law or agreed to in writing, software
3215 * distributed under the License is distributed on an "AS IS" BASIS,
3216 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3217 * See the License for the specific language governing permissions and
3218 * limitations under the License.
3219 */
3220/**
3221 * ObservedPropertyObjectPU
3222 * implementation of @State and @Provide decorated variables of type class object
3223 *
3224 * all definitions in this file are framework internal
3225 *
3226 * class that holds an actual property value of type T
3227 * uses its base class to manage subscribers to this
3228 * property.
3229*/
3230class ObservedPropertyObjectPU extends ObservedPropertyObjectAbstractPU {
3231    constructor(value, owningView, propertyName) {
3232        super(owningView, propertyName);
3233        this.setValueInternal(value);
3234    }
3235    aboutToBeDeleted(unsubscribeMe) {
3236        this.unsubscribeFromOwningProperty();
3237        if (unsubscribeMe) {
3238            this.unlinkSuscriber(unsubscribeMe.id__());
3239        }
3240        super.aboutToBeDeleted();
3241    }
3242    /**
3243     * Called by a SynchedPropertyObjectTwoWayPU (@Link, @Consume) that uses this as sync peer when it has changed
3244     * @param eventSource
3245     */
3246    syncPeerHasChanged(eventSource) {
3247
3248        this.notifyPropertyHasChangedPU();
3249    }
3250    /**
3251     * Wraped ObservedObjectPU has changed
3252     * @param souceObject
3253     * @param changedPropertyName
3254     */
3255    objectPropertyHasChangedPU(souceObject, changedPropertyName) {
3256
3257        this.notifyPropertyHasChangedPU();
3258    }
3259    objectPropertyHasBeenReadPU(souceObject, changedPropertyName) {
3260
3261        this.notifyPropertyHasBeenReadPU();
3262    }
3263    unsubscribeFromOwningProperty() {
3264        if (this.wrappedValue_) {
3265            if (this.wrappedValue_ instanceof SubscribaleAbstract) {
3266                this.wrappedValue_.removeOwningProperty(this);
3267            }
3268            else {
3269                ObservedObject.removeOwningProperty(this.wrappedValue_, this);
3270            }
3271        }
3272    }
3273    /*
3274      actually update this.wrappedValue_
3275      called needs to do value change check
3276      and also notify with this.aboutToChange();
3277    */
3278    setValueInternal(newValue) {
3279        if (typeof newValue !== 'object') {
3280
3281            return false;
3282        }
3283        this.unsubscribeFromOwningProperty();
3284        if (ObservedObject.IsObservedObject(newValue)) {
3285
3286            ObservedObject.addOwningProperty(newValue, this);
3287            this.wrappedValue_ = newValue;
3288        }
3289        else if (newValue instanceof SubscribaleAbstract) {
3290
3291            this.wrappedValue_ = newValue;
3292            this.wrappedValue_.addOwningProperty(this);
3293        }
3294        else {
3295
3296            this.wrappedValue_ = ObservedObject.createNew(newValue, this);
3297        }
3298        return true;
3299    }
3300    get() {
3301
3302        this.notifyPropertyHasBeenReadPU();
3303        return this.wrappedValue_;
3304    }
3305    getUnmonitored() {
3306
3307        // unmonitored get access , no call to otifyPropertyRead !
3308        return this.wrappedValue_;
3309    }
3310    set(newValue) {
3311        if (this.wrappedValue_ == newValue) {
3312
3313            return;
3314        }
3315
3316        this.setValueInternal(newValue);
3317        this.notifyPropertyHasChangedPU();
3318    }
3319}
3320/*
3321 * Copyright (c) 2022 Huawei Device Co., Ltd.
3322 * Licensed under the Apache License, Version 2.0 (the "License");
3323 * you may not use this file except in compliance with the License.
3324 * You may obtain a copy of the License at
3325 *
3326 *     http://www.apache.org/licenses/LICENSE-2.0
3327 *
3328 * Unless required by applicable law or agreed to in writing, software
3329 * distributed under the License is distributed on an "AS IS" BASIS,
3330 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3331 * See the License for the specific language governing permissions and
3332 * limitations under the License.
3333 */
3334/**
3335 * ObservedPropertySimplePU
3336 * implementation of @State and @Provide decorated variables of types (T=) boolean | number | string | enum
3337 *
3338 * Holds an actual property value of type T
3339 * uses its base class to manage subscribers to this
3340 * property.
3341 *
3342 * all definitions in this file are framework internal
3343*/
3344class ObservedPropertySimplePU extends ObservedPropertySimpleAbstractPU {
3345    constructor(value, owningView, propertyName) {
3346        super(owningView, propertyName);
3347        if (typeof value === "object") {
3348            throw new SyntaxError("ObservedPropertySimple value must not be an object");
3349        }
3350        this.setValueInternal(value);
3351    }
3352    aboutToBeDeleted(unsubscribeMe) {
3353        if (unsubscribeMe) {
3354            this.unlinkSuscriber(unsubscribeMe.id__());
3355        }
3356        super.aboutToBeDeleted();
3357    }
3358    /**
3359   * Called by a @Link - SynchedPropertySimpleTwoWay that uses this as sync peer when it has changed
3360   * @param eventSource
3361   */
3362    syncPeerHasChanged(eventSource) {
3363
3364        this.notifyPropertyHasChangedPU();
3365    }
3366    /*
3367      actually update this.wrappedValue_
3368      called needs to do value change check
3369      and also notify with this.aboutToChange();
3370    */
3371    setValueInternal(newValue) {
3372
3373        this.wrappedValue_ = newValue;
3374    }
3375    getUnmonitored() {
3376
3377        // unmonitored get access , no call to otifyPropertyRead !
3378        return this.wrappedValue_;
3379    }
3380    get() {
3381
3382        this.notifyPropertyHasBeenReadPU();
3383        return this.wrappedValue_;
3384    }
3385    set(newValue) {
3386        if (this.wrappedValue_ == newValue) {
3387
3388            return;
3389        }
3390
3391        this.setValueInternal(newValue);
3392        this.notifyPropertyHasChangedPU();
3393    }
3394}
3395/*
3396 * Copyright (c) 2022 Huawei Device Co., Ltd.
3397 * Licensed under the Apache License, Version 2.0 (the "License");
3398 * you may not use this file except in compliance with the License.
3399 * You may obtain a copy of the License at
3400 *
3401 *     http://www.apache.org/licenses/LICENSE-2.0
3402 *
3403 * Unless required by applicable law or agreed to in writing, software
3404 * distributed under the License is distributed on an "AS IS" BASIS,
3405 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3406 * See the License for the specific language governing permissions and
3407 * limitations under the License.
3408 */
3409class SynchedPropertyObjectOneWayPU extends ObservedPropertyObjectAbstractPU {
3410    constructor(source, owningChildView, thisPropertyName) {
3411        super(owningChildView, thisPropertyName);
3412        if (source && (typeof (source) === "object") && ("subscribeMe" in source)) {
3413            // code path for @(Local)StorageProp, the souce is a ObservedPropertyObject in aLocalStorage)
3414            this.source_ = source;
3415            this.sourceIsOwnObject = false;
3416            // subscribe to receive value change updates from LocalStorage source property
3417            this.source_.subscribeMe(this);
3418        }
3419        else {
3420            // code path for @Prop
3421            if (!ObservedObject.IsObservedObject(source)) {
3422                stateMgmtConsole.warn(`@Prop ${this.info()}  Provided source object's class
3423           lacks @Observed class decorator. Object property changes will not be observed.`);
3424            }
3425
3426            this.source_ = new ObservedPropertyObjectPU(source, this, thisPropertyName);
3427            this.sourceIsOwnObject = true;
3428        }
3429        // deep copy source Object and wrap it
3430        this.setWrappedValue(this.source_.get());
3431
3432    }
3433    /*
3434    like a destructor, need to call this before deleting
3435    the property.
3436    */
3437    aboutToBeDeleted() {
3438        if (this.source_) {
3439            this.source_.unlinkSuscriber(this.id__());
3440            if (this.sourceIsOwnObject == true && this.source_.numberOfSubscrbers() == 0) {
3441
3442                this.source_.aboutToBeDeleted();
3443            }
3444            this.source_ = undefined;
3445        }
3446        super.aboutToBeDeleted();
3447    }
3448    syncPeerHasChanged(eventSource) {
3449        if (eventSource && this.source_ == eventSource) {
3450            // defensive programming: should always be the case!
3451
3452            const newValue = this.source_.getUnmonitored();
3453            if (typeof newValue == "object") {
3454
3455                this.setWrappedValue(newValue);
3456                this.notifyPropertyHasChangedPU();
3457            }
3458        }
3459        else {
3460            stateMgmtConsole.warn(`SynchedPropertyNesedObjectPU[${this.id__()}]: syncPeerHasChanged Unexpected situation. Ignorning event.`);
3461        }
3462    }
3463    /**
3464     * event emited by wrapped ObservedObject, when one of its property values changes
3465     * @param souceObject
3466     * @param changedPropertyName
3467     */
3468    objectPropertyHasChangedPU(souceObject, changedPropertyName) {
3469
3470        this.notifyPropertyHasChangedPU();
3471    }
3472    objectPropertyHasBeenReadPU(souceObject, changedPropertyName) {
3473
3474        this.notifyPropertyHasBeenReadPU();
3475    }
3476    getUnmonitored() {
3477
3478        // unmonitored get access , no call to notifyPropertyRead !
3479        return this.wrappedValue_;
3480    }
3481    // get 'read through` from the ObservedObject
3482    get() {
3483
3484        this.notifyPropertyHasBeenReadPU();
3485        return this.wrappedValue_;
3486    }
3487    // assignment to local variable in the form of this.aProp = <object value>
3488    // set 'writes through` to the ObservedObject
3489    set(newValue) {
3490        if (this.wrappedValue_ == newValue) {
3491
3492            return;
3493        }
3494
3495        if (!ObservedObject.IsObservedObject(newValue)) {
3496            stateMgmtConsole.warn(`@Prop ${this.info()} Set: Provided new object's class
3497         lacks @Observed class decorator. Object property changes will not be observed.`);
3498        }
3499        this.setWrappedValue(newValue);
3500        this.notifyPropertyHasChangedPU();
3501    }
3502    reset(sourceChangedValue) {
3503
3504        // if set causes an actual change, then, ObservedPropertyObject source_ will call syncPeerHasChanged
3505        this.source_.set(sourceChangedValue);
3506    }
3507    setWrappedValue(value) {
3508        let rawValue = ObservedObject.GetRawObject(value);
3509        let copy;
3510        // FIXME: Proper object deep copy missing here!
3511        if (rawValue instanceof Array) {
3512            copy = ObservedObject.createNew([...rawValue], this);
3513        }
3514        else {
3515            copy = ObservedObject.createNew(Object.assign({}, rawValue), this);
3516        }
3517        Object.setPrototypeOf(copy, Object.getPrototypeOf(rawValue));
3518        ObservedObject.addOwningProperty(this.wrappedValue_, this);
3519        this.wrappedValue_ = copy;
3520    }
3521}
3522/*
3523 * Copyright (c) 2022 Huawei Device Co., Ltd.
3524 * Licensed under the Apache License, Version 2.0 (the "License");
3525 * you may not use this file except in compliance with the License.
3526 * You may obtain a copy of the License at
3527 *
3528 *     http://www.apache.org/licenses/LICENSE-2.0
3529 *
3530 * Unless required by applicable law or agreed to in writing, software
3531 * distributed under the License is distributed on an "AS IS" BASIS,
3532 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3533 * See the License for the specific language governing permissions and
3534 * limitations under the License.
3535 */
3536/**
3537 * SynchedPropertyObjectTwoWayPU
3538 * implementation of @Link and @Consume decorated variables of type class object
3539 *
3540 * all definitions in this file are framework internal
3541 */
3542class SynchedPropertyObjectTwoWayPU extends ObservedPropertyObjectAbstractPU {
3543    constructor(linkSource, owningChildView, thisPropertyName) {
3544        super(owningChildView, thisPropertyName);
3545        this.changeNotificationIsOngoing_ = false;
3546        this.linkedParentProperty_ = linkSource;
3547        if (this.linkedParentProperty_) {
3548            // register to the parent property
3549            this.linkedParentProperty_.subscribeMe(this);
3550        }
3551        // register to the ObservedObject
3552        ObservedObject.addOwningProperty(this.linkedParentProperty_.get(), this);
3553    }
3554    /*
3555    like a destructor, need to call this before deleting
3556    the property.
3557    */
3558    aboutToBeDeleted() {
3559        // unregister from parent of this link
3560        if (this.linkedParentProperty_) {
3561            this.linkedParentProperty_.unlinkSuscriber(this.id__());
3562            // unregister from the ObservedObject
3563            ObservedObject.removeOwningProperty(this.linkedParentProperty_.getUnmonitored(), this);
3564        }
3565        super.aboutToBeDeleted();
3566    }
3567    setObject(newValue) {
3568        if (!this.linkedParentProperty_) {
3569            stateMgmtConsole.warn(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: setObject, no linked parent property.`);
3570            return;
3571        }
3572        this.linkedParentProperty_.set(newValue);
3573    }
3574    /**
3575     * Called when sync peer ObservedPropertyObject or SynchedPropertyObjectTwoWay has chnaged value
3576     * that peer can be in either parent or child component if 'this' is used for a @Link
3577     * that peer can be in either acestor or descendant component if 'this' is used for a @Consume
3578     * @param eventSource
3579     */
3580    syncPeerHasChanged(eventSource) {
3581        if (!this.changeNotificationIsOngoing_) {
3582
3583            this.notifyPropertyHasChangedPU();
3584        }
3585    }
3586    /**
3587     * called when wrapped ObservedObject has changed poperty
3588     * @param souceObject
3589     * @param changedPropertyName
3590     */
3591    objectPropertyHasChangedPU(souceObject, changedPropertyName) {
3592
3593        this.notifyPropertyHasChangedPU();
3594    }
3595    objectPropertyHasBeenReadPU(souceObject, changedPropertyName) {
3596
3597        this.notifyPropertyHasBeenReadPU();
3598    }
3599    getUnmonitored() {
3600
3601        // unmonitored get access , no call to otifyPropertyRead !
3602        return (this.linkedParentProperty_ ? this.linkedParentProperty_.getUnmonitored() : undefined);
3603    }
3604    // get 'read through` from the ObservedProperty
3605    get() {
3606
3607        this.notifyPropertyHasBeenReadPU();
3608        return this.getUnmonitored();
3609    }
3610    // set 'writes through` to the ObservedProperty
3611    set(newValue) {
3612        if (this.getUnmonitored() == newValue) {
3613
3614            return;
3615        }
3616
3617        ObservedObject.removeOwningProperty(this.getUnmonitored(), this);
3618        // avoid circular notifications @Link -> source @State -> other but also back to same @Link
3619        this.changeNotificationIsOngoing_ = true;
3620        this.setObject(newValue);
3621        ObservedObject.addOwningProperty(this.getUnmonitored(), this);
3622        this.notifyPropertyHasChangedPU();
3623        this.changeNotificationIsOngoing_ = false;
3624    }
3625}
3626/*
3627 * Copyright (c) 2022 Huawei Device Co., Ltd.
3628 * Licensed under the Apache License, Version 2.0 (the "License");
3629 * you may not use this file except in compliance with the License.
3630 * You may obtain a copy of the License at
3631 *
3632 *     http://www.apache.org/licenses/LICENSE-2.0
3633 *
3634 * Unless required by applicable law or agreed to in writing, software
3635 * distributed under the License is distributed on an "AS IS" BASIS,
3636 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3637 * See the License for the specific language governing permissions and
3638 * limitations under the License.
3639 */
3640/**
3641 * SynchedPropertySimpleOneWayPU
3642 * implementation of @Prop decorated variable of types boolean | number | string | enum
3643 *
3644 * all definitions in this file are framework internal
3645 */
3646class SynchedPropertySimpleOneWayPU extends ObservedPropertySimpleAbstractPU {
3647    constructor(source, subscribeMe, thisPropertyName) {
3648        super(subscribeMe, thisPropertyName);
3649        if (source && (typeof (source) === "object") && ("notifyHasChanged" in source) && ("subscribeMe" in source)) {
3650            // code path for @(Local)StorageProp
3651            this.source_ = source;
3652            this.sourceIsOwnObject = false;
3653            // subscribe to receive value chnage updates from LocalStorge source property
3654            this.source_.subscribeMe(this);
3655        }
3656        else {
3657            // code path for @Prop
3658            this.source_ = new ObservedPropertySimplePU(source, this, thisPropertyName);
3659            this.sourceIsOwnObject = true;
3660        }
3661        // use own backing store for value to avoid
3662        // value changes to be propagated back to source
3663        this.wrappedValue_ = this.source_.getUnmonitored();
3664    }
3665    /*
3666      like a destructor, need to call this before deleting
3667      the property.
3668    */
3669    aboutToBeDeleted() {
3670        if (this.source_) {
3671            this.source_.unlinkSuscriber(this.id__());
3672            if (this.sourceIsOwnObject == true && this.source_.numberOfSubscrbers() == 0) {
3673
3674                this.source_.aboutToBeDeleted();
3675            }
3676            this.source_ = undefined;
3677            this.sourceIsOwnObject == false;
3678        }
3679        super.aboutToBeDeleted();
3680    }
3681    syncPeerHasChanged(eventSource) {
3682        if (eventSource && (eventSource == this.source_)) {
3683            // defensive, should always be the case
3684
3685            this.sourceHasChanged(eventSource);
3686        }
3687    }
3688    sourceHasChanged(eventSource) {
3689
3690        this.wrappedValue_ = eventSource.getUnmonitored();
3691        this.notifyPropertyHasChangedPU();
3692    }
3693    getUnmonitored() {
3694
3695        // unmonitored get access , no call to otifyPropertyRead !
3696        return this.wrappedValue_;
3697    }
3698    // get 'read through` from the ObservedProperty
3699    get() {
3700
3701        this.notifyPropertyHasBeenReadPU();
3702        return this.wrappedValue_;
3703    }
3704    set(newValue) {
3705        if (this.wrappedValue_ == newValue) {
3706
3707            return;
3708        }
3709
3710        this.wrappedValue_ = newValue;
3711        this.notifyPropertyHasChangedPU();
3712    }
3713    reset(sourceChangedValue) {
3714
3715        // if set causes an actual change, then, ObservedPropertySimple source_ will call hasChanged
3716        this.source_.set(sourceChangedValue);
3717    }
3718}
3719/*
3720 * Copyright (c) 2022 Huawei Device Co., Ltd.
3721 * Licensed under the Apache License, Version 2.0 (the "License");
3722 * you may not use this file except in compliance with the License.
3723 * You may obtain a copy of the License at
3724 *
3725 *     http://www.apache.org/licenses/LICENSE-2.0
3726 *
3727 * Unless required by applicable law or agreed to in writing, software
3728 * distributed under the License is distributed on an "AS IS" BASIS,
3729 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3730 * See the License for the specific language governing permissions and
3731 * limitations under the License.
3732 */
3733/**
3734 * SynchedPropertySimpleTwoWayPU
3735 * implementation of @Link and @Consume decorated variables of types boolean | number | string | enum
3736 *
3737 * all definitions in this file are framework internal
3738 */
3739class SynchedPropertySimpleTwoWayPU extends ObservedPropertySimpleAbstractPU {
3740    constructor(source, owningView, owningViewPropNme) {
3741        super(owningView, owningViewPropNme);
3742        this.changeNotificationIsOngoing_ = false;
3743        this.source_ = source;
3744        this.source_.subscribeMe(this);
3745    }
3746    /*
3747    like a destructor, need to call this before deleting
3748    the property.
3749  */
3750    aboutToBeDeleted() {
3751        if (this.source_) {
3752            this.source_.unlinkSuscriber(this.id__());
3753            this.source_ = undefined;
3754        }
3755        super.aboutToBeDeleted();
3756    }
3757    /**
3758     * Called when sync peer ObservedPropertySimple or SynchedPropertySimpletTwoWay has chnaged value
3759     * that peer can be in either parent or child component if 'this' is used for a @Link
3760     * that peer can be in either acestor or descendant component if 'this' is used for a @Consume
3761     * @param eventSource
3762     */
3763    syncPeerHasChanged(eventSource) {
3764        if (!this.changeNotificationIsOngoing_) {
3765
3766            this.notifyPropertyHasChangedPU();
3767        }
3768    }
3769    getUnmonitored() {
3770
3771        return (this.source_ ? this.source_.getUnmonitored() : undefined);
3772    }
3773    // get 'read through` from the ObservedProperty
3774    get() {
3775
3776        this.notifyPropertyHasBeenReadPU();
3777        return this.getUnmonitored();
3778    }
3779    // set 'writes through` to the ObservedProperty
3780    set(newValue) {
3781        if (!this.source_) {
3782
3783            return;
3784        }
3785        if (this.source_.get() == newValue) {
3786
3787            return;
3788        }
3789
3790        // avoid circular notifications @Link -> source @State -> other but also to same @Link
3791        this.changeNotificationIsOngoing_ = true;
3792        // the source_ ObservedProeprty will call: this.hasChanged(newValue);
3793        this.source_.set(newValue);
3794        this.notifyPropertyHasChangedPU();
3795        this.changeNotificationIsOngoing_ = false;
3796    }
3797}
3798/*
3799 * Copyright (c) 2022 Huawei Device Co., Ltd.
3800 * Licensed under the Apache License, Version 2.0 (the "License");
3801 * you may not use this file except in compliance with the License.
3802 * You may obtain a copy of the License at
3803 *
3804 *     http://www.apache.org/licenses/LICENSE-2.0
3805 *
3806 * Unless required by applicable law or agreed to in writing, software
3807 * distributed under the License is distributed on an "AS IS" BASIS,
3808 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3809 * See the License for the specific language governing permissions and
3810 * limitations under the License.
3811 */
3812/**
3813 * SynchedPropertyNesedObjectPU
3814 * implementation of @ObjectLink decorated variables
3815 *
3816 * all definitions in this file are framework internal
3817 *
3818 */
3819class SynchedPropertyNesedObjectPU extends ObservedPropertyObjectAbstractPU {
3820    /**
3821     * Construct a Property of a su component that links to a variable of parent view that holds an ObservedObject
3822     * example
3823     *   this.b.$a with b of type PC and a of type C, or
3824     *   this.$b[5] with this.b of type PC and array item b[5] of type C;
3825     *
3826     * @param subscribeMe
3827     * @param propName
3828     */
3829    constructor(obsObject, owningChildView, propertyName) {
3830        super(owningChildView, propertyName);
3831        this.obsObject_ = obsObject;
3832        // register to the ObservedObject
3833        ObservedObject.addOwningProperty(this.obsObject_, this);
3834    }
3835    /*
3836    like a destructor, need to call this before deleting
3837    the property.
3838    */
3839    aboutToBeDeleted() {
3840        // unregister from the ObservedObject
3841        ObservedObject.removeOwningProperty(this.obsObject_, this);
3842        super.aboutToBeDeleted();
3843    }
3844    objectPropertyHasChangedPU(eventSource, changedPropertyName) {
3845
3846        this.notifyPropertyHasChangedPU();
3847    }
3848    objectPropertyHasBeenReadPU(souceObject, changedPropertyName) {
3849
3850        this.notifyPropertyHasBeenReadPU();
3851    }
3852    getUnmonitored() {
3853        //
3854        // unmonitored get access , no call to otifyPropertyRead !
3855        return this.obsObject_;
3856    }
3857    // get 'read through` from the ObservedProperty
3858    get() {
3859
3860        // this.notifyPropertyRead();
3861        this.notifyPropertyHasBeenReadPU();
3862        return this.obsObject_;
3863    }
3864    // set 'writes through` to the ObservedProperty
3865    set(newValue) {
3866        if (this.obsObject_ == newValue) {
3867
3868            return;
3869        }
3870
3871        // unsubscribe from the old value ObservedObject
3872        ObservedObject.removeOwningProperty(this.obsObject_, this);
3873        this.obsObject_ = newValue;
3874        // subscribe to the new value ObservedObject
3875        ObservedObject.addOwningProperty(this.obsObject_, this);
3876        // notify value change to subscribing View
3877        this.notifyPropertyHasChangedPU();
3878    }
3879}
3880/*
3881 * Copyright (c) 2022 Huawei Device Co., Ltd.
3882 * Licensed under the Apache License, Version 2.0 (the "License");
3883 * you may not use this file except in compliance with the License.
3884 * You may obtain a copy of the License at
3885 *
3886 *     http://www.apache.org/licenses/LICENSE-2.0
3887 *
3888 * Unless required by applicable law or agreed to in writing, software
3889 * distributed under the License is distributed on an "AS IS" BASIS,
3890 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3891 * See the License for the specific language governing permissions and
3892 * limitations under the License.
3893 *
3894 *  * ViewPU - View for Partial Update
3895 *
3896* all definitions in this file are framework internal
3897*/
3898// denotes a missing elemntId, this is the case during initial render
3899const UndefinedElmtId = -1;
3900// Nativeview
3901// implemented in C++  for release
3902// and in utest/view_native_mock.ts for testing
3903class ViewPU extends NativeViewPartialUpdate {
3904    /**
3905     * Create a View
3906     *
3907     * 1. option: top level View, specify
3908     *    - compilerAssignedUniqueChildId must specify
3909     *    - parent=undefined
3910     *    - localStorage  must provide if @LocalSTorageLink/Prop variables are used
3911     *      in this View or descendant Views.
3912     *
3913     * 2. option: not a top level View
3914     *    - compilerAssignedUniqueChildId must specify
3915     *    - parent must specify
3916     *    - localStorage do not specify, will inherit from parent View.
3917     *
3918    */
3919    constructor(parent, localStorage, elmtId = -1) {
3920        super();
3921        this.parent_ = undefined;
3922        this.childrenWeakrefMap_ = new Map();
3923        this.watchedProps = new Map();
3924        // Set of dependent elmtIds that need partial update
3925        // during next re-render
3926        this.dirtDescendantElementIds_ = new Set();
3927        // registry of update functions
3928        // the key is the elementId of the Component/Element that's the result of this function
3929        this.updateFuncByElmtId = new Map();
3930        // my LocalStorge instance, shared with ancestor Views.
3931        // create a default instance on demand if none is initialized
3932        this.localStoragebackStore_ = undefined;
3933        // if set use the elmtId also as the ViewPU object's subscribable id.
3934        // these matching is requiremrnt for updateChildViewById(elmtId) being able to
3935        // find the child ViewPU object by given elmtId
3936        this.id_ = elmtId == -1 ? SubscriberManager.MakeId() : elmtId;
3937        this.providedVars_ = parent ? new Map(parent.providedVars_)
3938            : new Map();
3939        this.localStoragebackStore_ = undefined;
3940        if (parent) {
3941            // this View is not a top-level View
3942
3943            this.setCardId(parent.getCardId());
3944            this.localStorage_ = parent.localStorage_;
3945            parent.addChild(this);
3946        }
3947        else if (localStorage) {
3948            this.localStorage_ = localStorage;
3949
3950        }
3951        SubscriberManager.Add(this);
3952
3953    }
3954    get localStorage_() {
3955        if (!this.localStoragebackStore_) {
3956
3957            this.localStoragebackStore_ = new LocalStorage({ /* emty */});
3958        }
3959        return this.localStoragebackStore_;
3960    }
3961    set localStorage_(instance) {
3962        if (!instance) {
3963            // setting to undefined not allowed
3964            return;
3965        }
3966        if (this.localStoragebackStore_) {
3967            stateMgmtConsole.error(`${this.constructor.name} is setting LocalStorage instance twice`);
3968        }
3969        this.localStoragebackStore_ = instance;
3970    }
3971    // globally unique id, this is different from compilerAssignedUniqueChildId!
3972    id__() {
3973        return this.id_;
3974    }
3975    // super class will call this function from
3976    // its aboutToBeDeleted implementation
3977    aboutToBeDeletedInternal() {
3978        // When a custom component is deleted, need to notify the C++ side to clean the corresponding deletion cache Map,
3979        // because after the deletion, can no longer clean the RemoveIds cache on the C++ side through the
3980        // updateDirtyElements function.
3981        let removedElmtIds = [];
3982        this.updateFuncByElmtId.forEach((value, key) => {
3983            this.purgeVariableDependenciesOnElmtId(key);
3984            removedElmtIds.push(key);
3985        });
3986        this.deletedElmtIdsHaveBeenPurged(removedElmtIds);
3987        this.updateFuncByElmtId.clear();
3988        this.watchedProps.clear();
3989        this.providedVars_.clear();
3990        if (this.parent_) {
3991            this.parent_.removeChild(this);
3992        }
3993    }
3994    setParent(parent) {
3995        if (this.parent_ && parent) {
3996            stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).setChild: changing parent to '${parent.constructor.name}', id ${parent.id__()} (unsafe operation)`);
3997        }
3998        this.parent_ = parent;
3999    }
4000    /**
4001     * add given child and set 'this' as its parent
4002     * @param child child to add
4003     * @returns returns false if child with given child's id already exists
4004     *
4005     * framework internal function
4006     * Note: Use of WeakRef ensures child and parent do not generate a cycle dependency.
4007     * The add. Set<ids> is required to reliably tell what children still exist.
4008     */
4009    addChild(child) {
4010        if (this.childrenWeakrefMap_.has(child.id__())) {
4011            stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).addChild '${child.constructor.name}' id already exists ${child.id__()} !`);
4012            return false;
4013        }
4014        this.childrenWeakrefMap_.set(child.id__(), new WeakRef(child));
4015        child.setParent(this);
4016        return true;
4017    }
4018    /**
4019     * remove given child and remove 'this' as its parent
4020     * @param child child to add
4021     * @returns returns false if child with given child's id does not exist
4022     */
4023    removeChild(child) {
4024        const hasBeenDeleted = this.childrenWeakrefMap_.delete(child.id__());
4025        if (!hasBeenDeleted) {
4026            stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).removeChild '${child.constructor.name}', child id ${child.id__()} not known!`);
4027        }
4028        else {
4029            child.setParent(undefined);
4030        }
4031        return hasBeenDeleted;
4032    }
4033    /**
4034     * Retrieve child by given id
4035     * @param id
4036     * @returns child if in map and weak ref can still be downreferenced
4037     */
4038    getChildById(id) {
4039        const childWeakRef = this.childrenWeakrefMap_.get(id);
4040        return childWeakRef ? childWeakRef.deref() : undefined;
4041    }
4042    updateStateVars(params) {
4043        stateMgmtConsole.warn("ViewPU.updateStateVars unimplemented. Pls upgrade to latest eDSL transpiler version.");
4044    }
4045    initialRenderView() {
4046        this.initialRender();
4047    }
4048    UpdateElement(elmtId) {
4049        // do not process an Element that has been marked to be deleted
4050        const updateFunc = this.updateFuncByElmtId.get(elmtId);
4051        if ((updateFunc == undefined) || (typeof updateFunc !== "function")) {
4052            stateMgmtConsole.error(`${this.constructor.name}[${this.id__()}]: update function of ElementId ${elmtId} not found, internal error!`);
4053        }
4054        else {
4055
4056            updateFunc(elmtId, /* isFirstRender */ false);
4057            // continue in native JSView
4058            // Finish the Update in JSView::JsFinishUpdateFunc
4059            // this function appends no longer used elmtIds (as recrded by VSP) to the given allRmElmtIds array
4060            this.finishUpdateFunc(elmtId);
4061
4062        }
4063    }
4064    /**
4065     * force a complete rerender / update by executing all update functions
4066     * exec a regular rerender first
4067     *
4068     * @param deep recurse all children as well
4069     *
4070     * framework internal functions, apps must not call
4071     */
4072    forceCompleteRerender(deep = false) {
4073        stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).forceCompleteRerender - start.`);
4074        // request list of all (gloabbly) deleted elmtIds;
4075        let deletedElmtIds = [];
4076        this.getDeletedElemtIds(deletedElmtIds);
4077        // see which elmtIds are managed by this View
4078        // and clean up all book keeping for them
4079        this.purgeDeletedElmtIds(deletedElmtIds);
4080        Array.from(this.updateFuncByElmtId.keys()).sort(ViewPU.compareNumber).forEach(elmtId => this.UpdateElement(elmtId));
4081        if (deep) {
4082            this.childrenWeakrefMap_.forEach((weakRefChild) => {
4083                const child = weakRefChild.deref();
4084                if (child) {
4085                    child.forceCompleteRerender(true);
4086                }
4087            });
4088        }
4089        stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).forceCompleteRerender - end`);
4090    }
4091    /**
4092     * force a complete rerender / update on specific node by executing update function.
4093     *
4094     * @param elmtId which node needs to update.
4095     *
4096     * framework internal functions, apps must not call
4097     */
4098    forceRerenderNode(elmtId) {
4099        // request list of all (gloabbly) deleted elmtIds;
4100        let deletedElmtIds = [];
4101        this.getDeletedElemtIds(deletedElmtIds);
4102        // see which elmtIds are managed by this View
4103        // and clean up all book keeping for them
4104        this.purgeDeletedElmtIds(deletedElmtIds);
4105        this.UpdateElement(elmtId);
4106        // remove elemtId from dirtDescendantElementIds.
4107        this.dirtDescendantElementIds_.delete(elmtId);
4108    }
4109    updateStateVarsOfChildByElmtId(elmtId, params) {
4110
4111        if (elmtId < 0) {
4112            stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).updateChildViewById(${elmtId}) - invalid elmtId - internal error!`);
4113            return;
4114        }
4115        let child = this.getChildById(elmtId);
4116        if (!child) {
4117            stateMgmtConsole.warn(`ViewPU('${this.constructor.name}', ${this.id__()}).updateChildViewById(${elmtId}) - no child with this elmtId - internal error!`);
4118            return;
4119        }
4120        child.updateStateVars(params);
4121
4122    }
4123    // implements IMultiPropertiesChangeSubscriber
4124    viewPropertyHasChanged(varName, dependentElmtIds) {
4125        stateMgmtTrace.scopedTrace(() => {
4126
4127            this.syncInstanceId();
4128            if (dependentElmtIds.size && !this.isFirstRender()) {
4129                if (!this.dirtDescendantElementIds_.size) {
4130                    // mark Composedelement dirty when first elmtIds are added
4131                    // do not need to do this every time
4132                    this.markNeedUpdate();
4133                }
4134
4135                const union = new Set([...this.dirtDescendantElementIds_, ...dependentElmtIds]);
4136                this.dirtDescendantElementIds_ = union;
4137
4138            }
4139            let cb = this.watchedProps.get(varName);
4140            if (cb) {
4141
4142                cb.call(this, varName);
4143            }
4144            this.restoreInstanceId();
4145        }, "ViewPU.viewPropertyHasChanged", this.constructor.name, varName, dependentElmtIds.size);
4146    }
4147    /**
4148     * Function to be called from the constructor of the sub component
4149     * to register a @Watch varibale
4150     * @param propStr name of the variable. Note from @Provide and @Consume this is
4151     *      the variable name and not the alias!
4152     * @param callback application defined member function of sub-class
4153     */
4154    declareWatch(propStr, callback) {
4155        this.watchedProps.set(propStr, callback);
4156    }
4157    /**
4158     * This View @Provide's a variable under given name
4159     * Call this function from the constructor of the sub class
4160     * @param providedPropName either the variable name or the alias defined as
4161     *        decorator param
4162     * @param store the backing store object for this variable (not the get/set variable!)
4163     */
4164    addProvidedVar(providedPropName, store) {
4165        if (this.providedVars_.has(providedPropName)) {
4166            throw new ReferenceError(`${this.constructor.name}: duplicate @Provide property with name ${providedPropName}.
4167      Property with this name is provided by one of the ancestor Views already.`);
4168        }
4169        this.providedVars_.set(providedPropName, store);
4170    }
4171    /**
4172     * Method for the sub-class to call from its constructor for resolving
4173     *       a @Consume variable and initializing its backing store
4174     *       with the yncedPropertyTwoWay<T> object created from the
4175     *       @Provide variable's backing store.
4176     * @param providedPropName the name of the @Provide'd variable.
4177     *     This is either the @Consume decortor parameter, or variable name.
4178     * @param consumeVarName the @Consume variable name (not the
4179     *            @Consume decortor parameter)
4180     * @returns initiaizing value of the @Consume backing store
4181     */
4182    initializeConsume(providedPropName, consumeVarName) {
4183        let providedVarStore = this.providedVars_.get(providedPropName);
4184        if (providedVarStore === undefined) {
4185            throw new ReferenceError(`${this.constructor.name}: missing @Provide property with name ${providedPropName}.
4186     Fail to resolve @Consume(${providedPropName}).`);
4187        }
4188        return providedVarStore.createSync((source) => (source instanceof ObservedPropertySimple)
4189            ? new SynchedPropertySimpleTwoWayPU(source, this, consumeVarName)
4190            : new SynchedPropertyObjectTwoWayPU(source, this, consumeVarName));
4191    }
4192    /**
4193     * given the elmtid of a child or child of child within this custom component
4194     * remember this component needs a partial update
4195     * @param elmtId
4196     */
4197    markElemenDirtyById(elmtId) {
4198        // TODO ace-ets2bundle, framework, compilated apps need to update together
4199        // this function will be removed after a short transiition periode
4200        stateMgmtConsole.error(`markElemenDirtyById no longer supported.
4201        Please update your ace-ets2bundle and recompile your application!`);
4202    }
4203    /**
4204     * For each recorded dirty Element in this custom component
4205     * run its update function
4206     *
4207     */
4208    updateDirtyElements() {
4209        do {
4210
4211            // request list of all (gloabbly) deleteelmtIds;
4212            let deletedElmtIds = [];
4213            this.getDeletedElemtIds(deletedElmtIds);
4214            // see which elmtIds are managed by this View
4215            // and clean up all book keeping for them
4216            this.purgeDeletedElmtIds(deletedElmtIds);
4217            // process all elmtIds marked as needing update in ascending order.
4218            // ascending order ensures parent nodes will be updated before their children
4219            // prior cleanup ensure no already deleted Elements have their update func executed
4220            Array.from(this.dirtDescendantElementIds_).sort(ViewPU.compareNumber).forEach(elmtId => {
4221                this.UpdateElement(elmtId);
4222                this.dirtDescendantElementIds_.delete(elmtId);
4223            });
4224        } while (this.dirtDescendantElementIds_.size);
4225    }
4226    //  given a list elementIds removes these from state variables dependency list and from elmtId -> updateFunc map
4227    purgeDeletedElmtIds(rmElmtIds) {
4228        if (rmElmtIds.length == 0) {
4229            return;
4230        }
4231
4232        // rmElmtIds is the array of ElemntIds that
4233        let removedElmtIds = [];
4234        rmElmtIds.forEach((elmtId) => {
4235            // remove entry from Map elmtId -> update function
4236            if (this.updateFuncByElmtId.delete(elmtId)) {
4237                // for each state var, remove dependent elmtId (if present)
4238                // purgeVariableDependenciesOnElmtId needs to be generated by the compiler
4239                this.purgeVariableDependenciesOnElmtId(elmtId);
4240                // keep track of elmtId that has been de-registered
4241                removedElmtIds.push(elmtId);
4242            }
4243        });
4244        this.deletedElmtIdsHaveBeenPurged(removedElmtIds);
4245
4246
4247    }
4248    // the current executed update function
4249    observeComponentCreation(compilerAssignedUpdateFunc) {
4250        const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent();
4251
4252        compilerAssignedUpdateFunc(elmtId, /* is first rneder */ true);
4253        this.updateFuncByElmtId.set(elmtId, compilerAssignedUpdateFunc);
4254
4255    }
4256    // performs the update on a branch within if() { branch } else if (..) { branch } else { branch }
4257    ifElseBranchUpdateFunction(branchId, branchfunc) {
4258        const oldBranchid = If.getBranchId();
4259        if (branchId == oldBranchid) {
4260
4261            return;
4262        }
4263        If.branchId(branchId);
4264        branchfunc();
4265    }
4266    /**
4267     Partial updates for ForEach.
4268     * @param elmtId ID of element.
4269     * @param itemArray Array of items for use of itemGenFunc.
4270     * @param itemGenFunc Item generation function to generate new elements. If index parameter is
4271     *                    given set itemGenFuncUsesIndex to true.
4272     * @param idGenFunc   ID generation function to generate unique ID for each element. If index parameter is
4273     *                    given set idGenFuncUsesIndex to true.
4274     * @param itemGenFuncUsesIndex itemGenFunc optional index parameter is given or not.
4275     * @param idGenFuncUsesIndex idGenFunc optional index parameter is given or not.
4276     */
4277    forEachUpdateFunction(elmtId, itemArray, itemGenFunc, idGenFunc, itemGenFuncUsesIndex = false, idGenFuncUsesIndex = false) {
4278
4279        if (itemArray === null || itemArray === undefined) {
4280            stateMgmtConsole.error(`ForEach input array is null or undefined error.`);
4281            return;
4282        }
4283        if (itemGenFunc === null || itemGenFunc === undefined) {
4284            stateMgmtConsole.error(`Error: Item generation function not defined in forEach function.`);
4285            return;
4286        }
4287        if (idGenFunc === undefined) {
4288
4289            idGenFuncUsesIndex = true;
4290            // catch possible error caused by Stringify and re-throw an Error with a meaningful (!) error message
4291            idGenFunc = (item, index) => {
4292                try {
4293                    return `${index}__${JSON.stringify(item)}`;
4294                }
4295                catch (e) {
4296                    throw new Error(`${this.constructor.name}[${this.id__()}]: ForEach id ${elmtId}: use of default id generator function not possble on provided data structure. Need to specify id generator function (ForEach 3rd parameter).`);
4297                }
4298            };
4299        }
4300        let diffIndexArray = []; // New indexes compared to old one.
4301        let newIdArray = [];
4302        let idDuplicates = [];
4303        const arr = itemArray; // just to trigger a 'get' onto the array
4304        // ID gen is with index.
4305        if (idGenFuncUsesIndex) {
4306
4307            // Create array of new ids.
4308            arr.forEach((item, indx) => {
4309                newIdArray.push(idGenFunc(item, indx));
4310            });
4311        }
4312        else {
4313            // Create array of new ids.
4314
4315            arr.forEach((item, index) => {
4316                newIdArray.push(`${itemGenFuncUsesIndex ? index + '_' : ''}` + idGenFunc(item));
4317            });
4318        }
4319        // Set new array on C++ side.
4320        // C++ returns array of indexes of newly added array items.
4321        // these are indexes in new child list.
4322        ForEach.setIdArray(elmtId, newIdArray, diffIndexArray, idDuplicates);
4323        // Its error if there are duplicate IDs.
4324        if (idDuplicates.length > 0) {
4325            idDuplicates.forEach((indx) => {
4326                stateMgmtConsole.error(`Error: ${newIdArray[indx]} generated for ${indx}${indx < 4 ? indx == 2 ? "nd" : "rd" : "th"} array item ${arr[indx]}.`);
4327            });
4328            stateMgmtConsole.error(`Ids generated by the ForEach id gen function must be unique, error.`);
4329        }
4330
4331        // Item gen is with index.
4332
4333        // Create new elements if any.
4334        diffIndexArray.forEach((indx) => {
4335            ForEach.createNewChildStart(newIdArray[indx], this);
4336            if (itemGenFuncUsesIndex) {
4337                itemGenFunc(arr[indx], indx);
4338            }
4339            else {
4340                itemGenFunc(arr[indx]);
4341            }
4342            ForEach.createNewChildFinish(newIdArray[indx], this);
4343        });
4344    }
4345    /**
4346       * CreateStorageLink and CreateStorageLinkPU are used by the implementation of @StorageLink and
4347       * @LocalStotrageLink in full update and partial update solution respectively.
4348       * These are not part of the public AppStorage API , apps should not use.
4349       * @param storagePropName - key in LocalStorage
4350       * @param defaultValue - value to use when creating a new prop in the LocalStotage
4351       * @param owningView - the View/ViewPU owning the @StorageLink/@LocalStorageLink variable
4352       * @param viewVariableName -  @StorageLink/@LocalStorageLink variable name
4353       * @returns SynchedPropertySimple/ObjectTwoWay/PU
4354       */
4355    createStorageLink(storagePropName, defaultValue, viewVariableName) {
4356        return AppStorage.__CreateSync(storagePropName, defaultValue, (source) => (source === undefined)
4357            ? undefined
4358            : (source instanceof ObservedPropertySimple)
4359                ? new SynchedPropertySimpleTwoWayPU(source, this, viewVariableName)
4360                : new SynchedPropertyObjectTwoWayPU(source, this, viewVariableName));
4361    }
4362    createStorageProp(storagePropName, defaultValue, viewVariableName) {
4363        return AppStorage.__CreateSync(storagePropName, defaultValue, (source) => (source === undefined)
4364            ? undefined
4365            : (source instanceof ObservedPropertySimple)
4366                ? new SynchedPropertySimpleOneWayPU(source, this, viewVariableName)
4367                : new SynchedPropertyObjectOneWayPU(source, this, viewVariableName));
4368    }
4369    createLocalStorageLink(storagePropName, defaultValue, viewVariableName) {
4370        return this.localStorage_.__createSync(storagePropName, defaultValue, (source) => (source === undefined)
4371            ? undefined
4372            : (source instanceof ObservedPropertySimple)
4373                ? new SynchedPropertySimpleTwoWayPU(source, this, viewVariableName)
4374                : new SynchedPropertyObjectTwoWayPU(source, this, viewVariableName));
4375    }
4376    createLocalStorageProp(storagePropName, defaultValue, viewVariableName) {
4377        return this.localStorage_.__createSync(storagePropName, defaultValue, (source) => (source === undefined)
4378            ? undefined
4379            : (source instanceof ObservedPropertySimple)
4380                ? new SynchedPropertySimpleOneWayPU(source, this, viewVariableName)
4381                : new SynchedPropertyObjectOneWayPU(source, this, viewVariableName));
4382    }
4383}
4384// Array.sort() converts array items to string to compare them, sigh!
4385ViewPU.compareNumber = (a, b) => {
4386    return (a < b) ? -1 : (a > b) ? 1 : 0;
4387};
4388/*
4389 * Copyright (c) 2022 Huawei Device Co., Ltd.
4390 * Licensed under the Apache License, Version 2.0 (the "License");
4391 * you may not use this file except in compliance with the License.
4392 * You may obtain a copy of the License at
4393 *
4394 *     http://www.apache.org/licenses/LICENSE-2.0
4395 *
4396 * Unless required by applicable law or agreed to in writing, software
4397 * distributed under the License is distributed on an "AS IS" BASIS,
4398 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4399 * See the License for the specific language governing permissions and
4400 * limitations under the License.
4401 *
4402 *  * ViewPU - View for Partial Update
4403 *
4404* all definitions in this file are framework internal
4405*/
4406/**
4407    given parameters for calling a @Builder function
4408    this function wraps the Object of type T inside a ES6 Proxy.
4409    Each param, i.e. Object property is either a function or a value.
4410    If it is a function the function can either return a value of expected
4411    parameter type or an ObservedPropertyabstract<T> where T is the exected
4412    parameter type. The latter is the case when passing a state variable by
4413    reference.
4414
4415    Two purposes:
4416    1 - @Builder function boxy accesses params a '$$.paramA'
4417        However paramA can be a function, so to obtain the value the
4418        access would need to be '$$.param()' The proxy executes
4419        the function and return s the result
4420    2 - said function returns to ObservedPropertyAbstract backing store of
4421        a calling @Component state variable (whenever the state var is
4422        provided to the @Builder function). For this case the proxy can provide
4423        - the value by executing paramA() to return the ObservedPropertyAbstract
4424          and further (monitored!) get() to read its value
4425        - when requested to return '__param1' it returns the ObservedPropertyAbstract
4426          object. The scenario is to use to init a @Link source.
4427  */
4428function makeBuilderParameterProxy(builderName, source) {
4429    return new Proxy(source, {
4430        set(target, prop, val) {
4431            throw Error(`@Builder '${builderName}': Invalid attempt to set(write to) parameter '${prop.toString()}' error!`);
4432        },
4433        get(target, prop) {
4434            const prop1 = prop.toString().trim().startsWith("__")
4435                ? prop.toString().trim().substring(2)
4436                : prop.toString().trim();
4437
4438            if (!(typeof target === "object") && (prop1 in target)) {
4439                throw Error(`@Builder '${builderName}': '${prop1}' used but not a function parameter error!`);
4440            }
4441            const value = target[prop1];
4442            if (typeof value !== "function") {
4443
4444                return value;
4445            }
4446            const funcRet = value();
4447            if ((typeof funcRet === "object") && ('get' in funcRet)) {
4448                if (prop1 !== prop) {
4449
4450                    return funcRet;
4451                }
4452                else {
4453
4454                    const result = funcRet.get();
4455
4456                    return result;
4457                }
4458            }
4459
4460            return funcRet;
4461        } // get
4462    }); // new Proxy
4463}
4464/*
4465 * Copyright (c) 2021 Huawei Device Co., Ltd.
4466 * Licensed under the Apache License, Version 2.0 (the "License");
4467 * you may not use this file except in compliance with the License.
4468 * You may obtain a copy of the License at
4469 *
4470 *     http://www.apache.org/licenses/LICENSE-2.0
4471 *
4472 * Unless required by applicable law or agreed to in writing, software
4473 * distributed under the License is distributed on an "AS IS" BASIS,
4474 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4475 * See the License for the specific language governing permissions and
4476 * limitations under the License.
4477 */
4478
4479PersistentStorage.ConfigureBackend(new Storage());
4480Environment.ConfigureBackend(new EnvironmentSetting());
4481
4482