diff --git a/packages/pug-runtime/index.js b/packages/pug-runtime/index.js index 84c615eaa..648af65db 100644 --- a/packages/pug-runtime/index.js +++ b/packages/pug-runtime/index.js @@ -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; diff --git a/packages/pug-runtime/test/index.test.js b/packages/pug-runtime/test/index.test.js index 1bf0f6e1f..6d1d0c737 100644 --- a/packages/pug-runtime/test/index.test.js +++ b/packages/pug-runtime/test/index.test.js @@ -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'); + }); +}); diff --git a/packages/pug/lib/index.js b/packages/pug/lib/index.js index ec734f7bb..73c52c769 100644 --- a/packages/pug/lib/index.js +++ b/packages/pug/lib/index.js @@ -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; }, }); diff --git a/packages/pug/test/__snapshots__/pug.test.js.snap b/packages/pug/test/__snapshots__/pug.test.js.snap index dd3ef1968..8e3600c04 100644 --- a/packages/pug/test/__snapshots__/pug.test.js.snap +++ b/packages/pug/test/__snapshots__/pug.test.js.snap @@ -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 = \\"\\", diff --git a/packages/pug/test/error.reporting.test.js b/packages/pug/test/error.reporting.test.js index e378e1f14..99ee8e3a4 100644 --- a/packages/pug/test/error.reporting.test.js +++ b/packages/pug/test/error.reporting.test.js @@ -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( diff --git a/packages/pug/test/pug.test.js b/packages/pug/test/pug.test.js index 0b4d85274..f68894932 100644 --- a/packages/pug/test/pug.test.js +++ b/packages/pug/test/pug.test.js @@ -1243,7 +1243,6 @@ describe('pug', function() { __dirname + '/temp/input-compileModuleFileClient.js', fn ); - var expected = '
baz
'; var fn = require(__dirname + '/temp/input-compileModuleFileClient.js'); expect(fn({foo: 'baz'})).toBe('
baz
'); });