| var clone = require('./'); |
| |
| 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 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 }); |
| 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) { |
| throw e; |
| } |
| }; |
| } else { |
| console.log('WARNING: cannot create an apart context.'); |
| } |
| } |
| |
| exports["clone string"] = function (test) { |
| test.expect(2); // how many tests? |
| |
| var a = "foo"; |
| test.strictEqual(clone(a), a); |
| a = ""; |
| test.strictEqual(clone(a), a); |
| |
| test.done(); |
| }; |
| |
| exports["clone number"] = function (test) { |
| test.expect(5); // how many tests? |
| |
| var a = 0; |
| test.strictEqual(clone(a), a); |
| a = 1; |
| test.strictEqual(clone(a), a); |
| a = -1000; |
| test.strictEqual(clone(a), a); |
| a = 3.1415927; |
| test.strictEqual(clone(a), a); |
| a = -3.1415927; |
| test.strictEqual(clone(a), a); |
| |
| test.done(); |
| }; |
| |
| exports["clone date"] = function (test) { |
| test.expect(3); // how many tests? |
| |
| var a = new Date; |
| var c = clone(a); |
| test.ok(!!a.getUTCDate && !!a.toUTCString); |
| test.ok(!!c.getUTCDate && !!c.toUTCString); |
| test.equal(a.getTime(), c.getTime()); |
| |
| test.done(); |
| }; |
| |
| exports["clone object"] = function (test) { |
| test.expect(1); // how many tests? |
| |
| var a = { foo: { bar: "baz" } }; |
| var b = clone(a); |
| |
| test.deepEqual(b, a); |
| |
| test.done(); |
| }; |
| |
| exports["clone array"] = function (test) { |
| test.expect(2); // how many tests? |
| |
| var a = [ |
| { foo: "bar" }, |
| "baz" |
| ]; |
| var b = clone(a); |
| |
| test.ok(b instanceof Array); |
| test.deepEqual(b, a); |
| |
| test.done(); |
| }; |
| |
| exports["clone buffer"] = function (test) { |
| if (typeof Buffer == 'undefined') { |
| return test.done(); |
| } |
| |
| test.expect(1); |
| |
| var a = new Buffer("this is a test buffer"); |
| var b = clone(a); |
| |
| // no underscore equal since it has no concept of Buffers |
| test.deepEqual(b, a); |
| test.done(); |
| }; |
| |
| exports["clone regexp"] = function (test) { |
| test.expect(5); |
| |
| var a = /abc123/gi; |
| var b = clone(a); |
| test.deepEqual(b, a); |
| |
| var c = /a/g; |
| test.ok(c.lastIndex === 0); |
| |
| c.exec('123a456a'); |
| test.ok(c.lastIndex === 4); |
| |
| var d = clone(c); |
| test.ok(d.global); |
| test.ok(d.lastIndex === 4); |
| |
| test.done(); |
| }; |
| |
| exports["clone object containing array"] = function (test) { |
| test.expect(1); // how many tests? |
| |
| var a = { |
| arr1: [ { a: '1234', b: '2345' } ], |
| arr2: [ { c: '345', d: '456' } ] |
| }; |
| |
| var b = clone(a); |
| |
| test.deepEqual(b, a); |
| |
| test.done(); |
| }; |
| |
| exports["clone object with circular reference"] = function (test) { |
| test.expect(8); // how many tests? |
| |
| var c = [1, "foo", {'hello': 'bar'}, function () {}, false, [2]]; |
| var b = [c, 2, 3, 4]; |
| |
| var a = {'b': b, 'c': c}; |
| a.loop = a; |
| a.loop2 = a; |
| c.loop = c; |
| c.aloop = a; |
| |
| var aCopy = clone(a); |
| 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]); |
| |
| test.ok(eq(a, aCopy)); |
| aCopy.c[0] = 2; |
| test.ok(!eq(a, aCopy)); |
| aCopy.c = "2"; |
| test.ok(!eq(a, aCopy)); |
| |
| function eq(x, y) { |
| return inspect(x) === inspect(y); |
| } |
| |
| test.done(); |
| }; |
| |
| exports['clone prototype'] = function (test) { |
| test.expect(3); // how many tests? |
| |
| var a = { |
| a: "aaa", |
| x: 123, |
| y: 45.65 |
| }; |
| var b = clone.clonePrototype(a); |
| |
| test.strictEqual(b.a, a.a); |
| test.strictEqual(b.x, a.x); |
| test.strictEqual(b.y, a.y); |
| |
| 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) { |
| test.expect(3); |
| |
| var n = null; |
| |
| var a = { foo: 'bar' }; |
| a.__proto__ = n; |
| test.ok(typeof a === 'object'); |
| test.ok(typeof a !== null); |
| |
| var b = clone(a); |
| test.ok(a.foo, b.foo); |
| |
| test.done(); |
| }; |
| |
| exports['clone object with depth argument'] = function (test) { |
| test.expect(6); |
| |
| var a = { |
| foo: { |
| bar : { |
| baz : 'qux' |
| } |
| } |
| }; |
| |
| var b = clone(a, false, 1); |
| test.deepEqual(b, a); |
| test.notEqual(b, a); |
| test.strictEqual(b.foo, a.foo); |
| |
| b = clone(a, true, 2); |
| test.deepEqual(b, a); |
| test.notEqual(b.foo, a.foo); |
| test.strictEqual(b.foo.bar, a.foo.bar); |
| |
| test.done(); |
| }; |
| |
| exports['maintain prototype chain in clones'] = function (test) { |
| test.expect(1); |
| |
| function T() {} |
| |
| var a = new T(); |
| var b = clone(a); |
| test.strictEqual(Object.getPrototypeOf(a), Object.getPrototypeOf(b)); |
| |
| test.done(); |
| }; |
| |
| exports['parent prototype is overriden with prototype provided'] = function (test) { |
| test.expect(1); |
| |
| 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) { |
| test.expect(1); |
| var a = { |
| foo: { |
| bar: null, |
| baz: { |
| qux: false |
| } |
| } |
| }; |
| |
| var b = clone(a); |
| |
| test.deepEqual(b, a); |
| test.done(); |
| }; |
| |
| exports['clone instance with getter'] = function (test) { |
| test.expect(1); |
| function Ctor() {}; |
| Object.defineProperty(Ctor.prototype, 'prop', { |
| configurable: true, |
| enumerable: true, |
| get: function() { |
| return 'value'; |
| } |
| }); |
| |
| var a = new Ctor(); |
| var b = clone(a); |
| |
| test.strictEqual(b.prop, 'value'); |
| 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(); |
| }); |
| }; |