Skip to content

Commit 753fc6f

Browse files
Kevin SmithKevin Smith
Kevin Smith
authored and
Kevin Smith
committed
[MERGE #6017 @zenparsing] Do not expose async function resumer callbacks to user code
Merge pull request #6017 from zenparsing:await-fix Removes the ability to capture the success and failure await resumer callbacks and aligns Chakra with the current specification of await.
2 parents e6e25c3 + 69d2f9d commit 753fc6f

File tree

3 files changed

+48
-24
lines changed

3 files changed

+48
-24
lines changed

lib/Runtime/Library/JavascriptPromise.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,13 +1447,7 @@ namespace Js
14471447
value = JavascriptOperators::GetProperty(next, PropertyIds::value, scriptContext);
14481448
Var promiseVar = CALL_FUNCTION(scriptContext->GetThreadContext(), promiseResolve, CallInfo(CallFlags_Value, 2), library->GetPromiseConstructor(), value);
14491449
JavascriptPromise* promise = VarTo<JavascriptPromise>(promiseVar);
1450-
1451-
Var promiseThen = JavascriptOperators::GetProperty(promise, PropertyIds::then, scriptContext);
1452-
if (!JavascriptConversion::IsCallable(promiseThen))
1453-
{
1454-
JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
1455-
}
1456-
CALL_FUNCTION(scriptContext->GetThreadContext(), VarTo<RecyclableObject>(promiseThen), CallInfo(CallFlags_Value, 3), promise, successFunction, failFunction);
1450+
CreateThenPromise(promise, successFunction, failFunction, scriptContext);
14571451

14581452
END_SAFE_REENTRANT_REGION
14591453
}

test/es7/asyncawait-functionality.baseline

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ Executing test #31 - Async and arguments.caller
3737
Executing test #32 - Async and split scope
3838
Test #32 - Success initial value of the formal is the same as the default param value
3939
Test #32 - Success initial value of the body symbol is the same as the default param value
40-
Executing test #33 - `then` is called with both onFulfilled and onRejected
41-
Test #33 - then: true, catch: true
40+
Executing test #33 - `then` is not called when awaiting a non-promise or native promise
41+
Executing test #34 - `then` is called when awaiting a promise subclass
42+
Executing test #35 - `then` is called when awaiting a non-promise thenable
4243

4344
Completion Results:
4445
Test #1 - Success lambda expression with no argument called with result = 'true'
@@ -85,7 +86,8 @@ Test #28 - Success finally block is executed in async body
8586
Test #30 - Success async function and arguments.callee
8687
Test #32 - Success updated value of the formal is the same as the value returned from the second async function
8788
Test #32 - Success updated value of the body symbol is the same as the value returned from the second async function
88-
Test #33 - Success caught the expected exception
89+
Test #34 - Success "then" called on a promise subclass
90+
Test #35 - Success "then" called on a thenable
8991
Test #6 - Success await in an async function #1 called with result = '-4'
9092
Test #6 - Success await in an async function #2 called with result = '2'
9193
Test #6 - Success await in an async function catch a rejected Promise in 'err'. Error = 'Error: My Error'

test/es7/asyncawait-functionality.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,29 +1039,57 @@ var tests = [
10391039
}
10401040
},
10411041
{
1042-
name: "`then` is called with both onFulfilled and onRejected",
1042+
name: "`then` is not called when awaiting a non-promise or native promise",
10431043
body: function (index) {
1044-
async function bar() {
1045-
throw new Error("Whoops");
1044+
async function f() {
1045+
await 1;
1046+
await Promise.resolve(1);
10461047
}
10471048

1048-
async function foo() {
1049-
try {
1050-
await bar();
1051-
} catch (e){
1052-
echo(`Test #${index} - Success caught the expected exception`);
1049+
var oldThen = Promise.prototype.then;
1050+
Promise.prototype.then = function(onResolve, onReject) {
1051+
echo(`Test #${index} - Failed "then" called on non-promise or native promise`);
1052+
return oldThen.apply(this, arguments);
1053+
};
1054+
1055+
f();
1056+
1057+
Promise.prototype.then = oldThen;
1058+
}
1059+
},
1060+
{
1061+
name: "`then` is called when awaiting a promise subclass",
1062+
body: function (index) {
1063+
class PromiseSubclass extends Promise {
1064+
constructor(executor) { super(executor); }
1065+
then(onResolve, onReject) {
1066+
echo(`Test #${index} - Success "then" called on a promise subclass`);
1067+
return super.then(onResolve, onReject);
10531068
}
10541069
}
10551070

1056-
var oldThen = Promise.prototype.then;
1057-
Promise.prototype.then = function(thenx, catchx) {
1058-
echo(`Test #${index} - then: ${!!thenx}, catch: ${!!catchx}`)
1059-
return oldThen.apply(this, arguments);
1071+
async function f() {
1072+
await PromiseSubclass.resolve(1);
10601073
}
10611074

1062-
foo();
1075+
f();
1076+
}
1077+
},
1078+
{
1079+
name: "`then` is called when awaiting a non-promise thenable",
1080+
body: function (index) {
1081+
let thenable = {
1082+
then(onResolve, onReject) {
1083+
echo(`Test #${index} - Success "then" called on a thenable`);
1084+
return Promise.resolve(1);
1085+
}
1086+
};
10631087

1064-
Promise.prototype.then = oldThen;
1088+
async function f() {
1089+
await thenable;
1090+
}
1091+
1092+
f();
10651093
}
10661094
}
10671095
];

0 commit comments

Comments
 (0)