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