Nativescript: fromObjectRecursive from 'data/observable" mutates source

Created on 12 Jun 2017  路  7Comments  路  Source: NativeScript/NativeScript

fromObjectRecursive internally calls addPropertiesFromObject with recursive=true. The internal function mutates the source (see source[prop]= )without any sort of advertising it in the docs.

function addPropertiesFromObject(observable: ObservableFromObject, source: any, recursive: boolean = false) {
    let isRecursive = recursive;
    for (let prop in source) {
        if (source.hasOwnProperty(prop)) {
            if (isRecursive) {
                if (!Array.isArray(source[prop]) && source[prop] && typeof source[prop] === 'object' && !(source[prop] instanceof Observable)) {
                    source[prop] = fromObjectRecursive(source[prop]);
                }
            }
            defineNewProperty(observable, prop);
            observable.set(prop, source[prop]);
        }
    }
}

help wanted medium

All 7 comments

@sserdyuk the difference in fromObject and fromObjectRecursive is that the second one iterates recursively your object and creates Observable objects from any nested Object type properties.
e.g.

var obj = {
    "id": 1,
     "info" : {
        "name" : "John"
    }
}

let observableObject = fromObject(obj);
console.dir(observableObject);
// will print
/*
JS: === dump(): dumping members ===
JS: {
JS:     "_observers": {},
JS:     "_map": {
JS:         "id": 1,
JS:         "info": {
JS:             "name": "John"
JS:         }
JS:     },
JS:     "id": 1,
JS:     "info": "#CR:[object Object]"
JS: }
JS: === dump(): dumping function and properties names ===
*/
let observableObjectRecursive= fromObjectRecursive(obj);
console.dir(observableObjectRecursive);
// will print
JS: === dump(): dumping members ===
JS: {
JS:     "_observers": {},
JS:     "_map": {
JS:         "id": 1,
JS:         "info": {
JS:             "_observers": {},
JS:             "_map": {
JS:                 "name": "John"
JS:             },
JS:             "name": "John"
JS:         }
JS:     },
JS:     "id": 1,
JS:     "info": "#CR:[object Object]"
JS: }
JS: === dump(): dumping function and properties names ===

@NickIliev It's not a question, it's a bug report. Two bugs: it mutates the source object, and having been called twice, it internally returns same object. Both behaviors are unexpected.

    const source = { a: 1, b: { c: 2 } };
    console.log('source.b before is POJO');
    console.dir(source.b);
    const obs1 = fromObjectRecursive(source);
    console.log('source.b after is ObservableFromObject');
    console.dir(source.b);
    const obs2 = fromObjectRecursive(source);
    console.log('obs2 b.c is : '+ obs2.get('b').get('c'));
    obs1.get('b').set('c', 3);
    console.log('obs2 b.c: should be 2 but is '+ obs2.get('b').get('c'));

JS: source.b before is POJO
JS: === dump(): dumping members ===
JS: {
JS:     "c": 2
JS: }
JS: === dump(): dumping function and properties names ===
JS: === dump(): finished ===
JS: source.b after is ObservableFromObject
JS: === dump(): dumping members ===
JS: {
JS:     "_observers": {},
JS:     "_map": {
JS:         "c": 2
JS:     },
JS:     "c": 2
JS: }
JS: === dump(): dumping function and properties names ===
JS: constructor()
JS: get()
JS: set()
JS: on()
JS: off()
JS: addEventListener()
JS: removeEventListener()
JS: notify()
JS: notifyPropertyChange()
JS: hasListeners()
JS: _createPropertyChangeData()
JS: _emit()
JS: _getEventList()
JS: _indexOfListener()
JS: === dump(): finished ===
JS: obs2 b.c is : 2
JS: obs2 b.c: should be 2 but is 3

Yes it is a bug. It obviously mutates both the source and the observable arguments. IMO it should always do full clones.

@sserdyuk thank you for clarifying the issue - confirming this as a bug.
Steps to reproduce: use this test application.

Fix included in https://github.com/NativeScript/NativeScript/tree/hhristov/nested-frames - will be included in the upcoming release

Confirming as resolved with tns-core-modules@next and this demo applicaiton

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings