Line and column # reporting for Node errors

This commit is contained in:
Matthew Dean
2017-01-01 12:58:09 -08:00
parent 43ab0b8722
commit 68ea31dc89
11 changed files with 92 additions and 31 deletions

View File

@@ -39,8 +39,14 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports,
if (pluginObj) {
this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
if (pluginObj.use) {
pluginObj.use.call(this.context, pluginObj);
try {
if (pluginObj.use) {
pluginObj.use.call(this.context, pluginObj);
}
}
catch (e) {
e.message = 'Error during @plugin call';
return new this.less.LessError(e, imports, filename);
}
return pluginObj;
}
@@ -52,37 +58,46 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports,
};
localExports = localModule.exports;
registry = functionRegistry.create();
var registerPlugin = function(obj) {
pluginObj = obj;
};
try {
var registerPlugin = function(obj) {
pluginObj = obj;
};
loader = new Function("module", "require", "registerPlugin", "functions", "tree", "less", "fileInfo", contents);
loader(localModule, this.require, registerPlugin, registry, this.less.tree, this.less, fileInfo);
} catch (e) {
return new this.less.LessError({ message: 'Parse error' }, imports, filename);
}
if (!pluginObj) {
pluginObj = localModule.exports;
}
pluginObj = this.validatePlugin(pluginObj, filename, shortname);
if (!pluginObj) {
pluginObj = localModule.exports;
}
pluginObj = this.validatePlugin(pluginObj, filename, shortname);
if (pluginObj) {
// Run on first load
pluginManager.addPlugin(pluginObj, fileInfo.filename, registry);
pluginObj.functions = registry.getLocalFunctions();
pluginObj.imports = imports;
pluginObj.filename = filename;
if (pluginObj) {
// Run on first load
pluginManager.addPlugin(pluginObj, fileInfo.filename, registry);
pluginObj.functions = registry.getLocalFunctions();
this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
// Run every @plugin call
// Run every @plugin call
try {
if (pluginObj.use) {
pluginObj.use.call(this.context, pluginObj);
}
}
else {
return new this.less.LessError({ message: "Not a valid plugin" });
catch (e) {
e.message = 'Error during @plugin call';
return new this.less.LessError(e, imports, filename);
}
} catch (e) {
return new this.less.LessError({ message: 'Parse error' }, imports, filename);
}
else {
return new this.less.LessError({ message: "Not a valid plugin" });
}
return pluginObj;

View File

@@ -26,6 +26,9 @@ var LessError = module.exports = function LessError(e, importManager, currentFil
var filename = e.filename || currentFilename;
this.message = e.message;
this.stack = e.stack;
if (importManager && filename) {
var input = importManager.contents[filename],
loc = utils.getLocation(e.index, input),
@@ -38,17 +41,31 @@ var LessError = module.exports = function LessError(e, importManager, currentFil
this.filename = filename;
this.index = e.index;
this.line = typeof line === 'number' ? line + 1 : null;
this.column = col;
if (!this.line && this.stack) {
var found = this.stack.match(/(<anonymous>|Function):(\d+):(\d+)/);
if (found) {
if (found[2]) {
this.line = parseInt(found[2]) - 2;
}
if (found[3]) {
this.column = parseInt(found[3]);
}
}
}
this.callLine = callLine + 1;
this.callExtract = lines[callLine];
this.column = col;
this.extract = [
lines[line - 1],
lines[line],
lines[line + 1]
lines[this.line - 2],
lines[this.line - 1],
lines[this.line]
];
}
this.message = e.message;
this.stack = e.stack;
};

View File

@@ -4,7 +4,8 @@ var Node = require("./node"),
Quoted = require("./quoted"),
Ruleset = require("./ruleset"),
Anonymous = require("./anonymous"),
utils = require("../utils");
utils = require("../utils"),
LessError = require("../less-error");
//
// CSS @import node
@@ -131,7 +132,13 @@ Import.prototype.doEval = function (context) {
if (this.options.isPlugin) {
if (this.root && this.root.eval) {
this.root.eval(context);
try {
this.root.eval(context);
}
catch (e) {
e.message = "Plugin error during evaluation";
throw new LessError(e, this.root.imports, this.root.filename);
}
}
registry = context.frames[0] && context.frames[0].functionRegistry;
if ( registry && this.root && this.root.functions ) {

View File

@@ -207,7 +207,7 @@ testErrorSheet = function (sheet) {
.replace(/\{pathrel\}/g, "")
.replace(/\{pathhref\}/g, "http://localhost:8081/test/less/errors/")
.replace(/\{404status\}/g, " (404)")
.replace(/\{node\}.*\{\/node\}/g, "")
.replace(/\{node\}[\s\S]*\{\/node\}/g, "")
.replace(/\n$/, "")
.trim();
expect(actualErrorMsg).toEqual(errorTxt);

View File

@@ -137,7 +137,7 @@ module.exports = function() {
function testErrors(name, err, compiledLess, doReplacements, sourcemap, baseFolder) {
fs.readFile(path.join(baseFolder, name) + '.txt', 'utf8', function (e, expectedErr) {
process.stdout.write('- ' + path.join(baseFolder, name) + ": ");
expectedErr = doReplacements(expectedErr, baseFolder, err.filename);
expectedErr = doReplacements(expectedErr, baseFolder, err && err.filename);
if (!err) {
if (compiledLess) {
fail('No Error', 'red');

View File

@@ -0,0 +1 @@
@plugin "plugin/plugin-error-2";

View File

@@ -0,0 +1,5 @@
SyntaxError: Error during @plugin call in {path}plugin-error-2.js{node} on line 3, column 16:
2 use: function() {
3 throw new Error("An error was here.")
4 }
{/node}

View File

@@ -0,0 +1 @@
@plugin "plugin/plugin-error-3";

View File

@@ -0,0 +1,5 @@
SyntaxError: Plugin error during evaluation in {path}plugin-error-3.js{node} on line 3, column 16:
2 eval: function() {
3 throw new Error("An error was here.")
4 }
{/node}

View File

@@ -0,0 +1,5 @@
registerPlugin({
use: function() {
throw new Error("An error was here.")
}
});

View File

@@ -0,0 +1,5 @@
registerPlugin({
eval: function() {
throw new Error("An error was here.")
}
});