Introduce v8::Promise::Then(context, on_fulfilled, on_rejected)
Currently v8::Promise::Then takes only one handler. It should take two handlers, on_fulfilled and on_rejected like ECMAScript Promise. Bug: chromium:912848 Change-Id: I08a20990a27b3f8621225fad42a8de1dad67796f Reviewed-on: https://chromium-review.googlesource.com/c/1375509 Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Yutaka Hirano <yhirano@chromium.org> Cr-Commit-Position: refs/heads/master@{#58204}
This commit is contained in:
parent
fe0c99ad43
commit
228b362a52
@ -4124,6 +4124,10 @@ class V8_EXPORT Promise : public Object {
|
||||
V8_WARN_UNUSED_RESULT MaybeLocal<Promise> Then(Local<Context> context,
|
||||
Local<Function> handler);
|
||||
|
||||
V8_WARN_UNUSED_RESULT MaybeLocal<Promise> Then(Local<Context> context,
|
||||
Local<Function> on_fulfilled,
|
||||
Local<Function> on_rejected);
|
||||
|
||||
/**
|
||||
* Returns true if the promise has at least one derived promise, and
|
||||
* therefore resolve/reject handlers (including default handler).
|
||||
|
14
src/api.cc
14
src/api.cc
@ -7285,6 +7285,20 @@ MaybeLocal<Promise> Promise::Then(Local<Context> context,
|
||||
RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
|
||||
}
|
||||
|
||||
MaybeLocal<Promise> Promise::Then(Local<Context> context,
|
||||
Local<Function> on_fulfilled,
|
||||
Local<Function> on_rejected) {
|
||||
PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
|
||||
auto self = Utils::OpenHandle(this);
|
||||
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*on_fulfilled),
|
||||
Utils::OpenHandle(*on_rejected)};
|
||||
i::Handle<i::Object> result;
|
||||
has_pending_exception = !i::Execution::Call(isolate, isolate->promise_then(),
|
||||
self, arraysize(argv), argv)
|
||||
.ToHandle(&result);
|
||||
RETURN_ON_FAILED_EXECUTION(Promise);
|
||||
RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
|
||||
}
|
||||
|
||||
bool Promise::HasHandler() {
|
||||
i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
|
||||
|
@ -24693,7 +24693,7 @@ TEST(Promises) {
|
||||
CHECK(r->IsPromise());
|
||||
}
|
||||
|
||||
|
||||
// Promise.Then(on_fulfilled)
|
||||
TEST(PromiseThen) {
|
||||
LocalContext context;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
@ -24790,6 +24790,121 @@ TEST(PromiseThen) {
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
// Promise.Then(on_fulfilled, on_rejected)
|
||||
TEST(PromiseThen2) {
|
||||
LocalContext context;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
|
||||
v8::HandleScope scope(isolate);
|
||||
Local<Object> global = context->Global();
|
||||
|
||||
// Creation.
|
||||
Local<v8::Promise::Resolver> pr =
|
||||
v8::Promise::Resolver::New(context.local()).ToLocalChecked();
|
||||
Local<v8::Promise> p = pr->GetPromise();
|
||||
|
||||
CHECK(p->IsPromise());
|
||||
|
||||
pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
|
||||
|
||||
// Chaining non-pending promises.
|
||||
CompileRun(
|
||||
"var x1 = 0;\n"
|
||||
"var x2 = 0;\n"
|
||||
"function f1(x) { x1 = x; return x+1 };\n"
|
||||
"function f2(x) { x2 = x; return x+1 };\n"
|
||||
"function f3(x) { throw x + 100 };\n");
|
||||
Local<Function> f1 = Local<Function>::Cast(
|
||||
global->Get(context.local(), v8_str("f1")).ToLocalChecked());
|
||||
Local<Function> f2 = Local<Function>::Cast(
|
||||
global->Get(context.local(), v8_str("f2")).ToLocalChecked());
|
||||
Local<Function> f3 = Local<Function>::Cast(
|
||||
global->Get(context.local(), v8_str("f3")).ToLocalChecked());
|
||||
|
||||
// Then
|
||||
CompileRun("x1 = x2 = 0;");
|
||||
Local<v8::Promise> a = p->Then(context.local(), f1, f2).ToLocalChecked();
|
||||
CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
Local<v8::Promise> b = a->Then(context.local(), f3, f2).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
Local<v8::Promise> c = b->Then(context.local(), f1, f2).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
v8::Local<v8::Promise> d = c->Then(context.local(), f1, f2).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
v8::Local<v8::Promise> e = d->Then(context.local(), f3, f2).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
v8::Local<v8::Promise> f = e->Then(context.local(), f1, f3).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
|
||||
f->Then(context.local(), f1, f2).ToLocalChecked();
|
||||
isolate->RunMicrotasks();
|
||||
CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(304, global->Get(context.local(), v8_str("x2"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
TEST(PromiseStateAndValue) {
|
||||
LocalContext context;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
Loading…
Reference in New Issue
Block a user