Skip to content
Permalink
Browse files

util: use V8 C++ API for inspecting Promises

PR-URL: #12254
Refs: #11875
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Josh Gavant <josh.gavant@outlook.com>
  • Loading branch information...
TimothyGu committed Apr 6, 2017
1 parent afd5966 commit a37273c1e4b93ed048e1d45818fe6c525480b121
Showing with 54 additions and 38 deletions.
  1. +24 −38 lib/util.js
  2. +30 −0 src/node_util.cc
@@ -302,16 +302,6 @@ function ensureDebugIsInitialized() {
}


function inspectPromise(p) {
// Only create a mirror if the object is a Promise.
if (!binding.isPromise(p))
return null;
ensureDebugIsInitialized();
const mirror = Debug.MakeMirror(p, true);
return {status: mirror.status(), value: mirror.promiseValue().value_};
}


function formatValue(ctx, value, recurseTimes) {
if (ctx.showProxy &&
((typeof value === 'object' && value !== null) ||
@@ -527,30 +517,25 @@ function formatValue(ctx, value, recurseTimes) {
'byteOffset',
'buffer');
}
} else if (binding.isPromise(value)) {
braces = ['{', '}'];
formatter = formatPromise;
} else if (binding.isMapIterator(value)) {
constructor = { name: 'MapIterator' };
braces = ['{', '}'];
empty = false;
formatter = formatCollectionIterator;
} else if (binding.isSetIterator(value)) {
constructor = { name: 'SetIterator' };
braces = ['{', '}'];
empty = false;
formatter = formatCollectionIterator;
} else {
var promiseInternals = inspectPromise(value);
if (promiseInternals) {
braces = ['{', '}'];
formatter = formatPromise;
} else {
if (binding.isMapIterator(value)) {
constructor = { name: 'MapIterator' };
braces = ['{', '}'];
empty = false;
formatter = formatCollectionIterator;
} else if (binding.isSetIterator(value)) {
constructor = { name: 'SetIterator' };
braces = ['{', '}'];
empty = false;
formatter = formatCollectionIterator;
} else {
// Unset the constructor to prevent "Object {...}" for ordinary objects.
if (constructor && constructor.name === 'Object')
constructor = null;
braces = ['{', '}'];
empty = true; // No other data than keys.
}
}
// Unset the constructor to prevent "Object {...}" for ordinary objects.
if (constructor && constructor.name === 'Object')
constructor = null;
braces = ['{', '}'];
empty = true; // No other data than keys.
}
empty = empty === true && keys.length === 0;
@@ -779,14 +764,15 @@ function formatCollectionIterator(ctx, value, recurseTimes, visibleKeys, keys) {
}

function formatPromise(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
var internals = inspectPromise(value);
if (internals.status === 'pending') {
const output = [];
const [state, result] = binding.getPromiseDetails(value);

if (state === binding.kPending) {
output.push('<pending>');
} else {
var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1;
var str = formatValue(ctx, internals.value, nextRecurseTimes);
if (internals.status === 'rejected') {
var str = formatValue(ctx, result, nextRecurseTimes);
if (state === binding.kRejected) {
output.push('<rejected> ' + str);
} else {
output.push(str);
@@ -14,6 +14,7 @@ using v8::Integer;
using v8::Local;
using v8::Object;
using v8::Private;
using v8::Promise;
using v8::Proxy;
using v8::Value;

@@ -43,6 +44,24 @@ using v8::Value;
VALUE_METHOD_MAP(V)
#undef V

static void GetPromiseDetails(const FunctionCallbackInfo<Value>& args) {
// Return undefined if it's not a Promise.
if (!args[0]->IsPromise())
return;

auto isolate = args.GetIsolate();

Local<Promise> promise = args[0].As<Promise>();
Local<Array> ret = Array::New(isolate, 2);

int state = promise->State();
ret->Set(0, Integer::New(isolate, state));
if (state != Promise::PromiseState::kPending)
ret->Set(1, promise->Result());

args.GetReturnValue().Set(ret);
}

static void GetProxyDetails(const FunctionCallbackInfo<Value>& args) {
// Return undefined if it's not a proxy.
if (!args[0]->IsProxy())
@@ -148,8 +167,19 @@ void Initialize(Local<Object> target,
Integer::NewFromUnsigned(env->isolate(), NODE_PUSH_VAL_TO_ARRAY_MAX),
v8::ReadOnly).FromJust();

#define V(name) \
target->Set(context, \
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
Integer::New(env->isolate(), Promise::PromiseState::name)) \
.FromJust()
V(kPending);
V(kFulfilled);
V(kRejected);
#undef V

env->SetMethod(target, "getHiddenValue", GetHiddenValue);
env->SetMethod(target, "setHiddenValue", SetHiddenValue);
env->SetMethod(target, "getPromiseDetails", GetPromiseDetails);
env->SetMethod(target, "getProxyDetails", GetProxyDetails);

env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);

0 comments on commit a37273c

Please sign in to comment.
You can’t perform that action at this time.