Add @@species/better subclassing support to Promises
This patch makes Promise.prototype.then use @@species as specified in ES2015. The fix is hoped for by certain users, such as legacy core.js versions which encounter an unhandled Promise reject (complete with an ugly console message) when Promise subclassing is supported in a mostly correct way, and we do error checking on Promise constructors, but @@species is not supported. BUG=chromium:575314,v8:4633 LOG=Y R=adamk Review URL: https://codereview.chromium.org/1577223002 Cr-Commit-Position: refs/heads/master@{#33225}
This commit is contained in:
parent
150887a13c
commit
569145019d
@ -23,10 +23,12 @@ var promiseOnResolveSymbol =
|
||||
var promiseRawSymbol = utils.ImportNow("promise_raw_symbol");
|
||||
var promiseStatusSymbol = utils.ImportNow("promise_status_symbol");
|
||||
var promiseValueSymbol = utils.ImportNow("promise_value_symbol");
|
||||
var SpeciesConstructor;
|
||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||
|
||||
utils.Import(function(from) {
|
||||
MakeTypeError = from.MakeTypeError;
|
||||
SpeciesConstructor = from.SpeciesConstructor;
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@ -276,7 +278,7 @@ function PromiseThen(onResolve, onReject) {
|
||||
throw MakeTypeError(kNotAPromise, this);
|
||||
}
|
||||
|
||||
var constructor = this.constructor;
|
||||
var constructor = SpeciesConstructor(this, GlobalPromise);
|
||||
onResolve = IS_CALLABLE(onResolve) ? onResolve : PromiseIdResolveHandler;
|
||||
onReject = IS_CALLABLE(onReject) ? onReject : PromiseIdRejectHandler;
|
||||
var deferred = NewPromiseCapability(constructor);
|
||||
|
42
test/mjsunit/harmony/promise-species.js
Normal file
42
test/mjsunit/harmony/promise-species.js
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-species --allow-natives-syntax
|
||||
|
||||
// Test that Promises use @@species appropriately
|
||||
|
||||
// Another constructor with no species will not be instantiated
|
||||
var test = new Promise(function(){});
|
||||
var bogoCount = 0;
|
||||
function bogusConstructor() { bogoCount++; }
|
||||
test.constructor = bogusConstructor;
|
||||
assertTrue(Promise.resolve(test) instanceof Promise);
|
||||
assertFalse(Promise.resolve(test) instanceof bogusConstructor);
|
||||
// Tests that chromium:575314 is fixed thoroughly
|
||||
Promise.resolve(test).catch(e => %AbortJS("Error " + e)).then(() => {
|
||||
if (bogoCount != 0) %AbortJS("bogoCount was " + bogoCount + " should be 0");
|
||||
});
|
||||
|
||||
// If there is a species, it will be instantiated
|
||||
// @@species will be read exactly once, and the constructor is called with a
|
||||
// function
|
||||
var count = 0;
|
||||
var params;
|
||||
class MyPromise extends Promise {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
params = args;
|
||||
}
|
||||
static get [Symbol.species]() {
|
||||
count++
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
var myPromise = MyPromise.resolve().then();
|
||||
assertEquals(1, count);
|
||||
assertEquals(1, params.length);
|
||||
assertEquals('function', typeof(params[0]));
|
||||
assertTrue(myPromise instanceof MyPromise);
|
||||
assertTrue(myPromise instanceof Promise);
|
Loading…
Reference in New Issue
Block a user