Bug 1142515: add utils to compare simple objects to support Loop context in rooms. r=Standard8

This commit is contained in:
Mike de Boer 2015-05-07 11:38:54 +02:00
Родитель 8e66196893
Коммит 7acc550f67
2 изменённых файлов: 166 добавлений и 1 удалений

Просмотреть файл

@ -553,6 +553,71 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
return result; return result;
} }
/**
* Get the difference after comparing two different objects. It compares property
* names and their respective values if necessary.
* This function does _not_ recurse into object values to keep this functions'
* complexity predictable to O(2).
*
* @param {Object} a Object number 1, the comparator.
* @param {Object} b Object number 2, the comparison.
* @return {Object} The diff output, which is itself an object structured as:
* {
* updated: [prop1, prop6],
* added: [prop2],
* removed: [prop3]
* }
*/
function objectDiff(a, b) {
var propsA = a ? Object.getOwnPropertyNames(a) : [];
var propsB = b ? Object.getOwnPropertyNames(b) : [];
var diff = {
updated: [],
added: [],
removed: []
};
var prop;
for (var i = 0, lA = propsA.length; i < lA; ++i) {
prop = propsA[i];
if (propsB.indexOf(prop) == -1) {
diff.removed.push(prop);
} else if (a[prop] !== b[prop]) {
diff.updated.push(prop);
}
}
for (var j = 0, lB = propsB.length; j < lB; ++j) {
prop = propsB[j];
if (propsA.indexOf(prop) == -1) {
diff.added.push(prop);
}
}
return diff;
}
/**
* When comparing two object, you sometimes want to ignore falsy values when
* they're not persisted on the server, for example.
* This function removes all the empty/ falsy properties from the target object.
*
* @param {Object} obj Target object to strip the falsy properties from
* @return {Object}
*/
function stripFalsyValues(obj) {
var props = Object.getOwnPropertyNames(obj);
var prop;
for (var i = props.length; i >= 0; --i) {
prop = props[i];
// If the value of the object property evaluates to |false|, delete it.
if (!obj[prop]) {
delete obj[prop];
}
}
return obj;
}
this.utils = { this.utils = {
CALL_TYPES: CALL_TYPES, CALL_TYPES: CALL_TYPES,
FAILURE_DETAILS: FAILURE_DETAILS, FAILURE_DETAILS: FAILURE_DETAILS,
@ -576,6 +641,8 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
atob: atob, atob: atob,
btoa: btoa, btoa: btoa,
strToUint8Array: strToUint8Array, strToUint8Array: strToUint8Array,
Uint8ArrayToStr: Uint8ArrayToStr Uint8ArrayToStr: Uint8ArrayToStr,
objectDiff: objectDiff,
stripFalsyValues: stripFalsyValues
}; };
}).call(inChrome ? this : loop.shared); }).call(inChrome ? this : loop.shared);

Просмотреть файл

@ -318,4 +318,102 @@ describe("loop.shared.utils", function() {
expect(result).eql({ major: Infinity, minor: 0 }); expect(result).eql({ major: Infinity, minor: 0 });
}); });
}); });
describe("#objectDiff", function() {
var a, b, diff;
afterEach(function() {
a = b = diff = null;
});
it("should find object property additions", function() {
a = {
prop1: null
};
b = {
prop1: null,
prop2: null
};
diff = sharedUtils.objectDiff(a, b);
expect(diff.updated).to.eql([]);
expect(diff.removed).to.eql([]);
expect(diff.added).to.eql(["prop2"]);
});
it("should find object property value changes", function() {
a = {
prop1: null
};
b = {
prop1: "null"
};
diff = sharedUtils.objectDiff(a, b);
expect(diff.updated).to.eql(["prop1"]);
expect(diff.removed).to.eql([]);
expect(diff.added).to.eql([]);
});
it("should find object property removals", function() {
a = {
prop1: null
};
b = {};
diff = sharedUtils.objectDiff(a, b);
expect(diff.updated).to.eql([]);
expect(diff.removed).to.eql(["prop1"]);
expect(diff.added).to.eql([]);
});
it("should report a mix of removed, added and updated properties", function() {
a = {
prop1: null,
prop2: null
};
b = {
prop1: "null",
prop3: null
};
diff = sharedUtils.objectDiff(a, b);
expect(diff.updated).to.eql(["prop1"]);
expect(diff.removed).to.eql(["prop2"]);
expect(diff.added).to.eql(["prop3"]);
});
});
describe("#stripFalsyValues", function() {
var obj;
afterEach(function() {
obj = null;
});
it("should strip falsy object property values", function() {
obj = {
prop1: null,
prop2: false,
prop3: undefined,
prop4: void 0,
prop5: "",
prop6: 0
};
sharedUtils.stripFalsyValues(obj);
expect(obj).to.eql({});
});
it("should keep non-falsy values", function() {
obj = {
prop1: "null",
prop2: null,
prop3: true
};
sharedUtils.stripFalsyValues(obj);
expect(obj).to.eql({ prop1: "null", prop3: true });
});
});
}); });