Skip to content

Commit

Permalink
globals: introduce prompt on global
Browse files Browse the repository at this point in the history
  • Loading branch information
Ayase-252 committed May 5, 2021
1 parent efd70f4 commit fcde071
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,5 +333,6 @@ module.exports = {
btoa: 'readable',
atob: 'readable',
performance: 'readable',
prompt: 'readable'
},
};
20 changes: 20 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,26 @@ added: v0.1.7

The process object. See the [`process` object][] section.

## `prompt([message[, defaultValue]])`
<!-- YAML
added: REPLACEME
-->

<!-- type=global -->

* `message` {string} Optional, Message shown to user. Default: `'prompt'`.
* `defaultValue` {string} Optional, Returned value when user inputs the
empty string.
* Returns: {string|null}

`prompt()` the given message and waits for the user's input.
If the `stdin` is not interactive, it returns `null`.
If default value is not given and the user's input is empty string, it also
returns `null`.
If default value is given and the user's input is empty string, it returns
`defaultValue`.
Otherwise, it returns the user's input as `string`.

## `queueMicrotask(callback)`
<!-- YAML
added: v11.0.0
Expand Down
55 changes: 55 additions & 0 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const {
ObjectSetPrototypeOf,
ReflectGet,
ReflectSet,
Uint8Array,
SymbolToStringTag,
globalThis,
} = primordials;
Expand Down Expand Up @@ -246,6 +247,60 @@ if (!config.noBrowserGlobals) {
return performance;
});

defineOperation(globalThis, 'prompt', function prompt(
message = 'prompt',
defaultValue
) {
const { validateString } = require('internal/validators');
validateString(message);
if (defaultValue !== undefined) {
validateString(defaultValue);
}

defaultValue ??= null;
if (!process.stdin.isTTY) {
return null;
}

process.stdout.write(message + '\r\n');
const res = readFromStdInSync();
return res || defaultValue;

// Mimic implementation of `prompt` of deno
function readFromStdInSync() {
const fs = require('fs');
const LF = '\n'.charCodeAt(0);
const CR = '\r'.charCodeAt(0);
const charaBuf = new Uint8Array(1);
const stdfd = process.platform === 'win32' ?
process.stdin.fd :
fs.openSync('/dev/tty', 'r');
const res = [];

while (true) {
const bytesRead = fs.readSync(stdfd, charaBuf, 0, 1);
if (bytesRead === 0) {
break;
}
if (charaBuf[0] === CR) {
const bytesRead = fs.readSync(stdfd, charaBuf, 0, 1);
if (charaBuf[0] === LF) {
break;
}
res.push(CR);
if (bytesRead === 0) {
break;
}
}
if (charaBuf[0] === LF) {
break;
}
res.push(charaBuf[0]);
}
return new TextDecoder().decode(new Uint8Array(res));
}
});

// Non-standard extensions:
defineOperation(globalThis, 'clearImmediate', timers.clearImmediate);
defineOperation(globalThis, 'setImmediate', timers.setImmediate);
Expand Down
4 changes: 4 additions & 0 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ if (global.performance) {
knownGlobals.push(global.performance);
}

if (global.prompt) {
knownGlobals.push(global.prompt);
}

function allowGlobals(...allowlist) {
knownGlobals = knownGlobals.concat(allowlist);
}
Expand Down
1 change: 1 addition & 0 deletions test/parallel/test-global.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ builtinModules.forEach((moduleName) => {
'clearInterval',
'clearTimeout',
'performance',
'prompt',
'setImmediate',
'setInterval',
'setTimeout',
Expand Down
2 changes: 2 additions & 0 deletions test/pseudo-tty/test-prompt.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
sushi

12 changes: 12 additions & 0 deletions test/pseudo-tty/test-prompt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const common = require('../common');
const assert = require('assert');

(async () => {
const resp1 = prompt('what your favorite food?');
assert.strictEqual(resp1, 'sushi');

const resp2 = prompt('what is the default value?', 'DEFAULT');
assert.strictEqual(resp2, 'DEFAULT');
})().then(common.mustCall(() => {}));
3 changes: 3 additions & 0 deletions test/pseudo-tty/test-prompt.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sushi
what your favorite food?
what is the default value?

0 comments on commit fcde071

Please sign in to comment.