Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly handle errors originating from included files when compileDebug is enabled #3269

Merged
merged 3 commits into from Feb 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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