diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 13ec60f7773381..b7621dc5d71ac3 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -63,6 +63,7 @@ const { kRejected, previewEntries, getConstructorName: internalGetConstructorName, + getExternalValue, propertyFilter: { ALL_PROPERTIES, ONLY_ENUMERABLE @@ -977,8 +978,10 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { } } else { if (keys.length === 0 && protoProps === undefined) { - if (isExternal(value)) - return ctx.stylize('[External]', 'special'); + if (isExternal(value)) { + const address = getExternalValue(value); + return ctx.stylize(`[External: ${address}]`, 'special'); + } return `${getCtxStyle(value, constructor, tag)}{}`; } braces[0] = `${getCtxStyle(value, constructor, tag)}{`; diff --git a/src/node_util.cc b/src/node_util.cc index 44148ba2b0958a..3571dff5fd671b 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -11,6 +11,7 @@ using v8::Array; using v8::ArrayBufferView; using v8::Boolean; using v8::Context; +using v8::External; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Global; @@ -19,6 +20,7 @@ using v8::Integer; using v8::Isolate; using v8::KeyCollectionMode; using v8::Local; +using v8::MaybeLocal; using v8::Object; using v8::ONLY_CONFIGURABLE; using v8::ONLY_ENUMERABLE; @@ -68,6 +70,20 @@ static void GetConstructorName( args.GetReturnValue().Set(name); } +static void GetExternalValue( + const FunctionCallbackInfo& args) { + CHECK(args[0]->IsExternal()); + auto isolate = args.GetIsolate(); + Local external = args[0].As(); + + void* ptr = external->Value(); + char val[20]; + snprintf(val, sizeof(val), "%p", ptr); + + MaybeLocal ret = String::NewFromUtf8(isolate, val); + args.GetReturnValue().Set(ret.ToLocalChecked()); +} + static void GetPromiseDetails(const FunctionCallbackInfo& args) { // Return undefined if it's not a Promise. if (!args[0]->IsPromise()) @@ -314,6 +330,7 @@ void Initialize(Local target, env->SetMethodNoSideEffect(target, "getOwnNonIndexProperties", GetOwnNonIndexProperties); env->SetMethodNoSideEffect(target, "getConstructorName", GetConstructorName); + env->SetMethodNoSideEffect(target, "getExternalValue", GetExternalValue); env->SetMethod(target, "sleep", Sleep); env->SetMethod(target, "arrayBufferViewHasBuffer", ArrayBufferViewHasBuffer); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 78184d85f6e9f3..7a8fb32bc1ef9b 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -147,8 +147,8 @@ assert.strictEqual( "[String: 'hello'] { [length]: 5, [Symbol(foo)]: 123 }" ); -assert.strictEqual(util.inspect((new JSStream())._externalStream), - '[External]'); +assert.match(util.inspect((new JSStream())._externalStream), + /^\[External: .*?\]$/); { const regexp = /regexp/;