clone
Advanced tools
Comparing version 0.2.0 to 1.0.0
82
clone.js
'use strict'; | ||
function objectToString(o) { | ||
return Object.prototype.toString.call(o); | ||
} | ||
var clone = (function(global) { | ||
// shim for Node's 'util' package | ||
// DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/). | ||
var util = { | ||
isArray: function (ar) { | ||
return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); | ||
}, | ||
isDate: function (d) { | ||
return typeof d === 'object' && objectToString(d) === '[object Date]'; | ||
}, | ||
isRegExp: function (re) { | ||
return typeof re === 'object' && objectToString(re) === '[object RegExp]'; | ||
}, | ||
getRegExpFlags: function (re) { | ||
var flags = ''; | ||
re.global && (flags += 'g'); | ||
re.ignoreCase && (flags += 'i'); | ||
re.multiline && (flags += 'm'); | ||
return flags; | ||
} | ||
}; | ||
if (typeof module === 'object') | ||
module.exports = clone; | ||
/** | ||
@@ -52,2 +25,9 @@ * Clones (copies) an Object using deep copying. | ||
function clone(parent, circular, depth, prototype) { | ||
var filter; | ||
if (typeof circular === 'object') { | ||
depth = circular.depth; | ||
prototype = circular.prototype; | ||
filter = circular.filter; | ||
circular = circular.circular | ||
} | ||
// maintain two arrays for circular references, where corresponding parents | ||
@@ -81,8 +61,8 @@ // and children have the same index | ||
if (util.isArray(parent)) { | ||
if (isArray(parent)) { | ||
child = []; | ||
} else if (util.isRegExp(parent)) { | ||
child = new RegExp(parent.source, util.getRegExpFlags(parent)); | ||
} else if (isRegExp(parent)) { | ||
child = new RegExp(parent.source, clone.getRegExpFlags(parent)); | ||
if (parent.lastIndex) child.lastIndex = parent.lastIndex; | ||
} else if (util.isDate(parent)) { | ||
} else if (isDate(parent)) { | ||
child = new Date(parent.getTime()); | ||
@@ -147,1 +127,39 @@ } else if (useBuffer && Buffer.isBuffer(parent)) { | ||
}; | ||
function getRegExpFlags(re) { | ||
var flags = ''; | ||
re.global && (flags += 'g'); | ||
re.ignoreCase && (flags += 'i'); | ||
re.multiline && (flags += 'm'); | ||
return flags; | ||
} | ||
function objectToString(o) { | ||
return Object.prototype.toString.call(o); | ||
} | ||
function isDate(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object Date]'; | ||
} | ||
function isArray(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object Array]'; | ||
} | ||
function isRegExp(o) { | ||
return typeof o === 'object' && objectToString(o) === '[object RegExp]'; | ||
} | ||
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; | ||
return clone; | ||
})( typeof(global) === 'object' ? global : | ||
typeof(window) === 'object' ? window : this); | ||
if (module && module.exports) | ||
module.exports = clone; |
@@ -11,3 +11,3 @@ { | ||
], | ||
"version": "0.2.0", | ||
"version": "1.0.0", | ||
"repository": { | ||
@@ -36,3 +36,5 @@ "type": "git", | ||
"Nathan Zadoks (https://github.com/nathan7)", | ||
"Róbert Oroszi <robert+gh@oroszi.net> (https://github.com/oroce)" | ||
"Róbert Oroszi <robert+gh@oroszi.net> (https://github.com/oroce)", | ||
"Aurélio A. Heckert (http://softwarelivre.org/aurium)", | ||
"Guy Ellis (http://www.guyellisrocks.com/)" | ||
], | ||
@@ -46,3 +48,3 @@ "license": "MIT", | ||
"underscore": "*", | ||
"nodeunit": "*" | ||
"nodeunit": "^0.9" | ||
}, | ||
@@ -49,0 +51,0 @@ "optionalDependencies": {}, |
@@ -5,5 +5,7 @@ # clone | ||
offers foolproof _deep cloning_ of variables in JavaScript. | ||
[![info badge](https://nodei.co/npm/clone.png?downloads=true&downloadRank=true&stars=true)](http://npm-stat.com/charts.html?package=clone) | ||
offers foolproof _deep cloning_ of objects, arrays, numbers, strings etc. in JavaScript. | ||
## Installation | ||
@@ -13,7 +15,5 @@ | ||
or | ||
(It also works with browserify, ender or standalone.) | ||
ender build clone | ||
## Example | ||
@@ -110,3 +110,3 @@ | ||
Copyright © 2011-2014 [Paul Vorbach](http://paul.vorba.ch/) and | ||
Copyright © 2011-2015 [Paul Vorbach](http://paul.vorba.ch/) and | ||
[contributors](https://github.com/pvorb/node-clone/graphs/contributors). | ||
@@ -113,0 +113,0 @@ |
179
test.js
@@ -6,8 +6,42 @@ if(module.parent === null) { | ||
if (typeof(global) === 'object') global.TESTING = true; | ||
var clone = require('./'); | ||
var util = require('util'); | ||
var _ = require('underscore'); | ||
function inspect(obj) { | ||
seen = []; | ||
return JSON.stringify(obj, function(key, val) { | ||
if (val != null && typeof val == "object") { | ||
if (seen.indexOf(val) >= 0) return '[cyclic]' | ||
seen.push(val) | ||
} | ||
return val | ||
}); | ||
} | ||
// Creates a new VM in node, or a iframe in a browser to run the script. | ||
function apartContext(context, script, callback) { | ||
var vm = require('vm'); | ||
if (vm) { | ||
var ctx = vm.createContext({ctx: context}); | ||
callback(vm.runInContext(script, ctx)); | ||
} | ||
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 | ||
} | ||
}; | ||
} else { | ||
console.log('WARNING: cant create an apart context (vm.createContext or iframe).'); | ||
} | ||
} | ||
@@ -25,4 +59,2 @@ exports["clone string"] = function(test) { | ||
exports["clone number"] = function(test) { | ||
@@ -45,4 +77,2 @@ test.expect(5); // how many tests? | ||
exports["clone date"] = function(test) { | ||
@@ -53,5 +83,5 @@ test.expect(3); // how many tests? | ||
var c = clone(a); | ||
test.ok(a instanceof Date); | ||
test.ok(c instanceof Date); | ||
test.equal(c.getTime(), a.getTime()); | ||
test.ok(!!a.getUTCDate && !!a.toUTCString); | ||
test.ok(!!c.getUTCDate && !!c.toUTCString); | ||
test.equal(a.getTime(), c.getTime()); | ||
@@ -61,4 +91,2 @@ test.done(); | ||
exports["clone object"] = function(test) { | ||
@@ -76,6 +104,4 @@ test.expect(2); // how many tests? | ||
exports["clone array"] = function(test) { | ||
test.expect(2); // how many tests? | ||
test.expect(3); // how many tests? | ||
@@ -89,2 +115,3 @@ var a = [ | ||
test.ok(_(a).isEqual(b), "underscore equal"); | ||
test.ok(b instanceof Array); | ||
test.deepEqual(b, a); | ||
@@ -96,2 +123,4 @@ | ||
exports["clone buffer"] = function(test) { | ||
if (typeof Buffer == 'undefined') return test.done(); | ||
test.expect(1); | ||
@@ -107,4 +136,2 @@ | ||
exports["clone regexp"] = function(test) { | ||
@@ -131,3 +158,2 @@ test.expect(5); | ||
exports["clone object containing array"] = function(test) { | ||
@@ -148,8 +174,5 @@ test.expect(2); // how many tests? | ||
exports["clone object with circular reference"] = function(test) { | ||
test.expect(8); // how many tests? | ||
var _ = test.ok; | ||
var c = [1, "foo", {'hello': 'bar'}, function() {}, false, [2]]; | ||
@@ -163,7 +186,7 @@ var b = [c, 2, 3, 4]; | ||
var aCopy = clone(a); | ||
_(a != aCopy); | ||
_(a.c != aCopy.c); | ||
_(aCopy.c == aCopy.b[0]); | ||
_(aCopy.c.loop.loop.aloop == aCopy); | ||
_(aCopy.c[0] == a.c[0]); | ||
test.ok(a != aCopy); | ||
test.ok(a.c != aCopy.c); | ||
test.ok(aCopy.c == aCopy.b[0]); | ||
test.ok(aCopy.c.loop.loop.aloop == aCopy); | ||
test.ok(aCopy.c[0] == a.c[0]); | ||
@@ -173,7 +196,7 @@ //console.log(util.inspect(aCopy, true, null) ); | ||
//console.log(util.inspect(a, true, null) ); | ||
_(eq(a, aCopy)); | ||
test.ok(eq(a, aCopy)); | ||
aCopy.c[0] = 2; | ||
_(!eq(a, aCopy)); | ||
test.ok(!eq(a, aCopy)); | ||
aCopy.c = "2"; | ||
_(!eq(a, aCopy)); | ||
test.ok(!eq(a, aCopy)); | ||
//console.log("------------------------------------------------------------"); | ||
@@ -183,3 +206,3 @@ //console.log(util.inspect(aCopy, true, null) ); | ||
function eq(x, y) { | ||
return util.inspect(x, true, null) === util.inspect(y, true, null); | ||
return inspect(x) === inspect(y); | ||
} | ||
@@ -190,5 +213,3 @@ | ||
exports['clonePrototype'] = function(test) { | ||
exports['clone prototype'] = function(test) { | ||
test.expect(3); // how many tests? | ||
@@ -208,17 +229,18 @@ | ||
test.done(); | ||
} | ||
}; | ||
exports['cloneWithinNewVMContext'] = function(test) { | ||
test.expect(3); | ||
var vm = require('vm'); | ||
var ctx = vm.createContext({ clone: clone }); | ||
var script = "clone( {array: [1, 2, 3], date: new Date(), regex: /^foo$/ig} );"; | ||
var results = vm.runInContext(script, ctx); | ||
test.ok(results.array instanceof Array); | ||
test.ok(results.date instanceof Date); | ||
test.ok(results.regex instanceof RegExp); | ||
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['cloneObjectWithNoConstructor'] = function(test) { | ||
exports['clone object with no constructor'] = function(test) { | ||
test.expect(3); | ||
@@ -233,3 +255,3 @@ var n = null; | ||
test.done(); | ||
} | ||
}; | ||
@@ -255,3 +277,3 @@ exports['clone object with depth argument'] = function (test) { | ||
test.done(); | ||
} | ||
}; | ||
@@ -265,3 +287,3 @@ exports['maintain prototype chain in clones'] = function (test) { | ||
test.done(); | ||
} | ||
}; | ||
@@ -275,3 +297,3 @@ exports['parent prototype is overriden with prototype provided'] = function (test) { | ||
test.done(); | ||
} | ||
}; | ||
@@ -291,3 +313,3 @@ exports['clone object with null children'] = function(test) { | ||
test.done(); | ||
} | ||
}; | ||
@@ -310,2 +332,59 @@ exports['clone instance with getter'] = function(test) { | ||
test.done(); | ||
}; | ||
}; | ||
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 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(); | ||
} | ||
); | ||
}; |
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
24701
9
444
0
1