Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
repl: Enable tab completion for global properties.
When `useGlobal` is false, tab completion in the repl does not enumerate
global properties. Instead of just setting these properties blindly on
the global context, e.g.

    context[prop] = global[prop]

Use `Object.defineProperty` and the property descriptor found on
`global` for the new property in `context`.

Also addresses a previously unnoticed issue where `console` is writable
when `useGlobal` is false.

Ref: #7353
  • Loading branch information
lance committed Jun 27, 2016
commit dcaf20b30459f355cf885b3189f07f0b2eaff253
18 changes: 14 additions & 4 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,20 @@ REPLServer.prototype.createContext = function() {
context = global;
} else {
context = vm.createContext();
for (var i in global) context[i] = global[i];
context.console = new Console(this.outputStream);
context.global = context;
context.global.global = context;
const _console = new Console(this.outputStream);
Object.getOwnPropertyNames(global).forEach((name) => {
if (name === 'console') {
Object.defineProperty(context, name, {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does global in the inner context refer to now? I think it should still be context, right?

(The second line here also seems to have been superfluous?)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both lines should stay the same

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@addaleax - yes, this was an oversight...

configurable: true,
enumerable: true,
value: _console
});
}
else {
Object.defineProperty(context, name,
Object.getOwnPropertyDescriptor(global, name));
}
});
}

const module = new Module('<repl>');
Expand Down
3 changes: 3 additions & 0 deletions test/parallel/test-repl-console.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ assert(r.context.console);

// ensure that the repl console instance is not the global one
assert.notStrictEqual(r.context.console, console);

// ensure that the repl console instance does not have a setter
assert.throws(() => r.context.console = 'foo', TypeError);
11 changes: 11 additions & 0 deletions test/parallel/test-repl-tab-complete.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,14 @@ putIn.run(['.clear']);
testMe.complete('.b', common.mustCall((error, data) => {
assert.deepStrictEqual(data, [['break'], 'b']);
}));

var testNonGlobal = repl.start({
input: putIn,
output: putIn,
useGlobal: false
});

testNonGlobal.complete('I', common.mustCall((error, data) => {
assert.deepStrictEqual(data, [['Infinity', '', 'Int16Array', 'Int32Array',
'Int8Array', 'Intl'], 'I']);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intl will not be there if node binary is not built with intl support. May want to make the inclusion of Intl here conditional

}));