Skip to content

Commit

Permalink
[promises] improve feature detection
Browse files Browse the repository at this point in the history
- detection @@species pattern support
- detection unhandled rejection tracking support
- remove usage `Object.setPrototypeOf` and noisy console message in FF
  • Loading branch information
zloirock committed Feb 17, 2016
1 parent 7339847 commit 3568fe3
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 68 deletions.
44 changes: 10 additions & 34 deletions library/modules/es6.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,16 @@ var LIBRARY = require('./_library')
, empty = function(){ /* empty */ }
, Internal, GenericPromiseCapability, Wrapper;

var testResolve = function(sub){
var test = new $Promise(empty), promise;
if(sub)test.constructor = function(exec){
exec(empty, empty);
};
(promise = $Promise.resolve(test))['catch'](empty);
return promise === test;
};

var USE_NATIVE = function(){
var works = false;
var SubPromise = function(x){
var self = new $Promise(x);
setProto(self, SubPromise.prototype);
return self;
};
var USE_NATIVE = !!function(){
try {
works = $Promise && $Promise.resolve && testResolve();
setProto(SubPromise, $Promise);
SubPromise.prototype = require('./_object-create')($Promise.prototype, {constructor: {value: SubPromise}});
// actual Firefox has broken subclass support, test that
if(!(SubPromise.resolve(5).then(empty) instanceof SubPromise)){
works = false;
}
// V8 4.8- bug, https://code.google.com/p/v8/issues/detail?id=4162
if(works && require('./_descriptors')){
var thenableThenGotten = false;
$Promise.resolve(require('./_object-dp').f({}, 'then', {
get: function(){ thenableThenGotten = true; }
}));
works = thenableThenGotten;
}
} catch(e){ works = false; }
return !!works;
// correct subclassing with @@species support
var promise = $Promise.resolve(1)
, FakePromise1 = promise.constructor = function(exec){ exec(empty, empty); }
, FakePromise2 = function(exec){ exec(empty, empty); };
require('./_object-dp')(FakePromise1, require('./_wks')('species'), {value: FakePromise2});
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise2;
} catch(e){ /* empty */ }
}();

// helpers
Expand Down Expand Up @@ -258,7 +234,7 @@ $export($export.S + $export.F * !USE_NATIVE, PROMISE, {
return capability.promise;
}
});
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE || testResolve(true)), PROMISE, {
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
// 25.4.4.6 Promise.resolve(x)
resolve: function resolve(x){
// instanceof instead of internal slot check because we should fix it without replacement native Promise core
Expand Down
44 changes: 10 additions & 34 deletions modules/es6.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,16 @@ var LIBRARY = require('./_library')
, empty = function(){ /* empty */ }
, Internal, GenericPromiseCapability, Wrapper;

var testResolve = function(sub){
var test = new $Promise(empty), promise;
if(sub)test.constructor = function(exec){
exec(empty, empty);
};
(promise = $Promise.resolve(test))['catch'](empty);
return promise === test;
};

var USE_NATIVE = function(){
var works = false;
var SubPromise = function(x){
var self = new $Promise(x);
setProto(self, SubPromise.prototype);
return self;
};
var USE_NATIVE = !!function(){
try {
works = $Promise && $Promise.resolve && testResolve();
setProto(SubPromise, $Promise);
SubPromise.prototype = require('./_object-create')($Promise.prototype, {constructor: {value: SubPromise}});
// actual Firefox has broken subclass support, test that
if(!(SubPromise.resolve(5).then(empty) instanceof SubPromise)){
works = false;
}
// V8 4.8- bug, https://code.google.com/p/v8/issues/detail?id=4162
if(works && require('./_descriptors')){
var thenableThenGotten = false;
$Promise.resolve(require('./_object-dp').f({}, 'then', {
get: function(){ thenableThenGotten = true; }
}));
works = thenableThenGotten;
}
} catch(e){ works = false; }
return !!works;
// correct subclassing with @@species support
var promise = $Promise.resolve(1)
, FakePromise1 = promise.constructor = function(exec){ exec(empty, empty); }
, FakePromise2 = function(exec){ exec(empty, empty); };
require('./_object-dp')(FakePromise1, require('./_wks')('species'), {value: FakePromise2});
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise2;
} catch(e){ /* empty */ }
}();

// helpers
Expand Down Expand Up @@ -258,7 +234,7 @@ $export($export.S + $export.F * !USE_NATIVE, PROMISE, {
return capability.promise;
}
});
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE || testResolve(true)), PROMISE, {
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
// 25.4.4.6 Promise.resolve(x)
resolve: function resolve(x){
// instanceof instead of internal slot check because we should fix it without replacement native Promise core
Expand Down

0 comments on commit 3568fe3

Please sign in to comment.