From 354e3064aa262fa7ed3a4906b4eb1e51b1df46ae Mon Sep 17 00:00:00 2001 From: Jimmy Thomson Date: Mon, 12 Feb 2018 15:39:48 -0800 Subject: [PATCH] shim: adding v8::Promise and v8::Promise::Resolver implementations --- deps/chakrashim/include/v8.h | 1 + deps/chakrashim/lib/chakra_shim.js | 2 +- .../src/jsrtcachedpropertyidref.inc | 6 ++ deps/chakrashim/src/v8promise.cc | 20 +++- deps/chakrashim/src/v8resolver.cc | 99 ++++++++++++++++++- 5 files changed, 120 insertions(+), 8 deletions(-) diff --git a/deps/chakrashim/include/v8.h b/deps/chakrashim/include/v8.h index d8689791431..47ba089fef9 100644 --- a/deps/chakrashim/include/v8.h +++ b/deps/chakrashim/include/v8.h @@ -356,6 +356,7 @@ class Local { friend class PropertyDescriptor; friend class Proxy; friend class RegExp; + friend class Promise; friend class Set; friend class Signature; friend class Script; diff --git a/deps/chakrashim/lib/chakra_shim.js b/deps/chakrashim/lib/chakra_shim.js index 7ec253489f7..0dbd2eafca4 100644 --- a/deps/chakrashim/lib/chakra_shim.js +++ b/deps/chakrashim/lib/chakra_shim.js @@ -547,7 +547,7 @@ obj instanceof URIError; }; utils.isPromise = function(obj) { - return compareType(obj, 'Object') && obj instanceof Promise; + return compareType(obj, 'Promise') && obj instanceof Promise; }; utils.isRegExp = function(obj) { return compareType(obj, 'RegExp'); diff --git a/deps/chakrashim/src/jsrtcachedpropertyidref.inc b/deps/chakrashim/src/jsrtcachedpropertyidref.inc index 0326531065f..40242b4c3d9 100644 --- a/deps/chakrashim/src/jsrtcachedpropertyidref.inc +++ b/deps/chakrashim/src/jsrtcachedpropertyidref.inc @@ -128,6 +128,12 @@ DEF(Symbol_toStringTag) DEF(add) DEF(from) + +DEF(promise) +DEF(resolve) +DEF(reject) +DEF(state) + DEFSYMBOL(self) DEFSYMBOL(__external__) DEFSYMBOL(__hiddenvalues__) diff --git a/deps/chakrashim/src/v8promise.cc b/deps/chakrashim/src/v8promise.cc index 6e96ab952eb..2f4bbf93585 100644 --- a/deps/chakrashim/src/v8promise.cc +++ b/deps/chakrashim/src/v8promise.cc @@ -26,11 +26,27 @@ namespace v8 { Promise::Promise() { } Local Promise::Result() { - return Local(); + JsValueRef value; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::value, &value) != JsNoError) { + return Local(); + } + return Local::New(value); } Promise::PromiseState Promise::State() { - return PromiseState::kFulfilled; + JsValueRef state; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::state, &state) != JsNoError) { + return PromiseState::kPending; + } + int stateNumber; + if (JsNumberToInt(state, &stateNumber) != JsNoError) { + return PromiseState::kPending; + } + switch(stateNumber) { + case 1: return PromiseState::kFulfilled; + case 2: return PromiseState::kRejected; + default: return PromiseState::kPending; + } } MaybeLocal Promise::Then(Local context, diff --git a/deps/chakrashim/src/v8resolver.cc b/deps/chakrashim/src/v8resolver.cc index e0cc0f7fe01..00f882b9577 100644 --- a/deps/chakrashim/src/v8resolver.cc +++ b/deps/chakrashim/src/v8resolver.cc @@ -25,7 +25,35 @@ namespace v8 { using Resolver = Promise::Resolver; // CHAKRA-TODO: Unimplemented completely MaybeLocal Resolver::New(Local context) { - return Local(); + JsValueRef resolver; + if (JsCreateObject(&resolver) != JsNoError) { + return Local(); + } + + JsValueRef promise, resolve, reject; + if (JsCreatePromise(&promise, &resolve, &reject) != JsNoError) { + return Local(); + } + + if (jsrt::SetProperty(resolver, jsrt::CachedPropertyIdRef::promise, promise) != JsNoError) { + return Local(); + } + + if (jsrt::SetProperty(resolver, jsrt::CachedPropertyIdRef::resolve, resolve) != JsNoError) { + return Local(); + } + + if (jsrt::SetProperty(resolver, jsrt::CachedPropertyIdRef::reject, reject) != JsNoError) { + return Local(); + } + + JsValueRef state; + jsrt::UintToValue(0, &state); + if (jsrt::SetProperty(promise, jsrt::CachedPropertyIdRef::value, state) != JsNoError) { + return Local(); + } + + return Local::New(static_cast(resolver)); } Local Resolver::New(Isolate* isolate) { @@ -33,8 +61,11 @@ namespace v8 { } Local Resolver::GetPromise() { - CHAKRA_ASSERT(false); - return Local(); + JsValueRef promise; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::promise, &promise) != JsNoError) { + return Local(); + } + return Local::New(static_cast(promise)); } Resolver* Resolver::Cast(Value* obj) { @@ -42,7 +73,36 @@ namespace v8 { } Maybe Resolver::Resolve(Local context, Local value) { - return Just(false); + JsValueRef resolve; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::resolve, &resolve) != JsNoError) { + return Nothing(); + } + + JsValueRef promise; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::promise, &promise) != JsNoError) { + return Nothing(); + } + + if (jsrt::SetProperty(promise, jsrt::CachedPropertyIdRef::value, *value) != JsNoError) { + return Nothing(); + } + + JsValueRef state; + jsrt::UintToValue(1, &state); + if (jsrt::SetProperty(promise, jsrt::CachedPropertyIdRef::value, state) != JsNoError) { + return Nothing(); + } + + JsValueRef result; + JsValueRef args[2]; + args[0] = this; // ? What is the "this" of the resolver here? + args[1] = reinterpret_cast(*value); + + if (JsCallFunction(resolve, args, 2, &result) != JsNoError) { + return Nothing(); + } + + return Just(true); } void Resolver::Resolve(Local value) { @@ -51,6 +111,35 @@ namespace v8 { } Maybe Resolver::Reject(Local context, Local value) { - return Just(false); + JsValueRef reject; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::reject, &reject) != JsNoError) { + return Nothing(); + } + + JsValueRef promise; + if (jsrt::GetProperty(this, jsrt::CachedPropertyIdRef::promise, &promise) != JsNoError) { + return Nothing(); + } + + if (jsrt::SetProperty(promise, jsrt::CachedPropertyIdRef::value, *value) != JsNoError) { + return Nothing(); + } + + JsValueRef state; + jsrt::UintToValue(2, &state); + if (jsrt::SetProperty(promise, jsrt::CachedPropertyIdRef::value, state) != JsNoError) { + return Nothing(); + } + + JsValueRef result; + JsValueRef args[2]; + args[0] = this; // ? What is the "this" of the resolver here? + args[1] = reinterpret_cast(*value); + + if (JsCallFunction(reject, args, 2, &result) != JsNoError) { + return Nothing(); + } + + return Just(true); } } // namespace v8