Skip to content

Commit

Permalink
Add support for cloning Promises
Browse files Browse the repository at this point in the history
  • Loading branch information
rictic committed Sep 25, 2016
1 parent 83b1870 commit 1f44e00
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
17 changes: 15 additions & 2 deletions clone.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@ var nativeSet;
try {
nativeSet = Set;
} catch(_) {
// maybe a reference error because no `Set`. Give it a dummy value that no
// value will ever be an instanceof.
nativeSet = function() {};
}

var nativePromise;
try {
nativePromise = Promise;
} catch(_) {
nativePromise = function() {};
}

/**
* Clones (copies) an Object using deep copying.
*
Expand Down Expand Up @@ -77,6 +82,14 @@ function clone(parent, circular, depth, prototype) {
child = new nativeMap();
} else if (parent instanceof nativeSet) {
child = new nativeSet();
} else if (parent instanceof nativePromise) {
child = new nativePromise(function (resolve, reject) {
parent.then(function(value) {
resolve(_clone(value, depth - 1));
}, function(err) {
reject(_clone(err, depth - 1));
});
});
} else if (clone.__isArray(parent)) {
child = [];
} else if (clone.__isRegExp(parent)) {
Expand Down
58 changes: 58 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,61 @@ if (nativeSet) {
test.done();
}
}

var nativePromise;
try {
nativePromise = Promise;
} catch(_) {}
if (nativePromise) {
exports["clone a native Promise"] = function (test) {
test.expect(9);

var allDonePromises = [];

// Resolving to a value
allDonePromises.push(
clone(Promise.resolve('foo')).then(function (value) {
test.equal(value, 'foo');
})
);

// Rejecting to a value
allDonePromises.push(
clone(Promise.reject('bar')).catch(function (value) {
test.equal(value, 'bar');
})
);

// Resolving to a promise
allDonePromises.push(
clone(Promise.resolve(Promise.resolve('baz'))).then(function (value) {
test.equal(value, 'baz');
})
);

// Resolving to a circular value
var circle = {};
circle.circle = circle;
allDonePromises.push(
clone(Promise.resolve(circle)).then(function (value) {
test.notEqual(circle, value);
test.equal(value.circle, value);
})
);

var expandoPromise = Promise.resolve('ok');
expandoPromise.circle = expandoPromise;
expandoPromise.prop = 'val';
var clonedPromise = clone(expandoPromise);
test.notEqual(expandoPromise, clonedPromise);
test.equal(clonedPromise.prop, 'val');
test.equal(clonedPromise.circle, clonedPromise);
allDonePromises.push(clonedPromise.then(function(value) {
test.equal(value, 'ok');
}));

Promise.all(allDonePromises).then(function() {
test.done();
});
}
}

0 comments on commit 1f44e00

Please sign in to comment.