Skip to content

Commit

Permalink
base.setPropertyValue, do not allow to rewrite the array object, assi…
Browse files Browse the repository at this point in the history
…gn the value manually:

surveyjs#596
  • Loading branch information
andrewtelnov committed Aug 28, 2017
1 parent f5ce741 commit c744ef1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
21 changes: 18 additions & 3 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export class Base {
}

private propertyHash = {};
private arrayOnPush = {};
protected isLoadingFromJsonValue: boolean = false;
public onPropertyChanged: Event<(sender: Base, options: any) => any, any> = new Event<(sender: Base, options: any) => any, any>();
/**
Expand Down Expand Up @@ -131,9 +132,15 @@ export class Base {
*/
public setPropertyValue(name: string, val: any) {
var oldValue = this.propertyHash[name];
this.propertyHash[name] = val;
if(!this.isTwoValueEquals(oldValue, val)) {
this.propertyValueChanged(name, oldValue, val);
if(oldValue && Array.isArray(oldValue)) {
if(this.isTwoValueEquals(oldValue, val)) return;
this.setArray(oldValue, val, this.arrayOnPush[name]);
this.propertyValueChanged(name, oldValue, oldValue);
} else {
this.propertyHash[name] = val;
if(!this.isTwoValueEquals(oldValue, val)) {
this.propertyValueChanged(name, oldValue, val);
}
}
}
protected propertyValueChanged(name: string, oldValue: any, newValue: any) {
Expand All @@ -143,6 +150,7 @@ export class Base {
protected createNewArray(name: string, onPush: any = null, onRemove: any = null): Array<any> {
var newArray = new Array<any>();
this.propertyHash[name] = newArray;
this.arrayOnPush[name] = onPush;
var self = this;
newArray.push = function (value): number {
var result = Array.prototype.push.call(newArray, value);
Expand Down Expand Up @@ -182,6 +190,13 @@ export class Base {

return newArray;
}
protected setArray(src: any[], dest: any[], onPush: any) {
src.length = 0;
for(var i = 0; i < dest.length; i ++) {
Array.prototype.push.call(src, dest[i]);
if(onPush) onPush(src[i]);
}
}
protected isTwoValueEquals(x: any, y: any): boolean {
if (x === y) return true;
if (!(x instanceof Object) || !(y instanceof Object)) return false;
Expand Down
28 changes: 24 additions & 4 deletions tests/basetests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class BaseTester extends Base {
super();
var self = this;
this.createNewArray("items",
function(newItem){newItem.owner = self;},
function(newItem){newItem.isNew = true;},
function(deletedItem){deletedItem.isDeleted = true;});
}
public get value1(): number { return this.getPropertyValue("value1"); }
Expand Down Expand Up @@ -144,15 +144,15 @@ QUnit.test("Base array propety value, push/splice/pop", function (assert) {
});
base.items.push({value: 1});
assert.equal(base.items.length, 1, "There is one item");
assert.equal(base.items[0].owner, base, "Owner property is set to base")
assert.equal(base.items[0].isNew, true, "isNew property is set")
assert.equal(counter, 1, "event called one time");
assert.equal(propertyName, "items", "items has been changed");
var item = base.items[0];
base.items.splice(0, 1, {value: 2}, {value: 3});
assert.equal(base.items.length, 2, "There are two items");
assert.equal(item.isDeleted, true, "First Item is deleted")
assert.equal(base.items[0].owner, base, "Item1, Owner property is set to base")
assert.equal(base.items[0].owner, base, "Item2, Owner property is set to base")
assert.equal(base.items[0].isNew, true, "Item1, isNew property is set")
assert.equal(base.items[1].isNew, true, "Item2, isNew property is set")
assert.equal(counter, 2, "event called two times");
assert.equal(propertyName, "items", "items has been changed");

Expand All @@ -164,3 +164,23 @@ QUnit.test("Base array propety value, push/splice/pop", function (assert) {
assert.equal(counter, 4, "event called 4 times, pop is called two times");
assert.equal(propertyName, "items", "items has been changed");
});
QUnit.test("Base array propety value, set value", function (assert) {
var base = new BaseTester();
var counter = 0;
var propertyName;
base.onPropertyChanged.add(function (sender, options) {
counter ++;
propertyName = options.name;
});
base.setPropertyValue("items", [{value1: 1}, {value2: 2}]);
assert.equal(base.items.length, 2, "There are two items");
assert.equal(base.items[0].isNew, true, "first item, isNew property is set")
assert.equal(base.items[1].isNew, true, "second item, isNew property is set")
assert.equal(counter, 1, "event called one time");
assert.equal(propertyName, "items", "items has been changed");

base.items.push({value: 3});
assert.equal(base.items.length, 3, "There are 3 items");
assert.equal(base.items[2].isNew, true, "The third item, isNew property is set")
assert.equal(counter, 2, "event called two time");
});

0 comments on commit c744ef1

Please sign in to comment.