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

chore(gatsby): Migrate from source-map to @jridgewell/trace-mapping #35621

Merged
merged 4 commits into from Jun 1, 2022
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
2 changes: 1 addition & 1 deletion packages/gatsby-cli/package.json
Expand Up @@ -18,6 +18,7 @@
"@babel/runtime": "^7.15.4",
"@babel/template": "^7.16.7",
"@babel/types": "^7.16.8",
"@jridgewell/trace-mapping": "^0.3.13",
"@types/common-tags": "^1.8.1",
"better-opn": "^2.1.1",
"boxen": "^5.1.2",
Expand Down Expand Up @@ -47,7 +48,6 @@
"resolve-cwd": "^3.0.0",
"semver": "^7.3.7",
"signal-exit": "^3.0.6",
"source-map": "0.7.3",
"stack-trace": "^0.0.10",
"strip-ansi": "^6.0.1",
"update-notifier": "^5.1.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-cli/src/reporter/__tests__/errors.ts
Expand Up @@ -5,8 +5,8 @@ const errorStr = `./src/pages/index.module.scss\nModule build failed: /project/s
// TODO: Add tests for sourcemap mapping in prepareStackTrace[]

describe(`createErrorFromString`, () => {
it(`converts a string to an Error object`, async () => {
const err = await createErrorFromString(errorStr, ``)
it(`converts a string to an Error object`, () => {
const err = createErrorFromString(errorStr, ``)
expect(typeof err).toEqual(`object`)
expect(err.name).toEqual(`WebpackError`)
expect(err.message).toEqual(`./src/pages/index.module.scss`)
Expand Down
6 changes: 3 additions & 3 deletions packages/gatsby-cli/src/reporter/errors.ts
Expand Up @@ -103,10 +103,10 @@ export function getErrorFormatter(): PrettyError {
* Convert a stringified webpack compilation error back into
* an Error instance so it can be formatted properly
*/
export async function createErrorFromString(
export function createErrorFromString(
errorStr: string = ``,
sourceMapFile: string
): Promise<ErrorWithCodeFrame> {
): ErrorWithCodeFrame {
let [message, ...rest] = errorStr.split(/\r\n|[\n\r]/g)
// pull the message from the first line then remove the `Error:` prefix
// FIXME: when https://github.com/AriaMinaei/pretty-error/pull/49 is merged
Expand All @@ -120,7 +120,7 @@ export async function createErrorFromString(
error.name = `WebpackError`
try {
if (sourceMapFile) {
return await prepareStackTrace(error, sourceMapFile)
return prepareStackTrace(error, sourceMapFile)
}
} catch (err) {
// don't shadow a real error because of a parsing issue
Expand Down
33 changes: 16 additions & 17 deletions packages/gatsby-cli/src/reporter/prepare-stack-trace.ts
Expand Up @@ -6,11 +6,12 @@ import { readFileSync, readdirSync } from "fs"
import { codeFrameColumns } from "@babel/code-frame"
import stackTrace from "stack-trace"
import {
SourceMapConsumer,
BasicSourceMapConsumer,
IndexedSourceMapConsumer,
NullableMappedPosition,
} from "source-map"
TraceMap,
originalPositionFor,
OriginalMapping,
InvalidOriginalMapping,
sourceContentFor,
} from "@jridgewell/trace-mapping"
import * as path from "path"

export class ErrorWithCodeFrame extends Error {
Expand All @@ -27,10 +28,10 @@ export class ErrorWithCodeFrame extends Error {
}
}

export async function prepareStackTrace(
export function prepareStackTrace(
error: Error,
sourceOfMainMap: string
): Promise<ErrorWithCodeFrame> {
): ErrorWithCodeFrame {
const newError = new ErrorWithCodeFrame(error)
// source point to single map, but with code splitting for build-html we need to handle more maps
// we use fact that all .map files will be in same dir as main one here
Expand All @@ -39,10 +40,8 @@ export async function prepareStackTrace(
.filter(fileName => fileName.endsWith(`.js.map`))
.map(fileName => path.join(bundleDir, fileName))

const maps = await Promise.all(
bundleDirMapFiles.map(
async source => await new SourceMapConsumer(readFileSync(source, `utf8`))
)
const maps = bundleDirMapFiles.map(
source => new TraceMap(readFileSync(source, `utf8`))
)

const stack = stackTrace
Expand All @@ -66,12 +65,12 @@ export async function prepareStackTrace(
}

function getErrorSource(
maps: Array<BasicSourceMapConsumer | IndexedSourceMapConsumer>,
maps: Array<TraceMap>,
topFrame: stackTrace.StackFrame | IWrappedStackFrame
): string {
let source
for (const map of maps) {
source = map.sourceContentFor(topFrame.getFileName(), true)
source = sourceContentFor(map, topFrame.getFileName())
if (source) {
break
}
Expand Down Expand Up @@ -103,7 +102,7 @@ interface IWrappedStackFrame {
}

function wrapCallSite(
maps: Array<BasicSourceMapConsumer | IndexedSourceMapConsumer>,
maps: Array<TraceMap>,
frame: stackTrace.StackFrame
): IWrappedStackFrame | stackTrace.StackFrame {
const source = frame.getFileName()
Expand All @@ -126,9 +125,9 @@ function getPosition({
maps,
frame,
}: {
maps: Array<BasicSourceMapConsumer | IndexedSourceMapConsumer>
maps: Array<TraceMap>
frame: stackTrace.StackFrame
}): NullableMappedPosition {
}): OriginalMapping | InvalidOriginalMapping {
if (frame.getFileName().includes(`webpack:`)) {
// if source-map-register is initiated, stack traces would already be converted
return {
Expand All @@ -145,7 +144,7 @@ function getPosition({
const line = frame.getLineNumber()
const column = frame.getColumnNumber()
for (const map of maps) {
const test = map.originalPositionFor({ line, column })
const test = originalPositionFor(map, { line, column })
if (test.source) {
return test
}
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby-legacy-polyfills/package.json
Expand Up @@ -31,6 +31,7 @@
"dist/"
],
"devDependencies": {
"@jridgewell/trace-mapping": "^0.3.13",
"chokidar-cli": "^3.0.0",
"codegen.macro": "^4.1.0",
"core-js": "3.9.0",
Expand All @@ -42,7 +43,6 @@
"microbundle": "^0.14.2",
"npm-run-all": "^4.1.5",
"object-assign": "^4.1.1",
"source-map": "^0.7.3",
"url-polyfill": "^1.1.12",
"whatwg-fetch": "^3.6.2",
"yet-another-abortcontroller-polyfill": "0.0.4"
Expand Down
26 changes: 11 additions & 15 deletions packages/gatsby-legacy-polyfills/src/__tests__/polyfills.js
@@ -1,5 +1,5 @@
const path = require(`path`)
const { SourceMapConsumer } = require(`source-map`)
const { TraceMap } = require(`@jridgewell/trace-mapping`)
const execa = require(`execa`)
const fs = require(`fs-extra`)

Expand Down Expand Up @@ -30,7 +30,7 @@ describe(`polyfills`, () => {

afterAll(() => fs.remove(path.join(packageRoot, tmpDir)))

it(`has the correct polyfills`, done => {
it(`has the correct polyfills`, () => {
const polyfills = require(`../exclude`).LEGACY_POLYFILLS
const polyfillMap = path.join(packageRoot, tmpDir, `polyfills.js.map`)
expect(fs.existsSync(polyfillMap)).toBe(true)
Expand All @@ -46,18 +46,14 @@ describe(`polyfills`, () => {
})

const polyfillMapSource = fs.readFileSync(polyfillMap, `utf8`)
SourceMapConsumer.with(polyfillMapSource, null, consumer => {
const sources = consumer.sources.map(source =>
source.replace(/.*\/node_modules\//, ``)
)

// check if all polyfills are in the bundle
expect(sources).toEqual(
expect.arrayContaining(
fileMap.map(file => expect.stringContaining(file))
)
)
done()
})
const tracer = new TraceMap(polyfillMapSource)
const sources = tracer.sources.map(source =>
source.replace(/.*\/node_modules\//, ``)
)

// check if all polyfills are in the bundle
expect(sources).toEqual(
expect.arrayContaining(fileMap.map(file => expect.stringContaining(file)))
)
})
})
2 changes: 1 addition & 1 deletion packages/gatsby/package.json
Expand Up @@ -28,6 +28,7 @@
"@graphql-codegen/typescript-operations": "^2.3.5",
"@graphql-tools/code-file-loader": "^7.2.14",
"@graphql-tools/load": "^7.5.10",
"@jridgewell/trace-mapping": "^0.3.13",
"@nodelib/fs.walk": "^1.2.8",
"@parcel/core": "2.6.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
Expand Down Expand Up @@ -152,7 +153,6 @@
"slugify": "^1.6.1",
"socket.io": "3.1.2",
"socket.io-client": "3.1.3",
"source-map": "^0.7.3",
"source-map-support": "^0.5.20",
"st": "^2.0.0",
"stack-trace": "^0.0.10",
Expand Down
6 changes: 3 additions & 3 deletions packages/gatsby/src/commands/build-html.ts
Expand Up @@ -229,7 +229,7 @@ const renderHTMLQueue = async (
pagePaths: [pagePath],
})
seenErrors.add(error.stack)
const prettyError = await createErrorFromString(
const prettyError = createErrorFromString(
error.stack,
`${htmlComponentRendererPath}.map`
)
Expand Down Expand Up @@ -304,7 +304,7 @@ const renderHTMLQueue = async (
}

for (const unsafeBuiltinUsedStack of uniqueUnsafeBuiltinUsedStacks) {
const prettyError = await createErrorFromString(
const prettyError = createErrorFromString(
unsafeBuiltinUsedStack,
`${htmlComponentRendererPath}.map`
)
Expand Down Expand Up @@ -359,7 +359,7 @@ export const doBuildPages = async (
try {
await renderHTMLQueue(workerPool, activity, rendererPath, pagePaths, stage)
} catch (error) {
const prettyError = await createErrorFromString(
const prettyError = createErrorFromString(
error.stack,
`${rendererPath}.map`
)
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/src/utils/dev-ssr/render-dev-html-child.js
@@ -1,3 +1,4 @@
// TODO: Do not use source-map-support and migrate to a package that doesn't use source-map under the hood
require(`source-map-support`).install()
const sysPath = require(`path`)
const fs = require(`fs-extra`)
Expand Down
53 changes: 26 additions & 27 deletions packages/gatsby/src/utils/stack-trace-utils.ts
@@ -1,11 +1,12 @@
import stackTrace, { StackFrame } from "stack-trace"
import { codeFrameColumns } from "@babel/code-frame"
import {
NullableMappedPosition,
SourceMapConsumer,
RawSourceMap,
RawIndexMap,
} from "source-map"
TraceMap,
originalPositionFor,
OriginalMapping,
SourceMapInput,
sourceContentFor,
} from "@jridgewell/trace-mapping"

const fs = require(`fs-extra`)
const path = require(`path`)
Expand Down Expand Up @@ -111,33 +112,31 @@ export const getNonGatsbyCodeFrameFormatted = ({
}

interface IOriginalSourcePositionAndContent {
sourcePosition: NullableMappedPosition | null
sourcePosition: OriginalMapping | null
sourceContent: string | null
}

export async function findOriginalSourcePositionAndContent(
webpackSource: RawSourceMap | RawIndexMap | string,
export function findOriginalSourcePositionAndContent(
webpackSource: SourceMapInput | string,
position: { line: number; column: number | null }
): Promise<IOriginalSourcePositionAndContent> {
return await SourceMapConsumer.with(webpackSource, null, consumer => {
const sourcePosition = consumer.originalPositionFor({
line: position.line,
column: position.column ?? 0,
})

if (!sourcePosition.source) {
return {
sourcePosition: null,
sourceContent: null,
}
}

const sourceContent: string | null =
consumer.sourceContentFor(sourcePosition.source, true) ?? null
): IOriginalSourcePositionAndContent {
const tracer = new TraceMap(webpackSource)
const sourcePosition = originalPositionFor(tracer, {
line: position.line,
column: position.column ?? 0,
})

if (!sourcePosition.source) {
return {
sourcePosition,
sourceContent,
sourcePosition: null,
sourceContent: null,
}
})
}

const sourceContent = sourceContentFor(tracer, sourcePosition.source)

return {
sourcePosition,
sourceContent,
}
}
7 changes: 2 additions & 5 deletions packages/gatsby/src/utils/start-server.ts
Expand Up @@ -406,7 +406,7 @@ export async function startServer(
}
)

app.get(`/__original-stack-frame`, async (req, res) => {
app.get(`/__original-stack-frame`, (req, res) => {
const compilation = res.locals?.webpack?.devMiddleware?.stats?.compilation
const emptyResponse = {
codeFrame: `No codeFrame could be generated`,
Expand Down Expand Up @@ -454,10 +454,7 @@ export async function startServer(
line: lineNumber,
column: columnNumber,
}
const result = await findOriginalSourcePositionAndContent(
sourceMap,
position
)
const result = findOriginalSourcePositionAndContent(sourceMap, position)

const sourcePosition = result?.sourcePosition
const sourceLine = sourcePosition?.line
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Expand Up @@ -3140,7 +3140,7 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"

"@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9":
"@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9":
version "0.3.13"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
Expand Down Expand Up @@ -23041,14 +23041,14 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"

source-map@0.7.3, source-map@^0.7.3, source-map@~0.7.2:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"

source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"

source-map@^0.7.3, source-map@~0.7.2:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"

source-map@~0.1.30:
version "0.1.43"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
Expand Down