Skip to content

Commit 9c0f9ea

Browse files
author
Matt Loring
committed
Makes WrappedPromise an ES6 class
This allow for correct dispatch of method calls made on ES6 classes that subclass promise. Fixes: #112
1 parent 3e29e8c commit 9c0f9ea

File tree

4 files changed

+90
-18
lines changed

4 files changed

+90
-18
lines changed

es6-wrapped-promise.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
module.exports = (Promise, ensureAslWrapper) => {
4+
// Updates to this class should also be applied to the the ES3 version
5+
// in index.js.
6+
return class WrappedPromise extends Promise {
7+
constructor(executor) {
8+
var context, args;
9+
super(wrappedExecutor);
10+
var promise = this;
11+
12+
try {
13+
executor.apply(context, args);
14+
} catch (err) {
15+
args[1](err);
16+
}
17+
18+
return promise;
19+
function wrappedExecutor(resolve, reject) {
20+
context = this;
21+
args = [wrappedResolve, wrappedReject];
22+
23+
// These wrappers create a function that can be passed a function and an argument to
24+
// call as a continuation from the resolve or reject.
25+
function wrappedResolve(val) {
26+
ensureAslWrapper(promise, false);
27+
return resolve(val);
28+
}
29+
30+
function wrappedReject(val) {
31+
ensureAslWrapper(promise, false);
32+
return reject(val);
33+
}
34+
}
35+
}
36+
}
37+
};

index.js

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var shimmer = require('shimmer')
1010
, util = require('util')
1111
;
1212

13+
var v6plus = semver.gte(process.version, '6.0.0');
1314
var v7plus = semver.gte(process.version, '7.0.0');
1415

1516
var net = require('net');
@@ -391,6 +392,8 @@ if (instrumentPromise) {
391392
function wrapPromise() {
392393
var Promise = global.Promise;
393394

395+
// Updates to this class should also be applied to the the ES6 version
396+
// in es6-wrapped-promise.js.
394397
function wrappedPromise(executor) {
395398
if (!(this instanceof wrappedPromise)) {
396399
return Promise(executor);
@@ -407,7 +410,7 @@ function wrapPromise() {
407410
try {
408411
executor.apply(context, args);
409412
} catch (err) {
410-
args[1](err)
413+
args[1](err);
411414
}
412415

413416
return promise;
@@ -438,23 +441,26 @@ function wrapPromise() {
438441
wrap(Promise.prototype, 'chain', wrapThen);
439442
}
440443

441-
var PromiseFunctions = [
442-
'all',
443-
'race',
444-
'reject',
445-
'resolve',
446-
'accept', // Node.js <v7 only
447-
'defer' // Node.js <v7 only
448-
];
449-
450-
PromiseFunctions.forEach(function(key) {
451-
// don't break `in` by creating a key for undefined entries
452-
if (typeof Promise[key] === 'function') {
453-
wrappedPromise[key] = Promise[key];
454-
}
455-
});
456-
457-
global.Promise = wrappedPromise;
444+
if (v6plus) {
445+
global.Promise = require('./es6-wrapped-promise.js')(Promise, ensureAslWrapper);
446+
} else {
447+
var PromiseFunctions = [
448+
'all',
449+
'race',
450+
'reject',
451+
'resolve',
452+
'accept', // Node.js <v7 only
453+
'defer' // Node.js <v7 only
454+
];
455+
456+
PromiseFunctions.forEach(function(key) {
457+
// don't break `in` by creating a key for undefined entries
458+
if (typeof Promise[key] === 'function') {
459+
wrappedPromise[key] = Promise[key];
460+
}
461+
});
462+
global.Promise = wrappedPromise
463+
}
458464

459465
function ensureAslWrapper(promise, overwrite) {
460466
if (!promise.__asl_wrapper || overwrite) {

test/native-promises.tap.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2198,3 +2198,21 @@ if (typeof Promise.prototype.chain === 'function') {
21982198
}
21992199
});
22002200
}
2201+
2202+
test('subclasses', function(t) {
2203+
if (nodeVersion[0] < 6) {
2204+
// class syntax is not supported before node 6.
2205+
t.end();
2206+
return;
2207+
}
2208+
2209+
// SubclassedPromise does 2 asserts.
2210+
t.plan(3);
2211+
2212+
var SubclassedPromise = require('./promise-subclass.js')(t);
2213+
2214+
var s = SubclassedPromise.resolve(42).then(function(val) {
2215+
t.strictEqual(val, 42);
2216+
t.end();
2217+
});
2218+
});

test/promise-subclass.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
module.exports = (tap) => {
4+
return class SubclassedPromise extends Promise {
5+
then(onSuccess, onReject) {
6+
tap.type(onSuccess, 'function');
7+
tap.type(onReject, 'undefined');
8+
return Promise.prototype.then.call(this, onSuccess, onReject);
9+
}
10+
};
11+
};

0 commit comments

Comments
 (0)