diff --git a/packages/pug-runtime/index.js b/packages/pug-runtime/index.js index 84c615eaa..72e8e5028 100644 --- a/packages/pug-runtime/index.js +++ b/packages/pug-runtime/index.js @@ -247,18 +247,24 @@ 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'); + var encoding = 'utf8'; + str = str || require('fs').readFileSync(filename, { encoding: encoding }); + if (str.type === 'Buffer') { + str = Buffer.from(str.data).toString(encoding); + } + context = 3; + lines = str.split('\n'); + start = Math.max(lineno - context, 0); + end = Math.min(lines.length, lineno + context); } catch (ex) { 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..78daab70c 100644 --- a/packages/pug-runtime/test/index.test.js +++ b/packages/pug-runtime/test/index.test.js @@ -221,3 +221,48 @@ 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 rethrow error with toJSON()\'d Buffer', () => { + const err = new Error(); + const str = Buffer.from('hello world').toJSON(); + try { + runtime.rethrow(err, 'foo.pug', 3, str); + } 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'); + }); +}); diff --git a/packages/pug/test/__snapshots__/pug.test.js.snap b/packages/pug/test/__snapshots__/pug.test.js.snap index dd3ef1968..44c29c602 100644 --- a/packages/pug/test/__snapshots__/pug.test.js.snap +++ b/packages/pug/test/__snapshots__/pug.test.js.snap @@ -56,29 +56,31 @@ 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) { +function pug_rethrow(n, t, e, r) { if (!(n instanceof Error)) throw n; - if (!((\\"undefined\\" == typeof window && e) || r)) - throw ((n.message += \\" on line \\" + t), n); + if (!((\\"undefined\\" == typeof window && t) || r)) + throw ((n.message += \\" on line \\" + e), n); + var i, o, a, f; try { - r = r || require(\\"fs\\").readFileSync(e, \\"utf8\\"); - } catch (e) { - pug_rethrow(n, null, t); + (r = r || require(\\"fs\\").readFileSync(t, { encoding: \\"utf8\\" })), + \\"Buffer\\" === r.type && (r = Buffer.from(r.data).toString(\\"utf8\\")), + (i = 3), + (o = r.split(\\"\\\\n\\")), + (a = Math.max(e - i, 0)), + (f = Math.min(o.length, e + i)); + } catch (t) { + return void pug_rethrow(n, null, e); } - 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; + (i = o + .slice(a, f) + .map(function(n, t) { + var r = t + a + 1; + return (r == e ? \\" > \\" : \\" \\") + r + \\"| \\" + n; + }) + .join(\\"\\\\n\\")), + (n.path = t); try { - n.message = (e || \\"Pug\\") + \\":\\" + t + \\"\\\\n\\" + a + \\"\\\\n\\\\n\\" + n.message; + n.message = (t || \\"Pug\\") + \\":\\" + e + \\"\\\\n\\" + i + \\"\\\\n\\\\n\\" + n.message; } catch (n) {} throw n; } 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(