mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Improve meteor shell command evaluation.
Specific improvements: - Parentheses are now stripped from commands that look like named classes so that they will be treated as class declarations rather than as named class expressions. - When the `ecmascript` package is installed, `compileForShell` errors are now exposed to the `evalCommand` callback. - Instead of using `vm.runInThisContext` to parse and evaluate commands at the same time, `evalCommand` now parses commands by creating a new `vm.Script` and later evaluates them using `script.runInThisContext()`, so that `SyntaxError`s can be reported immediately. Fixes #5131.
This commit is contained in:
@@ -266,21 +266,54 @@ var evalCommandPromise = Promise.resolve();
|
||||
|
||||
function evalCommand(command, context, filename, callback) {
|
||||
if (Package.ecmascript) {
|
||||
var noParens = stripParens(command);
|
||||
if (noParens !== command) {
|
||||
var classMatch = /^\s*class\s+(\w+)/.exec(noParens);
|
||||
if (classMatch && classMatch[1] !== "extends") {
|
||||
// If the command looks like a named ES2015 class, we remove the
|
||||
// extra layer of parentheses added by the REPL so that the
|
||||
// command will be evaluated as a class declaration rather than as
|
||||
// a named class expression. Note that you can still type (class A
|
||||
// {}) explicitly to evaluate a named class expression. The REPL
|
||||
// code that calls evalCommand handles named function expressions
|
||||
// similarly (first with and then without parentheses), but that
|
||||
// code doesn't know about ES2015 classes, which is why we have to
|
||||
// handle them here.
|
||||
command = noParens;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
command = command.replace(/^\(|\)$/g, "");
|
||||
command = Package.ecmascript.ECMAScript.compileForShell(command);
|
||||
} catch (error) {
|
||||
// If there was an error compiling the original command, there's a
|
||||
// chance it didn't need to be compiled at all, so we might as well
|
||||
// let vm.runInThisContext try to evaluate it.
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var script = new vm.Script(command, {
|
||||
filename: filename,
|
||||
displayErrors: false
|
||||
});
|
||||
} catch (parseError) {
|
||||
callback(parseError);
|
||||
return;
|
||||
}
|
||||
|
||||
evalCommandPromise.then(function () {
|
||||
callback(null, vm.runInThisContext(command, filename));
|
||||
callback(null, script.runInThisContext());
|
||||
}).catch(callback);
|
||||
}
|
||||
|
||||
function stripParens(command) {
|
||||
if (command.charAt(0) === "(" &&
|
||||
command.charAt(command.length - 1) === ")") {
|
||||
return command.slice(1, command.length - 1);
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
// This function allows a persistent history of shell commands to be saved
|
||||
// to and loaded from .meteor/local/shell-history.
|
||||
Sp.initializeHistory = function initializeHistory() {
|
||||
|
||||
Reference in New Issue
Block a user