Skip to content

Commit 0b340ab

Browse files
BridgeARtargos
authored andcommitted
repl: tab auto complete big arrays
Due to a new API it's possible to skip the indices. That allows to use auto completion with big (typed) arrays. PR-URL: #22408 Fixes: #21446 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent acfb29c commit 0b340ab

File tree

5 files changed

+51
-54
lines changed

5 files changed

+51
-54
lines changed

lib/internal/util.js

-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ function isInsideNodeModules() {
364364
return false;
365365
}
366366

367-
368367
module.exports = {
369368
assertCrypto,
370369
cachedResult,

lib/internal/util/comparisons.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ const { compare } = process.binding('buffer');
44
const { isArrayBufferView } = require('internal/util/types');
55
const { internalBinding } = require('internal/bootstrap/loaders');
66
const { isDate, isMap, isRegExp, isSet } = internalBinding('types');
7-
const { getOwnNonIndexProperties } = process.binding('util');
7+
const {
8+
getOwnNonIndexProperties,
9+
propertyFilter: {
10+
ONLY_ENUMERABLE
11+
}
12+
} = process.binding('util');
813

914
const ReflectApply = Reflect.apply;
1015

@@ -107,8 +112,9 @@ function strictDeepEqual(val1, val2, memos) {
107112
if (val1.length !== val2.length) {
108113
return false;
109114
}
110-
const keys1 = getOwnNonIndexProperties(val1);
111-
if (keys1.length !== getOwnNonIndexProperties(val2).length) {
115+
const keys1 = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
116+
const keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
117+
if (keys1.length !== keys2.length) {
112118
return false;
113119
}
114120
return keyCheck(val1, val2, kStrict, memos, kIsArray, keys1);
@@ -139,8 +145,9 @@ function strictDeepEqual(val1, val2, memos) {
139145
// Buffer.compare returns true, so val1.length === val2.length. If they both
140146
// only contain numeric keys, we don't need to exam further than checking
141147
// the symbols.
142-
const keys1 = getOwnNonIndexProperties(val1);
143-
if (keys1.length !== getOwnNonIndexProperties(val2).length) {
148+
const keys1 = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
149+
const keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
150+
if (keys1.length !== keys2.length) {
144151
return false;
145152
}
146153
return keyCheck(val1, val2, kStrict, memos, kNoIterator, keys1);

lib/repl.js

+9-27
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ const {
5252
isIdentifierChar
5353
} = require('internal/deps/acorn/dist/acorn');
5454
const internalUtil = require('internal/util');
55-
const { isTypedArray } = require('internal/util/types');
5655
const util = require('util');
5756
const utilBinding = process.binding('util');
5857
const { inherits } = util;
@@ -74,6 +73,13 @@ const {
7473
const { sendInspectorCommand } = require('internal/util/inspector');
7574
const { experimentalREPLAwait } = process.binding('config');
7675
const { isRecoverableError } = require('internal/repl/recoverable');
76+
const {
77+
getOwnNonIndexProperties,
78+
propertyFilter: {
79+
ALL_PROPERTIES,
80+
SKIP_SYMBOLS
81+
}
82+
} = process.binding('util');
7783

7884
// Lazy-loaded.
7985
let processTopLevelAwait;
@@ -927,34 +933,10 @@ function isIdentifier(str) {
927933
return true;
928934
}
929935

930-
const ARRAY_LENGTH_THRESHOLD = 1e6;
931-
932-
function mayBeLargeObject(obj) {
933-
if (Array.isArray(obj)) {
934-
return obj.length > ARRAY_LENGTH_THRESHOLD ? ['length'] : null;
935-
} else if (isTypedArray(obj)) {
936-
return obj.length > ARRAY_LENGTH_THRESHOLD ? [] : null;
937-
}
938-
939-
return null;
940-
}
941-
942936
function filteredOwnPropertyNames(obj) {
943937
if (!obj) return [];
944-
const fakeProperties = mayBeLargeObject(obj);
945-
if (fakeProperties !== null) {
946-
this.outputStream.write('\r\n');
947-
process.emitWarning(
948-
'The current array, Buffer or TypedArray has too many entries. ' +
949-
'Certain properties may be missing from completion output.',
950-
'REPLWarning',
951-
undefined,
952-
undefined,
953-
true);
954-
955-
return fakeProperties;
956-
}
957-
return Object.getOwnPropertyNames(obj).filter(isIdentifier);
938+
const filter = ALL_PROPERTIES | SKIP_SYMBOLS;
939+
return getOwnNonIndexProperties(obj, filter).filter(isIdentifier);
958940
}
959941

960942
function getGlobalLexicalScopeNames(contextId) {

src/node_util.cc

+26-6
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,43 @@
44
namespace node {
55
namespace util {
66

7+
using v8::ALL_PROPERTIES;
78
using v8::Array;
89
using v8::Context;
910
using v8::FunctionCallbackInfo;
1011
using v8::Integer;
1112
using v8::Local;
1213
using v8::Object;
14+
using v8::ONLY_CONFIGURABLE;
15+
using v8::ONLY_ENUMERABLE;
16+
using v8::ONLY_WRITABLE;
1317
using v8::Private;
1418
using v8::Promise;
1519
using v8::Proxy;
20+
using v8::SKIP_STRINGS;
21+
using v8::SKIP_SYMBOLS;
1622
using v8::String;
23+
using v8::Uint32;
1724
using v8::Value;
1825

1926
static void GetOwnNonIndexProperties(
2027
const FunctionCallbackInfo<Value>& args) {
2128
Environment* env = Environment::GetCurrent(args);
2229
Local<Context> context = env->context();
2330

24-
if (!args[0]->IsObject())
25-
return;
31+
CHECK(args[0]->IsObject());
32+
CHECK(args[1]->IsUint32());
33+
34+
Local<Object> object = args[0].As<Object>();
2635

27-
v8::Local<v8::Object> object = args[0].As<v8::Object>();
36+
Local<Array> properties;
2837

29-
// Return only non-enumerable properties by default.
30-
v8::Local<v8::Array> properties;
38+
v8::PropertyFilter filter =
39+
static_cast<v8::PropertyFilter>(args[1].As<Uint32>()->Value());
3140

3241
if (!object->GetPropertyNames(
3342
context, v8::KeyCollectionMode::kOwnOnly,
34-
v8::ONLY_ENUMERABLE,
43+
filter,
3544
v8::IndexFilter::kSkipIndices)
3645
.ToLocal(&properties)) {
3746
return;
@@ -209,6 +218,17 @@ void Initialize(Local<Object> target,
209218
WatchdogHasPendingSigint);
210219

211220
env->SetMethod(target, "safeGetenv", SafeGetenv);
221+
222+
Local<Object> constants = Object::New(env->isolate());
223+
NODE_DEFINE_CONSTANT(constants, ALL_PROPERTIES);
224+
NODE_DEFINE_CONSTANT(constants, ONLY_WRITABLE);
225+
NODE_DEFINE_CONSTANT(constants, ONLY_ENUMERABLE);
226+
NODE_DEFINE_CONSTANT(constants, ONLY_CONFIGURABLE);
227+
NODE_DEFINE_CONSTANT(constants, SKIP_STRINGS);
228+
NODE_DEFINE_CONSTANT(constants, SKIP_SYMBOLS);
229+
target->Set(context,
230+
FIXED_ONE_BYTE_STRING(env->isolate(), "propertyFilter"),
231+
constants).FromJust();
212232
}
213233

214234
} // namespace util

test/parallel/test-repl-tab-complete.js

+4-15
Original file line numberDiff line numberDiff line change
@@ -393,12 +393,6 @@ testMe.complete('obj.', common.mustCall((error, data) => {
393393
assert(data[0].includes('obj.key'));
394394
}));
395395

396-
// tab completion for large buffer
397-
const warningRegEx = new RegExp(
398-
'\\(node:\\d+\\) REPLWarning: The current array, Buffer or TypedArray has ' +
399-
'too many entries\\. Certain properties may be missing from completion ' +
400-
'output\\.');
401-
402396
[
403397
Array,
404398
Buffer,
@@ -428,11 +422,7 @@ const warningRegEx = new RegExp(
428422
putIn.run([`var ele = new ${type.name}(1e6 + 1); ele.biu = 1;`]);
429423
}
430424

431-
common.hijackStderr(common.mustCall((err) => {
432-
process.nextTick(() => {
433-
assert.ok(warningRegEx.test(err));
434-
});
435-
}));
425+
common.hijackStderr(common.mustNotCall());
436426
testMe.complete('ele.', common.mustCall((err, data) => {
437427
common.restoreStderr();
438428
assert.ifError(err);
@@ -443,13 +433,12 @@ const warningRegEx = new RegExp(
443433
Buffer.alloc(0) :
444434
new type(0));
445435

436+
assert.strictEqual(data[0].includes('ele.biu'), true);
437+
446438
data[0].forEach((key) => {
447-
if (!key) return;
439+
if (!key || key === 'ele.biu') return;
448440
assert.notStrictEqual(ele[key.substr(4)], undefined);
449441
});
450-
451-
// no `biu`
452-
assert.strictEqual(data.includes('ele.biu'), false);
453442
}));
454443
});
455444

0 commit comments

Comments
 (0)