clone
Advanced tools
Comparing version 1.0.1 to 1.0.2
70
clone.js
@@ -0,5 +1,4 @@ | ||
var clone = (function() { | ||
'use strict'; | ||
var clone = (function(global) { | ||
/** | ||
@@ -23,3 +22,2 @@ * Clones (copies) an Object using deep copying. | ||
*/ | ||
function clone(parent, circular, depth, prototype) { | ||
@@ -61,8 +59,8 @@ var filter; | ||
if (isArray(parent)) { | ||
if (clone.__isArray(parent)) { | ||
child = []; | ||
} else if (isRegExp(parent)) { | ||
child = new RegExp(parent.source, clone.getRegExpFlags(parent)); | ||
} else if (clone.__isRegExp(parent)) { | ||
child = new RegExp(parent.source, __getRegExpFlags(parent)); | ||
if (parent.lastIndex) child.lastIndex = parent.lastIndex; | ||
} else if (isDate(parent)) { | ||
} else if (clone.__isDate(parent)) { | ||
child = new Date(parent.getTime()); | ||
@@ -99,3 +97,3 @@ } else if (useBuffer && Buffer.isBuffer(parent)) { | ||
} | ||
if (attrs && attrs.set == null) { | ||
@@ -120,3 +118,3 @@ continue; | ||
*/ | ||
clone.clonePrototype = function(parent) { | ||
clone.clonePrototype = function clonePrototype(parent) { | ||
if (parent === null) | ||
@@ -130,38 +128,38 @@ return null; | ||
function getRegExpFlags(re) { | ||
var flags = ''; | ||
re.global && (flags += 'g'); | ||
re.ignoreCase && (flags += 'i'); | ||
re.multiline && (flags += 'm'); | ||
return flags; | ||
} | ||
// private utility functions | ||
function objectToString(o) { | ||
function __objToStr(o) { | ||
return Object.prototype.toString.call(o); | ||
} | ||
}; | ||
clone.__objToStr = __objToStr; | ||
function isDate(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object Date]'; | ||
} | ||
function __isDate(o) { | ||
return typeof o === 'object' && __objToStr(o) === '[object Date]'; | ||
}; | ||
clone.__isDate = __isDate; | ||
function isArray(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object Array]'; | ||
} | ||
function __isArray(o) { | ||
return typeof o === 'object' && __objToStr(o) === '[object Array]'; | ||
}; | ||
clone.__isArray = __isArray; | ||
function isRegExp(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object RegExp]'; | ||
} | ||
function __isRegExp(o) { | ||
return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; | ||
}; | ||
clone.__isRegExp = __isRegExp; | ||
if (global.TESTING) clone.getRegExpFlags = getRegExpFlags; | ||
if (global.TESTING) clone.objectToString = objectToString; | ||
if (global.TESTING) clone.isDate = isDate; | ||
if (global.TESTING) clone.isArray = isArray; | ||
if (global.TESTING) clone.isRegExp = isRegExp; | ||
function __getRegExpFlags(re) { | ||
var flags = ''; | ||
if (re.global) flags += 'g'; | ||
if (re.ignoreCase) flags += 'i'; | ||
if (re.multiline) flags += 'm'; | ||
return flags; | ||
}; | ||
clone.__getRegExpFlags = __getRegExpFlags; | ||
return clone; | ||
})(); | ||
})( typeof(global) === 'object' ? global : | ||
typeof(window) === 'object' ? window : this); | ||
if (module && module.exports) | ||
if (typeof module === 'object' && module.exports) { | ||
module.exports = clone; | ||
} |
@@ -11,3 +11,3 @@ { | ||
], | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"repository": { | ||
@@ -42,7 +42,6 @@ "type": "git", | ||
"engines": { | ||
"node": "*" | ||
"node": ">=0.8" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"underscore": "*", | ||
"nodeunit": "~0.9.0" | ||
@@ -49,0 +48,0 @@ }, |
228
test.js
@@ -1,48 +0,48 @@ | ||
if(module.parent === null) { | ||
console.log('Run this test file with nodeunit:'); | ||
console.log('$ nodeunit test.js'); | ||
} | ||
if (typeof(global) === 'object') global.TESTING = true; | ||
var clone = require('./'); | ||
var _ = require('underscore'); | ||
function inspect(obj) { | ||
seen = []; | ||
return JSON.stringify(obj, function(key, val) { | ||
return JSON.stringify(obj, function (key, val) { | ||
if (val != null && typeof val == "object") { | ||
if (seen.indexOf(val) >= 0) return '[cyclic]' | ||
seen.push(val) | ||
if (seen.indexOf(val) >= 0) { | ||
return '[cyclic]'; | ||
} | ||
seen.push(val); | ||
} | ||
return val | ||
return val; | ||
}); | ||
} | ||
// Creates a new VM in node, or a iframe in a browser to run the script. | ||
// Creates a new VM in node, or an iframe in a browser in order to run the | ||
// script | ||
function apartContext(context, script, callback) { | ||
var vm = require('vm'); | ||
if (vm) { | ||
var ctx = vm.createContext({ctx: context}); | ||
var ctx = vm.createContext({ ctx: context }); | ||
callback(vm.runInContext(script, ctx)); | ||
} | ||
else if (document && document.createElement) { | ||
} else if (document && document.createElement) { | ||
var iframe = document.createElement('iframe'); | ||
iframe.style.display = 'none'; | ||
document.body.appendChild(iframe); | ||
var myCtxId = 'tmpCtx' + Math.random(); | ||
window[myCtxId] = context; | ||
iframe.src = 'test-apart-ctx.html?'+myCtxId+'&'+encodeURIComponent(script); | ||
iframe.onload = function(){ | ||
try { callback(iframe.contentWindow.results) } | ||
catch(e) { | ||
alert('Apart Context iFrame data collection fail.\n'+e); throw e | ||
iframe.src = 'test-apart-ctx.html?' + myCtxId + '&' + encodeURIComponent(script); | ||
iframe.onload = function() { | ||
try { | ||
callback(iframe.contentWindow.results); | ||
} catch (e) { | ||
throw e; | ||
} | ||
}; | ||
} else { | ||
console.log('WARNING: cant create an apart context (vm.createContext or iframe).'); | ||
console.log('WARNING: cannot create an apart context.'); | ||
} | ||
} | ||
exports["clone string"] = function(test) { | ||
exports["clone string"] = function (test) { | ||
test.expect(2); // how many tests? | ||
@@ -58,3 +58,3 @@ | ||
exports["clone number"] = function(test) { | ||
exports["clone number"] = function (test) { | ||
test.expect(5); // how many tests? | ||
@@ -76,3 +76,3 @@ | ||
exports["clone date"] = function(test) { | ||
exports["clone date"] = function (test) { | ||
test.expect(3); // how many tests? | ||
@@ -89,4 +89,4 @@ | ||
exports["clone object"] = function(test) { | ||
test.expect(2); // how many tests? | ||
exports["clone object"] = function (test) { | ||
test.expect(1); // how many tests? | ||
@@ -96,3 +96,2 @@ var a = { foo: { bar: "baz" } }; | ||
test.ok(_(a).isEqual(b), "underscore equal"); | ||
test.deepEqual(b, a); | ||
@@ -103,4 +102,4 @@ | ||
exports["clone array"] = function(test) { | ||
test.expect(3); // how many tests? | ||
exports["clone array"] = function (test) { | ||
test.expect(2); // how many tests? | ||
@@ -113,3 +112,2 @@ var a = [ | ||
test.ok(_(a).isEqual(b), "underscore equal"); | ||
test.ok(b instanceof Array); | ||
@@ -121,4 +119,6 @@ test.deepEqual(b, a); | ||
exports["clone buffer"] = function(test) { | ||
if (typeof Buffer == 'undefined') return test.done(); | ||
exports["clone buffer"] = function (test) { | ||
if (typeof Buffer == 'undefined') { | ||
return test.done(); | ||
} | ||
@@ -135,3 +135,3 @@ test.expect(1); | ||
exports["clone regexp"] = function(test) { | ||
exports["clone regexp"] = function (test) { | ||
test.expect(5); | ||
@@ -141,3 +141,2 @@ | ||
var b = clone(a); | ||
test.deepEqual(b, a); | ||
@@ -158,4 +157,4 @@ | ||
exports["clone object containing array"] = function(test) { | ||
test.expect(2); // how many tests? | ||
exports["clone object containing array"] = function (test) { | ||
test.expect(1); // how many tests? | ||
@@ -166,5 +165,5 @@ var a = { | ||
}; | ||
var b = clone(a); | ||
test.ok(_(a).isEqual(b), "underscore equal"); | ||
test.deepEqual(b, a); | ||
@@ -175,7 +174,8 @@ | ||
exports["clone object with circular reference"] = function(test) { | ||
exports["clone object with circular reference"] = function (test) { | ||
test.expect(8); // how many tests? | ||
var c = [1, "foo", {'hello': 'bar'}, function() {}, false, [2]]; | ||
var c = [1, "foo", {'hello': 'bar'}, function () {}, false, [2]]; | ||
var b = [c, 2, 3, 4]; | ||
var a = {'b': b, 'c': c}; | ||
@@ -186,2 +186,3 @@ a.loop = a; | ||
c.aloop = a; | ||
var aCopy = clone(a); | ||
@@ -194,5 +195,2 @@ test.ok(a != aCopy); | ||
//console.log(util.inspect(aCopy, true, null) ); | ||
//console.log("------------------------------------------------------------"); | ||
//console.log(util.inspect(a, true, null) ); | ||
test.ok(eq(a, aCopy)); | ||
@@ -203,4 +201,2 @@ aCopy.c[0] = 2; | ||
test.ok(!eq(a, aCopy)); | ||
//console.log("------------------------------------------------------------"); | ||
//console.log(util.inspect(aCopy, true, null) ); | ||
@@ -214,3 +210,3 @@ function eq(x, y) { | ||
exports['clone prototype'] = function(test) { | ||
exports['clone prototype'] = function (test) { | ||
test.expect(3); // how many tests? | ||
@@ -232,18 +228,18 @@ | ||
exports['clone within an apart context'] = function(test) { | ||
var results = apartContext( | ||
{clone: clone}, | ||
"results = ctx.clone({ a: [1, 2, 3], d: new Date(), r: /^foo$/ig })", | ||
function(results) { | ||
test.ok(results.a.constructor.toString() === Array.toString()); | ||
test.ok(results.d.constructor.toString() === Date.toString()); | ||
test.ok(results.r.constructor.toString() === RegExp.toString()); | ||
test.done(); | ||
} | ||
); | ||
exports['clone within an apart context'] = function (test) { | ||
var results = apartContext({ clone: clone }, | ||
"results = ctx.clone({ a: [1, 2, 3], d: new Date(), r: /^foo$/ig })", | ||
function (results) { | ||
test.ok(results.a.constructor.toString() === Array.toString()); | ||
test.ok(results.d.constructor.toString() === Date.toString()); | ||
test.ok(results.r.constructor.toString() === RegExp.toString()); | ||
test.done(); | ||
}); | ||
}; | ||
exports['clone object with no constructor'] = function(test) { | ||
exports['clone object with no constructor'] = function (test) { | ||
test.expect(3); | ||
var n = null; | ||
var a = { foo: 'bar' }; | ||
@@ -253,4 +249,6 @@ a.__proto__ = n; | ||
test.ok(typeof a !== null); | ||
var b = clone(a); | ||
test.ok(a.foo, b.foo); | ||
test.done(); | ||
@@ -261,2 +259,3 @@ }; | ||
test.expect(6); | ||
var a = { | ||
@@ -269,2 +268,3 @@ foo: { | ||
}; | ||
var b = clone(a, false, 1); | ||
@@ -279,2 +279,3 @@ test.deepEqual(b, a); | ||
test.strictEqual(b.foo.bar, a.foo.bar); | ||
test.done(); | ||
@@ -285,6 +286,9 @@ }; | ||
test.expect(1); | ||
function Constructor() {} | ||
var a = new Constructor(); | ||
function T() {} | ||
var a = new T(); | ||
var b = clone(a); | ||
test.strictEqual(Object.getPrototypeOf(a), Object.getPrototypeOf(b)); | ||
test.done(); | ||
@@ -295,10 +299,13 @@ }; | ||
test.expect(1); | ||
function Constructor() {} | ||
var a = new Constructor(); | ||
function T() {} | ||
var a = new T(); | ||
var b = clone(a, true, Infinity, null); | ||
test.strictEqual(b.__defineSetter__, undefined); | ||
test.done(); | ||
}; | ||
exports['clone object with null children'] = function(test) { | ||
exports['clone object with null children'] = function (test) { | ||
test.expect(1); | ||
@@ -313,3 +320,5 @@ var a = { | ||
}; | ||
var b = clone(a); | ||
test.deepEqual(b, a); | ||
@@ -319,3 +328,3 @@ test.done(); | ||
exports['clone instance with getter'] = function(test) { | ||
exports['clone instance with getter'] = function (test) { | ||
test.expect(1); | ||
@@ -338,57 +347,52 @@ function Ctor() {}; | ||
exports['get RegExp flags'] = function(test) { | ||
test.strictEqual(clone.getRegExpFlags(/a/), '' ); | ||
test.strictEqual(clone.getRegExpFlags(/a/i), 'i' ); | ||
test.strictEqual(clone.getRegExpFlags(/a/g), 'g' ); | ||
test.strictEqual(clone.getRegExpFlags(/a/gi), 'gi'); | ||
test.strictEqual(clone.getRegExpFlags(/a/m), 'm' ); | ||
exports['get RegExp flags'] = function (test) { | ||
test.strictEqual(clone.__getRegExpFlags(/a/), '' ); | ||
test.strictEqual(clone.__getRegExpFlags(/a/i), 'i' ); | ||
test.strictEqual(clone.__getRegExpFlags(/a/g), 'g' ); | ||
test.strictEqual(clone.__getRegExpFlags(/a/gi), 'gi'); | ||
test.strictEqual(clone.__getRegExpFlags(/a/m), 'm' ); | ||
test.done(); | ||
}; | ||
exports["recognize Array object"] = function(test) { | ||
var results = apartContext( | ||
null, "results = [1, 2, 3]", | ||
function(alien) { | ||
var local = [4, 5, 6]; | ||
test.ok(clone.isArray(alien)); // recognize in other context. | ||
test.ok(clone.isArray(local)); // recognize in local context. | ||
test.ok(!clone.isDate(alien)); | ||
test.ok(!clone.isDate(local)); | ||
test.ok(!clone.isRegExp(alien)); | ||
test.ok(!clone.isRegExp(local)); | ||
test.done(); | ||
} | ||
); | ||
exports["recognize Array object"] = function (test) { | ||
var results = apartContext(null, "results = [1, 2, 3]", function(alien) { | ||
var local = [4, 5, 6]; | ||
test.ok(clone.__isArray(alien)); // recognize in other context. | ||
test.ok(clone.__isArray(local)); // recognize in local context. | ||
test.ok(!clone.__isDate(alien)); | ||
test.ok(!clone.__isDate(local)); | ||
test.ok(!clone.__isRegExp(alien)); | ||
test.ok(!clone.__isRegExp(local)); | ||
test.done(); | ||
}); | ||
}; | ||
exports["recognize Date object"] = function(test) { | ||
var results = apartContext( | ||
null, "results = new Date()", | ||
function(alien) { | ||
var local = new Date(); | ||
test.ok(clone.isDate(alien)); // recognize in other context. | ||
test.ok(clone.isDate(local)); // recognize in local context. | ||
test.ok(!clone.isArray(alien)); | ||
test.ok(!clone.isArray(local)); | ||
test.ok(!clone.isRegExp(alien)); | ||
test.ok(!clone.isRegExp(local)); | ||
test.done(); | ||
} | ||
); | ||
exports["recognize Date object"] = function (test) { | ||
var results = apartContext(null, "results = new Date()", function(alien) { | ||
var local = new Date(); | ||
test.ok(clone.__isDate(alien)); // recognize in other context. | ||
test.ok(clone.__isDate(local)); // recognize in local context. | ||
test.ok(!clone.__isArray(alien)); | ||
test.ok(!clone.__isArray(local)); | ||
test.ok(!clone.__isRegExp(alien)); | ||
test.ok(!clone.__isRegExp(local)); | ||
test.done(); | ||
}); | ||
}; | ||
exports["recognize RegExp object"] = function(test) { | ||
var results = apartContext( | ||
null, "results = /foo/", | ||
function(alien) { | ||
var local = /bar/; | ||
test.ok(clone.isRegExp(alien)); // recognize in other context. | ||
test.ok(clone.isRegExp(local)); // recognize in local context. | ||
test.ok(!clone.isArray(alien)); | ||
test.ok(!clone.isArray(local)); | ||
test.ok(!clone.isDate(alien)); | ||
test.ok(!clone.isDate(local)); | ||
test.done(); | ||
} | ||
); | ||
exports["recognize RegExp object"] = function (test) { | ||
var results = apartContext(null, "results = /foo/", function(alien) { | ||
var local = /bar/; | ||
test.ok(clone.__isRegExp(alien)); // recognize in other context. | ||
test.ok(clone.__isRegExp(local)); // recognize in local context. | ||
test.ok(!clone.__isArray(alien)); | ||
test.ok(!clone.__isArray(local)); | ||
test.ok(!clone.__isDate(alien)); | ||
test.ok(!clone.__isDate(local)); | ||
test.done(); | ||
}); | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1
23835
425