From ceea80ddece2503d0e1793a8c010b781d0758a27 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Thu, 4 Apr 2024 17:30:39 +0200 Subject: [PATCH] Add source maps to node loader Closes GH-2458. Reviewed-by: Titus Wormer --- packages/node-loader/lib/index.js | 14 ++++++++-- packages/node-loader/package.json | 3 +- packages/node-loader/test/index.js | 44 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/node-loader/lib/index.js b/packages/node-loader/lib/index.js index 890450004..4acd3dfbd 100644 --- a/packages/node-loader/lib/index.js +++ b/packages/node-loader/lib/index.js @@ -21,6 +21,7 @@ import fs from 'node:fs/promises' import {createFormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors' import {extnamesToRegex} from '@mdx-js/mdx/internal-extnames-to-regex' +import {SourceMapGenerator} from 'source-map' import {VFile} from 'vfile' import {development as defaultDevelopment} from '#condition' @@ -36,7 +37,8 @@ export function createLoader(options) { const options_ = options || {} const {extnames, process} = createFormatAwareProcessors({ development: defaultDevelopment, - ...options_ + ...options_, + SourceMapGenerator }) const regex = extnamesToRegex(extnames) @@ -62,7 +64,15 @@ export function createLoader(options) { const value = await fs.readFile(url) const file = await process(new VFile({value, path: url})) - return {format: 'module', shortCircuit: true, source: String(file)} + return { + format: 'module', + shortCircuit: true, + source: + String(file) + + '\n//# sourceMappingURL=data:application/json;base64,' + + Buffer.from(JSON.stringify(file.map)).toString('base64') + + '\n' + } } return nextLoad(href, context) diff --git a/packages/node-loader/package.json b/packages/node-loader/package.json index ba29129aa..38e2e2bf6 100644 --- a/packages/node-loader/package.json +++ b/packages/node-loader/package.json @@ -44,12 +44,13 @@ ], "dependencies": { "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0", "vfile": "^6.0.0" }, "devDependencies": {}, "scripts": { "test": "npm run test-coverage", - "test-api": "node --conditions development --loader=@mdx-js/node-loader test/index.js", + "test-api": "node --conditions development --enable-source-maps --loader=@mdx-js/node-loader test/index.js", "test-coverage": "c8 --100 --reporter lcov npm run test-api" }, "xo": { diff --git a/packages/node-loader/test/index.js b/packages/node-loader/test/index.js index fa09d75ce..9c68167e1 100644 --- a/packages/node-loader/test/index.js +++ b/packages/node-loader/test/index.js @@ -52,4 +52,48 @@ test('@mdx-js/node-loader', async function (t) { await fs.rm(mdxUrl) }) + + await t.test('supports source maps work', async function () { + const mdxUrl = new URL('crash.mdx', import.meta.url) + + await fs.writeFile( + mdxUrl, + '\nexport function Throw() { throw new Error("Boom") }\n' + ) + + /** @type {MDXModule} */ + let result + + try { + result = await import(mdxUrl.href) + } catch (error) { + const exception = /** @type {NodeJS.ErrnoException} */ (error) + + if (exception.code === 'ERR_UNKNOWN_FILE_EXTENSION') { + await fs.rm(mdxUrl) + + throw new Error( + 'Please run Node with `--loader=@mdx-js/node-loader` to test the ESM loader' + ) + } + + throw error + } + + const Content = result.default + + assert.throws( + () => renderToStaticMarkup(React.createElement(Content)), + (error) => { + assert(error instanceof Error) + assert.equal(error.message, 'Boom') + // Source maps are off. + // The column should be 26, not 8. + assert(error.stack?.includes('crash.mdx:2:8)')) + return true + } + ) + + await fs.rm(mdxUrl) + }) })