Skip to content

Commit

Permalink
Properly handle errors originating from included files when compileDe…
Browse files Browse the repository at this point in the history
…bug is enabled (#3269)
  • Loading branch information
tmont committed Feb 28, 2021
1 parent d6f0615 commit d4b7f60
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 30 deletions.
16 changes: 10 additions & 6 deletions packages/pug-runtime/index.js
Expand Up @@ -247,18 +247,22 @@ function pug_rethrow(err, filename, lineno, str) {
err.message += ' on line ' + lineno;
throw err;
}
var context, lines, start, end;
try {
str = str || require('fs').readFileSync(filename, 'utf8');
str = str || require('fs').readFileSync(filename, {encoding: 'utf8'});
context = 3;
lines = str.split('\n');
start = Math.max(lineno - context, 0);
end = Math.min(lines.length, lineno + context);
} catch (ex) {
err.message +=
' - could not read from ' + filename + ' (' + ex.message + ')';
pug_rethrow(err, null, lineno);
return;
}
var context = 3,
lines = str.split('\n'),
start = Math.max(lineno - context, 0),
end = Math.min(lines.length, lineno + context);

// Error context
var context = lines
context = lines
.slice(start, end)
.map(function(line, i) {
var curr = i + start + 1;
Expand Down
47 changes: 47 additions & 0 deletions packages/pug-runtime/test/index.test.js
Expand Up @@ -221,3 +221,50 @@ addTest('style', function(style) {
expect(style({foo: 'bar'})).toBe('foo:bar;');
expect(style({foo: 'bar', baz: 'bash'})).toBe('foo:bar;baz:bash;');
});

describe('rethrow', () => {
it('should rethrow error', () => {
const err = new Error();
try {
runtime.rethrow(err, 'foo.pug', 3);
} catch (e) {
expect(e).toBe(err);
return;
}

throw new Error('expected rethrow to throw');
});

it('should rethrow error with str', () => {
const err = new Error();
try {
runtime.rethrow(err, 'foo.pug', 3, 'hello world');
} catch (e) {
expect(e).toBe(err);
expect(e.message.trim()).toBe(
`
foo.pug:3
1| hello world`.trim()
);
return;
}

throw new Error('expected rethrow to throw');
});

it('should handle bad arguments gracefully', () => {
const err = new Error('hello world');
const str = {not: 'a string'};
try {
runtime.rethrow(err, 'foo.pug', 3, str);
} catch (e) {
expect(e).toBe(err);
expect(e.message).toBe(
'hello world - could not read from foo.pug (str.split is not a function) on line 3'
);
return;
}

throw new Error('expected rethrow to throw');
});
});
4 changes: 3 additions & 1 deletion packages/pug/lib/index.js
Expand Up @@ -164,7 +164,9 @@ function compileBody(str, options) {
contents = load.read(filename, loadOptions);
}

debug_sources[filename] = contents;
debug_sources[filename] = Buffer.isBuffer(contents)
? contents.toString('utf8')
: contents;
return contents;
},
});
Expand Down
48 changes: 26 additions & 22 deletions packages/pug/test/__snapshots__/pug.test.js.snap
Expand Up @@ -56,31 +56,35 @@ exports[`pug .compileClient() should support module syntax in pug.compileClient(
return c !== r ? s + a.substring(c, r) : s;
}
var pug_match_html = /[\\"&<>]/;
function pug_rethrow(n, e, t, r) {
if (!(n instanceof Error)) throw n;
if (!((\\"undefined\\" == typeof window && e) || r))
throw ((n.message += \\" on line \\" + t), n);
function pug_rethrow(e, n, r, t) {
if (!(e instanceof Error)) throw e;
if (!((\\"undefined\\" == typeof window && n) || t))
throw ((e.message += \\" on line \\" + r), e);
var o, a, i, s;
try {
r = r || require(\\"fs\\").readFileSync(e, \\"utf8\\");
} catch (e) {
pug_rethrow(n, null, t);
(t = t || require(\\"fs\\").readFileSync(n, { encoding: \\"utf8\\" })),
(o = 3),
(a = t.split(\\"\\\\n\\")),
(i = Math.max(r - o, 0)),
(s = Math.min(a.length, r + o));
} catch (t) {
return (
(e.message += \\" - could not read from \\" + n + \\" (\\" + t.message + \\")\\"),
void pug_rethrow(e, null, r)
);
}
var a = 3,
i = r.split(\\"\\\\n\\"),
o = Math.max(t - a, 0),
h = Math.min(i.length, t + a),
a = i
.slice(o, h)
.map(function(n, e) {
var r = e + o + 1;
return (r == t ? \\" > \\" : \\" \\") + r + \\"| \\" + n;
})
.join(\\"\\\\n\\");
n.path = e;
(o = a
.slice(i, s)
.map(function(e, n) {
var t = n + i + 1;
return (t == r ? \\" > \\" : \\" \\") + t + \\"| \\" + e;
})
.join(\\"\\\\n\\")),
(e.path = n);
try {
n.message = (e || \\"Pug\\") + \\":\\" + t + \\"\\\\n\\" + a + \\"\\\\n\\\\n\\" + n.message;
} catch (n) {}
throw n;
e.message = (n || \\"Pug\\") + \\":\\" + r + \\"\\\\n\\" + o + \\"\\\\n\\\\n\\" + e.message;
} catch (e) {}
throw e;
}
function template(locals) {
var pug_html = \\"\\",
Expand Down
12 changes: 12 additions & 0 deletions packages/pug/test/error.reporting.test.js
Expand Up @@ -80,7 +80,19 @@ describe('error reporting', function() {
expect(err.message).toMatch(/[\\\/]include.locals.error.pug:2/);
expect(err.message).toMatch(/foo\(/);
});

it('handles compileDebug option properly', function() {
var err = getFileError(
__dirname + '/fixtures/compile.with.include.locals.error.pug',
{
compileDebug: true,
}
);
expect(err.message).toMatch(/[\\\/]include.locals.error.pug:2/);
expect(err.message).toMatch(/foo is not a function/);
});
});

describe('with a layout (without block) with an include (syntax)', function() {
it('includes detail of where the error was thrown including the filename', function() {
var err = getFileError(
Expand Down
1 change: 0 additions & 1 deletion packages/pug/test/pug.test.js
Expand Up @@ -1243,7 +1243,6 @@ describe('pug', function() {
__dirname + '/temp/input-compileModuleFileClient.js',
fn
);
var expected = '<div class="bar">baz</div>';
var fn = require(__dirname + '/temp/input-compileModuleFileClient.js');
expect(fn({foo: 'baz'})).toBe('<div class="bar">baz</div>');
});
Expand Down

0 comments on commit d4b7f60

Please sign in to comment.