Skip to content

Commit 1d660fe

Browse files
committed
lib,src: use V8 API for collection inspection
Use a new public V8 API for inspecting weak collections and collection iterators, rather than using V8-internal functions to achieve this. This currently comes with a slight modification of the output for inspecting iterators generated by `Set().entries()`. Fixes: nodejs#20409
1 parent 0babe5a commit 1d660fe

File tree

8 files changed

+47
-92
lines changed

8 files changed

+47
-92
lines changed

lib/console.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const {
2929
ERR_INVALID_ARG_VALUE,
3030
},
3131
} = require('internal/errors');
32-
const { previewMapIterator, previewSetIterator } = require('internal/v8');
32+
const { previewEntries } = process.binding('util');
3333
const { Buffer: { isBuffer } } = require('buffer');
3434
const cliTable = require('internal/cli_table');
3535
const util = require('util');
@@ -343,7 +343,7 @@ Console.prototype.table = function(tabularData, properties) {
343343

344344
const mapIter = isMapIterator(tabularData);
345345
if (mapIter)
346-
tabularData = previewMapIterator(tabularData);
346+
tabularData = previewEntries(tabularData);
347347

348348
if (mapIter || isMap(tabularData)) {
349349
const keys = [];
@@ -365,7 +365,7 @@ Console.prototype.table = function(tabularData, properties) {
365365

366366
const setIter = isSetIterator(tabularData);
367367
if (setIter)
368-
tabularData = previewSetIterator(tabularData);
368+
tabularData = previewEntries(tabularData);
369369

370370
const setlike = setIter || isSet(tabularData);
371371
if (setlike) {

lib/internal/bootstrap/node.js

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
// do this good and early, since it handles errors.
3030
setupProcessFatal();
3131

32-
setupV8();
3332
setupProcessICUVersions();
3433

3534
setupGlobalVariables();
@@ -471,22 +470,6 @@
471470
};
472471
}
473472

474-
function setupV8() {
475-
// Warm up the map and set iterator preview functions. V8 compiles
476-
// functions lazily (unless --nolazy is set) so we need to do this
477-
// before we turn off --allow_natives_syntax again.
478-
const v8 = NativeModule.require('internal/v8');
479-
v8.previewMapIterator(new Map().entries());
480-
v8.previewSetIterator(new Set().entries());
481-
v8.previewWeakMap(new WeakMap(), 1);
482-
v8.previewWeakSet(new WeakSet(), 1);
483-
// Disable --allow_natives_syntax again unless it was explicitly
484-
// specified on the command line.
485-
const re = /^--allow[-_]natives[-_]syntax$/;
486-
if (!process.execArgv.some((s) => re.test(s)))
487-
process.binding('v8').setFlagsFromString('--noallow_natives_syntax');
488-
}
489-
490473
function setupProcessICUVersions() {
491474
const icu = process.binding('config').hasIntl ?
492475
process.binding('icu') : undefined;

lib/internal/v8.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

lib/util.js

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,12 @@ const {
3030
const { TextDecoder, TextEncoder } = require('internal/encoding');
3131
const { isBuffer } = require('buffer').Buffer;
3232

33-
const {
34-
previewMapIterator,
35-
previewSetIterator,
36-
previewWeakMap,
37-
previewWeakSet
38-
} = require('internal/v8');
39-
4033
const {
4134
getPromiseDetails,
4235
getProxyDetails,
4336
kPending,
4437
kRejected,
38+
previewEntries
4539
} = process.binding('util');
4640

4741
const { internalBinding } = require('internal/bootstrap/loaders');
@@ -915,7 +909,7 @@ function formatMap(ctx, value, recurseTimes, keys) {
915909

916910
function formatWeakSet(ctx, value, recurseTimes, keys) {
917911
const maxArrayLength = Math.max(ctx.maxArrayLength, 0);
918-
const entries = previewWeakSet(value, maxArrayLength + 1);
912+
const entries = previewEntries(value).slice(0, maxArrayLength + 1);
919913
const maxLength = Math.min(maxArrayLength, entries.length);
920914
let output = new Array(maxLength);
921915
for (var i = 0; i < maxLength; ++i)
@@ -932,16 +926,14 @@ function formatWeakSet(ctx, value, recurseTimes, keys) {
932926

933927
function formatWeakMap(ctx, value, recurseTimes, keys) {
934928
const maxArrayLength = Math.max(ctx.maxArrayLength, 0);
935-
const entries = previewWeakMap(value, maxArrayLength + 1);
936-
// Entries exist as [key1, val1, key2, val2, ...]
937-
const remainder = entries.length / 2 > maxArrayLength;
938-
const len = entries.length / 2 - (remainder ? 1 : 0);
929+
const entries = previewEntries(value).slice(0, maxArrayLength + 1);
930+
const remainder = entries.length > maxArrayLength;
931+
const len = entries.length - (remainder ? 1 : 0);
939932
const maxLength = Math.min(maxArrayLength, len);
940933
let output = new Array(maxLength);
941934
for (var i = 0; i < len; i++) {
942-
const pos = i * 2;
943-
output[i] = `${formatValue(ctx, entries[pos], recurseTimes)} => ` +
944-
formatValue(ctx, entries[pos + 1], recurseTimes);
935+
output[i] = `${formatValue(ctx, entries[i][0], recurseTimes)} => ` +
936+
formatValue(ctx, entries[i][1], recurseTimes);
945937
}
946938
// Sort all entries to have a halfway reliable output (if more entries than
947939
// retrieved ones exist, we can not reliably return the same output).
@@ -953,9 +945,9 @@ function formatWeakMap(ctx, value, recurseTimes, keys) {
953945
return output;
954946
}
955947

956-
function formatCollectionIterator(preview, ctx, value, recurseTimes, keys) {
948+
function formatCollectionIterator(ctx, value, recurseTimes, keys) {
957949
const output = [];
958-
for (const entry of preview(value)) {
950+
for (const entry of previewEntries(value)) {
959951
if (ctx.maxArrayLength === output.length) {
960952
output.push('... more items');
961953
break;
@@ -969,13 +961,11 @@ function formatCollectionIterator(preview, ctx, value, recurseTimes, keys) {
969961
}
970962

971963
function formatMapIterator(ctx, value, recurseTimes, keys) {
972-
return formatCollectionIterator(previewMapIterator, ctx, value, recurseTimes,
973-
keys);
964+
return formatCollectionIterator(ctx, value, recurseTimes, keys);
974965
}
975966

976967
function formatSetIterator(ctx, value, recurseTimes, keys) {
977-
return formatCollectionIterator(previewSetIterator, ctx, value, recurseTimes,
978-
keys);
968+
return formatCollectionIterator(ctx, value, recurseTimes, keys);
979969
}
980970

981971
function formatPromise(ctx, value, recurseTimes, keys) {

node.gyp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@
146146
'lib/internal/http2/core.js',
147147
'lib/internal/http2/compat.js',
148148
'lib/internal/http2/util.js',
149-
'lib/internal/v8.js',
150149
'lib/internal/v8_prof_polyfill.js',
151150
'lib/internal/v8_prof_processor.js',
152151
'lib/internal/validators.js',

src/node.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4355,12 +4355,6 @@ void Init(int* argc,
43554355
}
43564356
#endif
43574357

4358-
// Needed for access to V8 intrinsics. Disabled again during bootstrapping,
4359-
// see lib/internal/bootstrap/node.js.
4360-
const char allow_natives_syntax[] = "--allow_natives_syntax";
4361-
V8::SetFlagsFromString(allow_natives_syntax,
4362-
sizeof(allow_natives_syntax) - 1);
4363-
43644358
// We should set node_is_initialized here instead of in node::Start,
43654359
// otherwise embedders using node::Init to initialize everything will not be
43664360
// able to set it and native modules will not load for them.

src/node_util.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,35 @@ static void GetProxyDetails(const FunctionCallbackInfo<Value>& args) {
4949
args.GetReturnValue().Set(ret);
5050
}
5151

52+
static void PreviewEntries(const FunctionCallbackInfo<Value>& args) {
53+
if (!args[0]->IsObject())
54+
return;
55+
56+
bool is_key_value;
57+
Local<Array> entries;
58+
if (!args[0].As<Object>()->PreviewEntries(&is_key_value).ToLocal(&entries))
59+
return;
60+
if (!is_key_value)
61+
return args.GetReturnValue().Set(entries);
62+
63+
uint32_t length = entries->Length();
64+
CHECK_EQ(length % 2, 0);
65+
66+
Environment* env = Environment::GetCurrent(args);
67+
Local<Context> context = env->context();
68+
69+
Local<Array> pairs = Array::New(env->isolate(), length / 2);
70+
for (uint32_t i = 0; i < length / 2; i++) {
71+
Local<Array> pair = Array::New(env->isolate(), 2);
72+
pair->Set(context, 0, entries->Get(context, i * 2).ToLocalChecked())
73+
.FromJust();
74+
pair->Set(context, 1, entries->Get(context, i * 2 + 1).ToLocalChecked())
75+
.FromJust();
76+
pairs->Set(context, i, pair).FromJust();
77+
}
78+
args.GetReturnValue().Set(pairs);
79+
}
80+
5281
// Side effect-free stringification that will never throw exceptions.
5382
static void SafeToString(const FunctionCallbackInfo<Value>& args) {
5483
auto context = args.GetIsolate()->GetCurrentContext();
@@ -188,6 +217,7 @@ void Initialize(Local<Object> target,
188217
env->SetMethod(target, "getPromiseDetails", GetPromiseDetails);
189218
env->SetMethod(target, "getProxyDetails", GetProxyDetails);
190219
env->SetMethod(target, "safeToString", SafeToString);
220+
env->SetMethod(target, "previewEntries", PreviewEntries);
191221

192222
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);
193223
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog);

test/parallel/test-util-inspect.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@
1919
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

22-
// Flags: --expose_internals
2322
'use strict';
2423
const common = require('../common');
2524
const assert = require('assert');
2625
const JSStream = process.binding('js_stream').JSStream;
2726
const util = require('util');
2827
const vm = require('vm');
29-
const { previewMapIterator } = require('internal/v8');
28+
const { previewEntries } = process.binding('util');
3029

3130
assert.strictEqual(util.inspect(1), '1');
3231
assert.strictEqual(util.inspect(false), 'false');
@@ -448,7 +447,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324');
448447
{
449448
const map = new Map();
450449
map.set(1, 2);
451-
const vals = previewMapIterator(map.entries());
450+
const vals = previewEntries(map.entries());
452451
const valsOutput = [];
453452
for (const o of vals) {
454453
valsOutput.push(o);
@@ -935,8 +934,7 @@ if (typeof Symbol !== 'undefined') {
935934
const aSet = new Set([1, 3]);
936935
assert.strictEqual(util.inspect(aSet.keys()), '[Set Iterator] { 1, 3 }');
937936
assert.strictEqual(util.inspect(aSet.values()), '[Set Iterator] { 1, 3 }');
938-
assert.strictEqual(util.inspect(aSet.entries()),
939-
'[Set Iterator] { [ 1, 1 ], [ 3, 3 ] }');
937+
assert.strictEqual(util.inspect(aSet.entries()), '[Set Iterator] { 1, 3 }');
940938
// Make sure the iterator doesn't get consumed.
941939
const keys = aSet.keys();
942940
assert.strictEqual(util.inspect(keys), '[Set Iterator] { 1, 3 }');

0 commit comments

Comments
 (0)