Skip to content

Commit 3209a8e

Browse files
lib: ensure --check flag works for piped-in code
Previously, the --check CLI flag had no effect when run on code piped from stdin. This commit updates the bootstrap logic to handle the --check flag the same way regardless of whether the code is piped from stdin. PR-URL: #11689 Fixes: #11680 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Richard Lau <[email protected]>
1 parent 53828e8 commit 3209a8e

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

lib/internal/bootstrap_node.js

+20-10
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,11 @@
132132

133133
// check if user passed `-c` or `--check` arguments to Node.
134134
if (process._syntax_check_only != null) {
135-
const vm = NativeModule.require('vm');
136135
const fs = NativeModule.require('fs');
137-
const internalModule = NativeModule.require('internal/module');
138136
// read the source
139137
const filename = Module._resolveFilename(process.argv[1]);
140138
var source = fs.readFileSync(filename, 'utf-8');
141-
// remove shebang and BOM
142-
source = internalModule.stripBOM(source.replace(/^#!.*/, ''));
143-
// wrap it
144-
source = Module.wrap(source);
145-
// compile the script, this will throw if it fails
146-
new vm.Script(source, {filename: filename, displayErrors: true});
139+
checkScriptSyntax(source, filename);
147140
process.exit(0);
148141
}
149142

@@ -184,8 +177,12 @@
184177
});
185178

186179
process.stdin.on('end', function() {
187-
process._eval = code;
188-
evalScript('[stdin]');
180+
if (process._syntax_check_only != null) {
181+
checkScriptSyntax(code, '[stdin]');
182+
} else {
183+
process._eval = code;
184+
evalScript('[stdin]');
185+
}
189186
});
190187
}
191188
}
@@ -445,6 +442,19 @@
445442
}
446443
}
447444

445+
function checkScriptSyntax(source, filename) {
446+
const Module = NativeModule.require('module');
447+
const vm = NativeModule.require('vm');
448+
const internalModule = NativeModule.require('internal/module');
449+
450+
// remove shebang and BOM
451+
source = internalModule.stripBOM(source.replace(/^#!.*/, ''));
452+
// wrap it
453+
source = Module.wrap(source);
454+
// compile the script, this will throw if it fails
455+
new vm.Script(source, {displayErrors: true, filename});
456+
}
457+
448458
// Below you find a minimal module system, which is used to load the node
449459
// core modules found in lib/*.js. All core modules are compiled into the
450460
// node binary, so they can be loaded faster.

test/parallel/test-cli-syntax.js

+38-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const syntaxArgs = [
3131
// no output should be produced
3232
assert.strictEqual(c.stdout, '', 'stdout produced');
3333
assert.strictEqual(c.stderr, '', 'stderr produced');
34-
assert.strictEqual(c.status, 0, 'code == ' + c.status);
34+
assert.strictEqual(c.status, 0, 'code === ' + c.status);
3535
});
3636
});
3737

@@ -52,11 +52,14 @@ const syntaxArgs = [
5252
// no stdout should be produced
5353
assert.strictEqual(c.stdout, '', 'stdout produced');
5454

55+
// stderr should include the filename
56+
assert(c.stderr.startsWith(file), "stderr doesn't start with the filename");
57+
5558
// stderr should have a syntax error message
5659
const match = c.stderr.match(/^SyntaxError: Unexpected identifier$/m);
5760
assert(match, 'stderr incorrect');
5861

59-
assert.strictEqual(c.status, 1, 'code == ' + c.status);
62+
assert.strictEqual(c.status, 1, 'code === ' + c.status);
6063
});
6164
});
6265

@@ -79,6 +82,38 @@ const syntaxArgs = [
7982
const match = c.stderr.match(/^Error: Cannot find module/m);
8083
assert(match, 'stderr incorrect');
8184

82-
assert.strictEqual(c.status, 1, 'code == ' + c.status);
85+
assert.strictEqual(c.status, 1, 'code === ' + c.status);
8386
});
8487
});
88+
89+
// should not execute code piped from stdin with --check
90+
// loop each possible option, `-c` or `--check`
91+
syntaxArgs.forEach(function(args) {
92+
const stdin = 'throw new Error("should not get run");';
93+
const c = spawnSync(node, args, {encoding: 'utf8', input: stdin});
94+
95+
// no stdout or stderr should be produced
96+
assert.strictEqual(c.stdout, '', 'stdout produced');
97+
assert.strictEqual(c.stderr, '', 'stderr produced');
98+
99+
assert.strictEqual(c.status, 0, 'code === ' + c.status);
100+
});
101+
102+
// should should throw if code piped from stdin with --check has bad syntax
103+
// loop each possible option, `-c` or `--check`
104+
syntaxArgs.forEach(function(args) {
105+
const stdin = 'var foo bar;';
106+
const c = spawnSync(node, args, {encoding: 'utf8', input: stdin});
107+
108+
// stderr should include '[stdin]' as the filename
109+
assert(c.stderr.startsWith('[stdin]'), "stderr doesn't start with [stdin]");
110+
111+
// no stdout or stderr should be produced
112+
assert.strictEqual(c.stdout, '', 'stdout produced');
113+
114+
// stderr should have a syntax error message
115+
const match = c.stderr.match(/^SyntaxError: Unexpected identifier$/m);
116+
assert(match, 'stderr incorrect');
117+
118+
assert.strictEqual(c.status, 1, 'code === ' + c.status);
119+
});

0 commit comments

Comments
 (0)