diff --git a/lib/integration/esbuild.js b/lib/integration/esbuild.js index 86657e5..73c3ccb 100644 --- a/lib/integration/esbuild.js +++ b/lib/integration/esbuild.js @@ -123,7 +123,7 @@ export function esbuild(options = {}) { let file = new VFile({value: doc, path: data.path}) /** @type {VFileValue|undefined} */ let value - /** @type {VFileMessage[]} */ + /** @type {(VFileMessage|Error)[]} */ let messages = [] /** @type {Message[]} */ const errors = [] @@ -134,20 +134,16 @@ export function esbuild(options = {}) { file = await process(file) value = file.value messages = file.messages - } catch (error) { - const exception = /** @type {VFileMessage} */ (error) - exception.fatal = true - messages.push(exception) + } catch (error_) { + const error = /** @type {VFileMessage|Error} */ (error_) + if ('fatal' in error) error.fatal = true + messages.push(error) } for (const message of messages) { - /** @type {{start?: Point, end?: Point}} */ - // Non-message errors stored on `vfile.messages`. - /* c8 ignore next */ - const location = message.position || {} - - const start = location.start - const end = location.end + const location = 'position' in message ? message.position : undefined + const start = location ? location.start : undefined + const end = location ? location.end : undefined let length = 0 let lineStart = 0 let line = 0 @@ -179,9 +175,14 @@ export function esbuild(options = {}) { const match = eol.exec(doc) const lineEnd = match ? match.index : doc.length - ;(message.fatal ? errors : warnings).push({ + ;(!('fatal' in message) || message.fatal ? errors : warnings).push({ pluginName: name, - text: message.reason, + text: + 'reason' in message + ? message.reason + : /* Extra fallback to make sure weird values are definitely strings */ + /* c8 ignore next */ + message.stack || String(message), notes: [], location: { namespace: 'file', diff --git a/test/esbuild.js b/test/esbuild.js index 05b1621..3103212 100644 --- a/test/esbuild.js +++ b/test/esbuild.js @@ -336,6 +336,64 @@ test('xdm (esbuild)', async (t) => { console.log('\nnote: the preceding errors and warnings are expected!\n') + await fs.writeFile(path.join(base, 'esbuild-plugin-crash.mdx'), '# hi') + + try { + await esbuild.build({ + entryPoints: [path.join(base, 'esbuild-plugin-crash.mdx')], + outfile: path.join(base, 'esbuild-plugin-crash.js'), + format: 'esm', + plugins: [ + esbuildXdm({ + rehypePlugins: [ + function () { + return () => { + throw new Error('Something went wrong') + } + } + ] + }) + ] + }) + t.fail('esbuild should throw') + } catch (error) { + /** @type {BuildFailure} */ + const result = JSON.parse(JSON.stringify(error)) + + for (const message of [...result.errors, ...result.warnings]) { + delete message.detail + message.text = message.text.split('\n')[0] + } + + t.deepEqual( + result, + { + errors: [ + { + location: { + column: 0, + file: 'test/context/esbuild-plugin-crash.mdx', + length: 0, + line: 0, + lineText: '# hi', + namespace: 'file', + suggestion: '' + }, + notes: [], + pluginName: 'esbuild-xdm', + text: 'Error: Something went wrong' + } + ], + warnings: [] + }, + 'should pass errors' + ) + } + + await fs.unlink(path.join(base, 'esbuild-plugin-crash.mdx')) + + console.log('\nnote: the preceding errors and warnings are expected!\n') + /** @type {(contents: string) => import('esbuild').Plugin} */ const inlinePlugin = (contents) => ({ name: 'inline plugin',