util: use V8 C++ API for inspecting Promises
PR-URL: https://github.com/nodejs/node/pull/12254 Refs: https://github.com/nodejs/node/issues/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>
This commit is contained in:
parent
afd5966fa9
commit
a37273c1e4
62
lib/util.js
62
lib/util.js
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user