Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
chakrashim: fix internal promise behavior
Browse files Browse the repository at this point in the history
`test-promise-internal-creation` was failing because of the `state` and
`result` properties we were attaching to it.  Moved those fields into
the external object.

This change also enables more promise tests.

PR-URL: #471
Reviewed-By: Jimmy Thomson <jithomso@microsoft.com>
Reviewed-By: Taylor Woll <tawoll@ntdev.microsoft.com>
  • Loading branch information
kfarnung committed Mar 7, 2018
1 parent 091a972 commit c31ab73
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 201 deletions.
1 change: 0 additions & 1 deletion deps/chakrashim/chakrashim.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
'src/v8persistent.cc',
'src/v8private.cc',
'src/v8promise.cc',
'src/v8resolver.cc',
'src/v8propertydescriptor.cc',
'src/v8proxy.cc',
'src/v8regexp.cc',
Expand Down
166 changes: 146 additions & 20 deletions deps/chakrashim/src/v8promise.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,100 @@
#include "v8chakra.h"
#include "jsrtutils.h"

#include <array>

namespace v8 {

class PromiseResolverData : public ExternalData {
public:
static const ExternalDataTypes ExternalDataType =
ExternalDataTypes::PromiseResolverData;

private:
Persistent<Value> resolve;
Persistent<Value> reject;
Persistent<Value> result;
Promise::PromiseState state;

public:
PromiseResolverData(Local<Value> resolve,
Local<Value> reject)
: ExternalData(ExternalDataType),
resolve(nullptr, resolve),
reject(nullptr, reject),
state(Promise::PromiseState::kPending) {}

~PromiseResolverData() {
this->resolve.Reset();
this->reject.Reset();
this->result.Reset();
}

static void CHAKRA_CALLBACK FinalizeCallback(void *data) {
if (data != nullptr) {
PromiseResolverData* promiseResolverData =
reinterpret_cast<PromiseResolverData*>(data);
delete promiseResolverData;
}
}

Promise::PromiseState State() {
return this->state;
}

Local<Value> Result() {
return Local<Value>::New(nullptr, this->result);
}

JsErrorCode Resolve(Local<Value> value) {
JsValueRef result = nullptr;
std::array<JsValueRef, 2> args = { jsrt::GetUndefined(), *value };
JsErrorCode err = JsCallFunction(*this->resolve, args.data(), args.size(),
&result);

if (err == JsNoError) {
this->state = Promise::PromiseState::kFulfilled;
this->result = value;
}

return err;
}

JsErrorCode Reject(Local<Value> value) {
JsValueRef result = nullptr;
std::array<JsValueRef, 2> args = { jsrt::GetUndefined(), *value };
JsErrorCode err = JsCallFunction(*this->reject, args.data(), args.size(),
&result);

if (err == JsNoError) {
this->state = Promise::PromiseState::kRejected;
this->result = value;
}

return err;
}
};

Promise::Promise() { }

Local<Value> Promise::Result() {
JsValueRef value;
if (jsrt::GetProperty(
this,
jsrt::CachedPropertyIdRef::value,
&value) != JsNoError) {
PromiseResolverData* data = nullptr;
if (!ExternalData::TryGetFromProperty(this, jsrt::GetExternalPropertyId(),
&data)) {
return Local<Value>();
}
return Local<Value>::New(value);

return data->Result();
}

Promise::PromiseState Promise::State() {
JsValueRef state;
if (jsrt::GetProperty(
this,
jsrt::CachedPropertyIdRef::state,
&state) != JsNoError) {
return PromiseState::kPending;
}
int stateNumber;
if (JsNumberToInt(state, &stateNumber) != JsNoError) {
PromiseResolverData* data = nullptr;
if (!ExternalData::TryGetFromProperty(this, jsrt::GetExternalPropertyId(),
&data)) {
return PromiseState::kPending;
}
switch (stateNumber) {
case 1: return PromiseState::kFulfilled;
case 2: return PromiseState::kRejected;
default: return PromiseState::kPending;
}

return data->State();
}

MaybeLocal<Promise> Promise::Then(Local<Context> context,
Expand All @@ -72,4 +134,68 @@ Promise* Promise::Cast(Value* obj) {
return static_cast<Promise*>(obj);
}

MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
JsValueRef promise, resolve, reject;
if (JsCreatePromise(&promise, &resolve, &reject) != JsNoError) {
return Local<Promise::Resolver>();
}

PromiseResolverData* data = new PromiseResolverData(resolve, reject);
if (jsrt::AddExternalData(
promise, data, PromiseResolverData::FinalizeCallback) != JsNoError) {
delete data;
return Local<Promise::Resolver>();
}

return Local<Promise::Resolver>::New(promise);
}

Local<Promise::Resolver> Promise::Resolver::New(Isolate* isolate) {
return New(isolate->GetCurrentContext()).ToLocalChecked();
}

Local<Promise> Promise::Resolver::GetPromise() {
return Local<Promise>::New(static_cast<JsValueRef>(this));
}

Promise::Resolver* Promise::Resolver::Cast(Value* obj) {
CHAKRA_ASSERT(obj->IsPromise());
return static_cast<Promise::Resolver*>(obj);
}

Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
Local<Value> value) {
PromiseResolverData* data = nullptr;
if (!ExternalData::TryGetFromProperty(this, jsrt::GetExternalPropertyId(),
&data)) {
return Nothing<bool>();
}

if (data->Resolve(value) != JsNoError) {
return Nothing<bool>();
}

return Just(true);
}

void Promise::Resolver::Resolve(Local<Value> value) {
Local<Context> context;
Resolve(context, value);
}

Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
Local<Value> value) {
PromiseResolverData* data = nullptr;
if (!ExternalData::TryGetFromProperty(this, jsrt::GetExternalPropertyId(),
&data)) {
return Nothing<bool>();
}

if (data->Reject(value) != JsNoError) {
return Nothing<bool>();
}

return Just(true);
}

} // namespace v8
174 changes: 0 additions & 174 deletions deps/chakrashim/src/v8resolver.cc

This file was deleted.

Loading

0 comments on commit c31ab73

Please sign in to comment.