repl: filter integer keys from repl tab complete list

Refactored version of https://github.com/joyent/node/pull/25819

Removes integer keys (and keys starting with numbers) from
candidate list on repl tab complete. Refactored the originally
submitted change to simplify and ensure that the integer keys
do not show up on objects either.

Reviewed By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/2409
This commit is contained in:
James M Snell
2015-08-17 12:03:32 -07:00
parent 43660ad37b
commit ce145bf358
2 changed files with 83 additions and 4 deletions

View File

@@ -561,6 +561,15 @@ const requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/;
const simpleExpressionRE =
/(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
function intFilter(item) {
// filters out anything not starting with A-Z, a-z, $ or _
return /^[A-Za-z_$]/.test(item);
}
function filteredOwnPropertyNames(obj) {
if (!obj) return [];
return Object.getOwnPropertyNames(obj).filter(intFilter);
}
// Provide a list of completions for the given leading text. This is
// given to the readline interface for handling tab completion.
@@ -705,9 +714,9 @@ REPLServer.prototype.complete = function(line, callback) {
if (this.useGlobal || vm.isContext(this.context)) {
var contextProto = this.context;
while (contextProto = Object.getPrototypeOf(contextProto)) {
completionGroups.push(Object.getOwnPropertyNames(contextProto));
completionGroups.push(filteredOwnPropertyNames(contextProto));
}
completionGroups.push(Object.getOwnPropertyNames(this.context));
completionGroups.push(filteredOwnPropertyNames(this.context));
addStandardGlobals(completionGroups, filter);
completionGroupsLoaded();
} else {
@@ -733,7 +742,7 @@ REPLServer.prototype.complete = function(line, callback) {
if (obj != null) {
if (typeof obj === 'object' || typeof obj === 'function') {
try {
memberGroups.push(Object.getOwnPropertyNames(obj));
memberGroups.push(filteredOwnPropertyNames(obj));
} catch (ex) {
// Probably a Proxy object without `getOwnPropertyNames` trap.
// We simply ignore it here, as we don't want to break the
@@ -751,7 +760,7 @@ REPLServer.prototype.complete = function(line, callback) {
p = obj.constructor ? obj.constructor.prototype : null;
}
while (p !== null) {
memberGroups.push(Object.getOwnPropertyNames(p));
memberGroups.push(filteredOwnPropertyNames(p));
p = Object.getPrototypeOf(p);
// Circular refs possible? Let's guard against that.
sentinel--;

View File

@@ -248,3 +248,73 @@ testMe.complete('proxy.', common.mustCall(function(error, data) {
assert.strictEqual(error, null);
assert.deepEqual(data, [[], 'proxy.']);
}));
// Make sure tab completion does not include integer members of an Array
var array_elements = [ [
'ary.__defineGetter__',
'ary.__defineSetter__',
'ary.__lookupGetter__',
'ary.__lookupSetter__',
'ary.__proto__',
'ary.constructor',
'ary.hasOwnProperty',
'ary.isPrototypeOf',
'ary.propertyIsEnumerable',
'ary.toLocaleString',
'ary.toString',
'ary.valueOf',
'',
'ary.concat',
'ary.entries',
'ary.every',
'ary.filter',
'ary.forEach',
'ary.indexOf',
'ary.join',
'ary.keys',
'ary.lastIndexOf',
'ary.length',
'ary.map',
'ary.pop',
'ary.push',
'ary.reduce',
'ary.reduceRight',
'ary.reverse',
'ary.shift',
'ary.slice',
'ary.some',
'ary.sort',
'ary.splice',
'ary.unshift' ],
'ary.'];
putIn.run(['.clear']);
putIn.run(['var ary = [1,2,3];']);
testMe.complete('ary.', common.mustCall(function(error, data) {
assert.deepEqual(data, array_elements);
}));
// Make sure tab completion does not include integer keys in an object
var obj_elements = [ [
'obj.__defineGetter__',
'obj.__defineSetter__',
'obj.__lookupGetter__',
'obj.__lookupSetter__',
'obj.__proto__',
'obj.constructor',
'obj.hasOwnProperty',
'obj.isPrototypeOf',
'obj.propertyIsEnumerable',
'obj.toLocaleString',
'obj.toString',
'obj.valueOf',
'',
'obj.a' ],
'obj.' ];
putIn.run(['.clear']);
putIn.run(['var obj = {1:"a","1a":"b",a:"b"};']);
testMe.complete('obj.', common.mustCall(function(error, data) {
assert.deepEqual(data, obj_elements);
}));