Номер строки SyntaxError в Node.js

У меня есть код, который использует модуль vm и runInNewContext и выполняет динамически генерируемый код JavaScript. В основном более безопасный вариант eval.

Код (переменная code) может содержать синтаксические ошибки, поэтому я хотел бы их поймать и напечатать некоторую полезную информацию.

try {
    vm.runInNewContext(code, sandbox, filename);
}
catch (e) {
    if (e instanceof SyntaxError) { // always false
        console.log(e.toString()); // "SyntaxError: Unexpected token ||" for example
        console.log(e.line); // how to get the line number?
    }
}

Я хочу напечатать номер строки с синтаксической ошибкой, но у меня две проблемы:

  • Я не знаю, как узнать, является ли исключение SyntaxError или чем-то еще. instaceof не работает (обновление - я могу использовать e.name === "SyntaxError").
  • Даже если бы я смог узнать это, как мне получить номер строки? Возможно ли это?

Спасибо заранее.

Обновление: я могу получить некоторую информацию из e.stack. Однако самый верхний вызов в трассировке стека runInNewContext (с номером строки), но я все еще не могу найти номер строки внутри code, который вызвал исключение (SyntaxError).

Ответ 1

1) Используйте if (e.name === "SyntaxError").

2) Все данные, связанные с ошибкой, хранятся в e.stack.

Ответ 2

используйте try/catch

сохранить стек в глобальной переменной

зарегистрировать песочницу

var util = require('util');
var vm = require('vm');
var sandbox = {e:null};
var src = 'try{count += 1;}catch(err) {e=err.stack}';

vm.runInNewContext(src , sandbox, 'myfile.vm');
console.log(util.inspect(sandbox));

это будет log:

{e: 'ReferenceError: count не определен \n в файле myfile.vm: 1:13\n...

теперь вы можете видеть, что ошибка возникает в строке 1, символ 13 myfile.vm это все равно потребует от вас места для некоторых блоков try/cathc в разных местах но по крайней мере вы можете получить обратную связь сейчас

EDIT:

Добавление метода для обнаружения ошибок синтаксиса из вашего рабочего кода

var acorn = require('acorn');
var src = "try{\n"+
    "   {" +
    "       count += 1;\n"+
    "   }catch(err) {\n" +
    "       e=err.stack\n" +
    "}";

var result = acorn.parse(src);

выполнение этого приведет к брошенному Исключению с "SyntaxError: Неожиданный токен (3: 4)" например. строка 3, символ 4 является неожиданным токеном, (дополнительный {который не должен быть там)

Ответ 3

Хотя немного (очень) старый, вы можете использовать stackedy module, который может помочь вам управлять трассировкой стека. Это не идеальное решение, поскольку номер строки, отображаемой в строке, - это номер строки внутри вызова функции, а не номер строки в исходном файле.

В частности, посмотрите простой пример:

index.js

var stackedy = require('stackedy');
var fs = require('fs');

var src = fs.readFileSync(__dirname + '/src.js');
var stack = stackedy(src, { filename : 'stax.js' }).run();

stack.on('error', function (err, c) {
    stack.stop();
    console.log('Error: ' + err);

    var cur = c.current;
    console.log('  in ' + cur.filename + ' at line ' + cur.start.line);

    c.stack.forEach(function (s) {
        console.log('  in ' + s.filename + ', '
            + s.functionName + '() at line ' + s.start.line
        );
    });
});

src.js

function f () { g() }
function g () { h() }
function h () { throw new SyntaxError('woops') }

f();

Вывод:

~/tmp ❯❯❯ node index.js
Error: SyntaxError: woops
  in stax.js at line 2
  in stax.js, h() at line 1
  in stax.js, g() at line 0
  in stax.js, f() at line 4

Как отмечено в комментариях, вы можете использовать err.name === 'SyntaxError' для проверки типа ошибки.

Ответ 4

Для * nix:

if (err) console.log(err.stack.split('\n')[1]);

Будет записана вторая строка stacktrace, точка, в которой произошла ошибка.

Windows или mac может потребовать другой разделительный символ (зависит от окончаний системной строки)