seamless-immutable
Advanced tools
Comparing version 1.2.0 to 1.3.0
{ | ||
"name": "seamless-immutable", | ||
"main": "seamless-immutable.js", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"homepage": "https://github.com/rtfeldman/seamless-immutable", | ||
@@ -6,0 +6,0 @@ "authors": [ |
{ | ||
"name": "seamless-immutable", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Immutable data structures for JavaScript which are backwards-compatible with normal JS Arrays and Objects.", | ||
@@ -11,2 +11,3 @@ "main": "seamless-immutable.js", | ||
"jscheck": "0.2.0", | ||
"jshint": "2.5.8", | ||
"lodash": "2.4.1", | ||
@@ -21,6 +22,7 @@ "mocha": "2.0.1", | ||
"test-watch": "mocha --watch test/*.spec.js", | ||
"jshint": "jshint seamless-immutable.js", | ||
"coverage": "export ISTANBUL_REPORTERS=text-summary,html,lcov && rm -rf tmp/ && rm -rf html-report/ && istanbul instrument test/ -o tmp/ && mocha --reporter mocha-istanbul tmp/*.spec.js && echo Open html-report/index.html to view results as HTML.", | ||
"zuul": "zuul -- test/*.spec.js", | ||
"zuul-local": "zuul --local -- test/*.spec.js", | ||
"travis-test": "npm test && npm run zuul && npm run coveralls", | ||
"travis-test": "npm run jshint && npm test && npm run zuul && npm run coveralls", | ||
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" | ||
@@ -40,3 +42,8 @@ }, | ||
}, | ||
"jshintConfig": { | ||
"newcap": false, | ||
"validthis": true, | ||
"proto": true | ||
}, | ||
"homepage": "https://github.com/rtfeldman/seamless-immutable" | ||
} |
@@ -80,3 +80,3 @@ (function(){ | ||
return Immutable(currentMethod.apply(obj, arguments)); | ||
}) | ||
}); | ||
} | ||
@@ -97,3 +97,3 @@ | ||
for(var i = 0, length = array.length; i < length; i++) { | ||
array[i] = Immutable(array[i]) | ||
array[i] = Immutable(array[i]); | ||
} | ||
@@ -132,3 +132,3 @@ | ||
return makeImmutableArray(result); | ||
}; | ||
} | ||
@@ -163,13 +163,13 @@ /** | ||
function asMutableArray(opts) { | ||
var result = [] | ||
var result = [], i, length; | ||
if(opts && opts['deep']) { | ||
for(var i = 0, length = this.length; i < length; i++) { | ||
if(opts && opts.deep) { | ||
for(i = 0, length = this.length; i < length; i++) { | ||
result.push( asDeepMutable(this[i]) ); | ||
} | ||
} else { | ||
for(var i = 0, length = this.length; i < length; i++) { | ||
for(i = 0, length = this.length; i < length; i++) { | ||
result.push(this[i]); | ||
} | ||
}; | ||
} | ||
@@ -190,3 +190,3 @@ return result; | ||
if (typeof iterator !== "function") { | ||
iterator = function(value) { return value }; | ||
iterator = function(value) { return value; }; | ||
} | ||
@@ -208,6 +208,12 @@ | ||
function asDeepMutable(obj) { | ||
if( !obj || !obj.hasOwnProperty(immutabilityTag) ) { return obj }; | ||
if( !obj || !obj.hasOwnProperty(immutabilityTag) ) { return obj; } | ||
return obj.asMutable({deep: true}); | ||
} | ||
function quickCopy(src, dest) { | ||
for (var key in src) { dest[key] = src[key]; } | ||
return dest; | ||
} | ||
/** | ||
@@ -226,13 +232,28 @@ * Returns an Immutable Object containing the properties and values of both | ||
var receivedArray = arg instanceof Array | ||
var anyChanges = false, | ||
result = quickCopy(this, {}), // A shallow clone of this object. | ||
receivedArray = (arg instanceof Array), | ||
key; | ||
// Start by shallowly cloning this object. | ||
var result = {}; | ||
// Use the given key to extract a value from the given object, then place | ||
// that value in the result object under the same key. If that resulted | ||
// in a change from this object's value at that key, set anyChanges = true. | ||
function addToResult(currentObj, otherObj, key) { | ||
var immutableValue = Immutable(otherObj[key]); | ||
for (var key in this) { result[key] = Immutable(this[key]); } | ||
anyChanges = anyChanges || | ||
(!currentObj.hasOwnProperty(key) || | ||
((immutableValue !== currentObj[key]) && | ||
// Avoid false positives due to (NaN !== NaN) evaluating to true | ||
(immutableValue === immutableValue))); | ||
result[key] = immutableValue; | ||
} | ||
// Achieve prioritization by overriding previous values that get in the way. | ||
if (!receivedArray && arguments.length === 1) { | ||
// The most common use case: just merge one object into the existing one. | ||
for (var key in arg) { result[key] = Immutable(arg[key]); } | ||
for (key in arg) { | ||
addToResult(this, arg, key); | ||
} | ||
} else { | ||
@@ -249,24 +270,30 @@ // We also accept either an Array or multiple arguments. | ||
for (var key in other) { result[key] = Immutable(other[key]); } | ||
for (key in other) { | ||
addToResult(this, other, key); | ||
} | ||
} | ||
} | ||
return makeImmutableObject(result); | ||
}; | ||
if (anyChanges) { | ||
return makeImmutableObject(result); | ||
} else { | ||
return this; | ||
} | ||
} | ||
function asMutableObject(opts) { | ||
var result = {}; | ||
var result = {}, key; | ||
if(opts && opts['deep']) { | ||
for (var key in this) { | ||
if(opts && opts.deep) { | ||
for (key in this) { | ||
result[key] = asDeepMutable(this[key]); | ||
} | ||
} else { | ||
for (var key in this) { | ||
for (key in this) { | ||
result[key] = this[key]; | ||
} | ||
}; | ||
} | ||
return result; | ||
}; | ||
} | ||
@@ -273,0 +300,0 @@ // Finalizes an object with immutable methods, freezes it, and returns it. |
@@ -95,3 +95,3 @@ var Immutable = require("../../seamless-immutable.js"); | ||
_.each(mutable, function (value, key) { | ||
assert(result.hasOwnProperty(key)); | ||
assert(result.hasOwnProperty(key), "Result " + JSON.stringify(result) + " did not have property " + key); | ||
}); | ||
@@ -112,2 +112,23 @@ }); | ||
it("does nothing when passed a merge that will result in no changes", function() { | ||
checkMultiple(function(immutable, mutables, runMerge) { | ||
// Make sure all the changes will be no-ops. | ||
_.each(mutables, function(mutable, index) { | ||
_.each(mutable, function (value, key) { | ||
// If the immutable one has this key, use the same value. | ||
// Otherwise, delete the key. | ||
if (immutable.hasOwnProperty(key)) { | ||
mutable[key] = immutable[key]; | ||
} else { | ||
delete mutable[key]; | ||
} | ||
}); | ||
}); | ||
var result = runMerge(); | ||
assert.strictEqual(result, immutable); | ||
}); | ||
}); | ||
it("returns a deeply Immutable Object", function() { | ||
@@ -131,2 +152,9 @@ checkMultiple(function(immutable, mutables, runMerge) { | ||
it("does nothing when passed a canned merge that will result in no changes", function() { | ||
var expected = Immutable({all: "your base", are: {belong: "to us"}}); | ||
var actual = expected.merge({all: "your base"}); // Should result in a no-op. | ||
assert.strictEqual(expected, actual, JSON.stringify(expected) + " did not equal " + JSON.stringify(actual)); | ||
}); | ||
it("is a no-op when passed nothing", function() { | ||
@@ -133,0 +161,0 @@ check(100, [TestUtils.ComplexObjectSpecifier()], function(obj) { |
69947
1099
10