Commit d757f378 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Add v8::Promise::Then.

Blink needs v8::Promise::Then to implement ScriptPromise::then.
Blink-side CL: https://codereview.chromium.org/316453002

BUG=371288
LOG=Y
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/314553002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21805 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3419aefe
......@@ -2614,6 +2614,7 @@ class V8_EXPORT Promise : public Object {
*/
Local<Promise> Chain(Handle<Function> handler);
Local<Promise> Catch(Handle<Function> handler);
Local<Promise> Then(Handle<Function> handler);
V8_INLINE static Promise* Cast(Value* obj);
......
......@@ -5910,6 +5910,26 @@ Local<Promise> Promise::Catch(Handle<Function> handler) {
}
Local<Promise> Promise::Then(Handle<Function> handler) {
i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
i::Isolate* isolate = promise->GetIsolate();
LOG_API(isolate, "Promise::Then");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
i::Handle<i::Object> result;
has_pending_exception = !i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_then()),
promise,
ARRAY_SIZE(argv), argv,
false).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
return Local<Promise>::Cast(Utils::ToLocal(result));
}
bool v8::ArrayBuffer::IsExternal() const {
return Utils::OpenHandle(this)->is_external();
}
......
......@@ -1598,6 +1598,7 @@ void Genesis::InstallNativeFunctions() {
INSTALL_NATIVE(JSFunction, "PromiseReject", promise_reject);
INSTALL_NATIVE(JSFunction, "PromiseChain", promise_chain);
INSTALL_NATIVE(JSFunction, "PromiseCatch", promise_catch);
INSTALL_NATIVE(JSFunction, "PromiseThen", promise_then);
INSTALL_NATIVE(JSFunction, "NotifyChange", observers_notify_change);
INSTALL_NATIVE(JSFunction, "EnqueueSpliceRecord", observers_enqueue_splice);
......
......@@ -162,6 +162,7 @@ enum BindingFlags {
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
to_complete_property_descriptor) \
V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
......@@ -340,6 +341,7 @@ class Context: public FixedArray {
PROMISE_REJECT_INDEX,
PROMISE_CHAIN_INDEX,
PROMISE_CATCH_INDEX,
PROMISE_THEN_INDEX,
TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
DERIVED_HAS_TRAP_INDEX,
DERIVED_GET_TRAP_INDEX,
......
......@@ -17,6 +17,7 @@ var PromiseResolve;
var PromiseReject;
var PromiseChain;
var PromiseCatch;
var PromiseThen;
// mirror-debugger.js currently uses builtins.promiseStatus. It would be nice
// if we could move these property names into the closure below.
......@@ -220,7 +221,7 @@ var promiseRaw = GLOBAL_PRIVATE("Promise#raw");
// Multi-unwrapped chaining with thenable coercion.
function PromiseThen(onResolve, onReject) {
PromiseThen = function PromiseThen(onResolve, onReject) {
onResolve = IS_SPEC_FUNCTION(onResolve) ? onResolve
: PromiseIdResolveHandler;
onReject = IS_SPEC_FUNCTION(onReject) ? onReject
......
......@@ -22603,6 +22603,72 @@ TEST(Promises) {
}
TEST(PromiseThen) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
Handle<Object> global = context->Global();
// Creation.
Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
Handle<v8::Promise> p = pr->GetPromise();
Handle<v8::Promise> q = qr->GetPromise();
CHECK(p->IsPromise());
CHECK(q->IsPromise());
pr->Resolve(v8::Integer::New(isolate, 1));
qr->Resolve(p);
// 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");
Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
// Chain
q->Chain(f1);
CHECK(global->Get(v8_str("x1"))->IsNumber());
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
isolate->RunMicrotasks();
CHECK(!global->Get(v8_str("x1"))->IsNumber());
CHECK_EQ(p, global->Get(v8_str("x1")));
// Then
CompileRun("x1 = x2 = 0;");
q->Then(f1);
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
isolate->RunMicrotasks();
CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
// Then
CompileRun("x1 = x2 = 0;");
pr = v8::Promise::Resolver::New(isolate);
qr = v8::Promise::Resolver::New(isolate);
qr->Resolve(pr);
qr->GetPromise()->Then(f1)->Then(f2);
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
isolate->RunMicrotasks();
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
pr->Resolve(v8::Integer::New(isolate, 3));
CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
isolate->RunMicrotasks();
CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
}
TEST(DisallowJavascriptExecutionScope) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment