From: rossberg@chromium.org Date: Thu, 12 Jun 2014 11:33:30 +0000 (+0000) Subject: Add v8::Promise::Then. X-Git-Tag: upstream/4.7.83~8708 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d757f378d31174738220178df59cdfc3286e75e9;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/include/v8.h b/include/v8.h index 25cb84e..e037ca7 100644 --- a/include/v8.h +++ b/include/v8.h @@ -2614,6 +2614,7 @@ class V8_EXPORT Promise : public Object { */ Local Chain(Handle handler); Local Catch(Handle handler); + Local Then(Handle handler); V8_INLINE static Promise* Cast(Value* obj); diff --git a/src/api.cc b/src/api.cc index cc9cd3a..0c97851 100644 --- a/src/api.cc +++ b/src/api.cc @@ -5910,6 +5910,26 @@ Local Promise::Catch(Handle handler) { } +Local Promise::Then(Handle handler) { + i::Handle promise = Utils::OpenHandle(this); + i::Isolate* isolate = promise->GetIsolate(); + LOG_API(isolate, "Promise::Then"); + ENTER_V8(isolate); + EXCEPTION_PREAMBLE(isolate); + i::Handle argv[] = { Utils::OpenHandle(*handler) }; + i::Handle 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()); + return Local::Cast(Utils::ToLocal(result)); +} + + bool v8::ArrayBuffer::IsExternal() const { return Utils::OpenHandle(this)->is_external(); } diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index cfef267..19a4394 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -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); diff --git a/src/contexts.h b/src/contexts.h index d9541b0..51a7162 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -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, diff --git a/src/promise.js b/src/promise.js index f7d6307..710abad 100644 --- a/src/promise.js +++ b/src/promise.js @@ -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 diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index bdda382..d97aef0 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -22603,6 +22603,72 @@ TEST(Promises) { } +TEST(PromiseThen) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + v8::HandleScope scope(isolate); + Handle global = context->Global(); + + // Creation. + Handle pr = v8::Promise::Resolver::New(isolate); + Handle qr = v8::Promise::Resolver::New(isolate); + Handle p = pr->GetPromise(); + Handle 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 f1 = Handle::Cast(global->Get(v8_str("f1"))); + Handle f2 = Handle::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();