Skip to content

Commit

Permalink
fix(pages): use realpathed tmp dirs to generate valid source maps (#…
Browse files Browse the repository at this point in the history
…4067)

On macOS, `os.tmpdir()` returns a symlink. This causes `esbuild` to
generate invalid source maps, as the number of `../` in relative
paths changes depending on whether you evaluate symlinks.
We previously fixed a similar issues for the middleware loader
(https://github.com/cloudflare/workers-sdk/pull/2249/files#diff-17e01c57aa611bb9e0b392a15fd63b5d18602e3a6c9a97c4a34e891bbfdcb7f3R496-R498),
and regular `wrangler dev`
(be30ee4).
Unfortunately, we didn't fix it for `wrangler pages dev`.
  • Loading branch information
mrbbot authored Oct 2, 2023
1 parent 17ced68 commit 3127071
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 12 deletions.
9 changes: 9 additions & 0 deletions .changeset/curvy-dryers-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"wrangler": patch
---

fix: generate valid source maps with `wrangler pages dev` on macOS

On macOS, `wrangler pages dev` previously generated source maps with an
incorrect number of `../`s in relative paths. This change ensures paths are
always correct, improving support for breakpoint debugging.
8 changes: 5 additions & 3 deletions packages/wrangler/src/pages/buildFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { FatalError } from "../errors";
import { toUrlPath } from "../paths";
Expand All @@ -9,7 +8,7 @@ import { buildWorker } from "./functions/buildWorker";
import { generateConfigFromFileTree } from "./functions/filepath-routing";
import { writeRoutesModule } from "./functions/routes";
import { convertRoutesToRoutesJSONSpec } from "./functions/routes-transformation";
import { RUNNING_BUILDERS } from "./utils";
import { realTmpdir, RUNNING_BUILDERS } from "./utils";
import type { BundleResult } from "../deployment-bundle/bundle";
import type { PagesBuildArgs } from "./build";
import type { Config } from "./functions/routes";
Expand Down Expand Up @@ -60,7 +59,10 @@ export async function buildFunctions({
(runningBuilder) => runningBuilder.stop && runningBuilder.stop()
);

const routesModule = join(tmpdir(), `./functionsRoutes-${Math.random()}.mjs`);
const routesModule = join(
realTmpdir(),
`./functionsRoutes-${Math.random()}.mjs`
);
const baseURL = toUrlPath("/");

const config: Config = await generateConfigFromFileTree({
Expand Down
10 changes: 5 additions & 5 deletions packages/wrangler/src/pages/dev.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { execSync, spawn } from "node:child_process";
import { existsSync, lstatSync, readFileSync } from "node:fs";
import { homedir, tmpdir } from "node:os";
import { homedir } from "node:os";
import { join, resolve } from "node:path";
import { watch } from "chokidar";
import * as esbuild from "esbuild";
Expand All @@ -25,7 +25,7 @@ import {
traverseAndBuildWorkerJSDirectory,
} from "./functions/buildWorker";
import { validateRoutes } from "./functions/routes-validation";
import { CLEANUP, CLEANUP_CALLBACKS } from "./utils";
import { CLEANUP, CLEANUP_CALLBACKS, realTmpdir } from "./utils";
import type { CfModule } from "../deployment-bundle/worker";
import type { AdditionalDevProps } from "../dev";
import type {
Expand Down Expand Up @@ -315,7 +315,7 @@ export const Handler = async ({
// We want to actually run the `_worker.js` script through the bundler
// So update the final path to the script that will be uploaded and
// change the `runBuild()` function to bundle the `_worker.js`.
scriptPath = join(tmpdir(), `./bundledWorker-${Math.random()}.mjs`);
scriptPath = join(realTmpdir(), `./bundledWorker-${Math.random()}.mjs`);
runBuild = async () => {
try {
await buildRawWorker({
Expand Down Expand Up @@ -345,7 +345,7 @@ export const Handler = async ({
});
} else if (usingFunctions) {
// Try to use Functions
scriptPath = join(tmpdir(), `./functionsWorker-${Math.random()}.mjs`);
scriptPath = join(realTmpdir(), `./functionsWorker-${Math.random()}.mjs`);

if (legacyNodeCompat) {
console.warn(
Expand Down Expand Up @@ -483,7 +483,7 @@ export const Handler = async ({
validateRoutes(JSON.parse(routesJSONContents), directory);

entrypoint = join(
tmpdir(),
realTmpdir(),
`${Math.random().toString(36).slice(2)}.js`
);
await runBuild(scriptPath, entrypoint, routesJSONContents);
Expand Down
8 changes: 4 additions & 4 deletions packages/wrangler/src/pages/functions/buildWorker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { access, cp, lstat, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { build as esBuild } from "esbuild";
import { nanoid } from "nanoid";
Expand All @@ -8,6 +7,7 @@ import traverseModuleGraph from "../../deployment-bundle/traverse-module-graph";
import { FatalError } from "../../errors";
import { logger } from "../../logger";
import { getBasePath } from "../../paths";
import { realTmpdir } from "../utils";
import type { BundleResult } from "../../deployment-bundle/bundle";
import type { CfModule } from "../../deployment-bundle/worker";
import type { Plugin } from "esbuild";
Expand All @@ -30,7 +30,7 @@ export type Options = {

export function buildWorker({
routesModule,
outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.js`),
outfile = join(realTmpdir(), `./functionsWorker-${Math.random()}.js`),
outdir,
minify = false,
sourcemap = false,
Expand Down Expand Up @@ -180,7 +180,7 @@ export type RawOptions = {
*/
export function buildRawWorker({
workerScriptPath,
outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.js`),
outfile = join(realTmpdir(), `./functionsWorker-${Math.random()}.js`),
outdir,
directory,
bundle = true,
Expand Down Expand Up @@ -273,7 +273,7 @@ export async function traverseAndBuildWorkerJSDirectory({
]
);

const outfile = join(tmpdir(), `./bundledWorker-${Math.random()}.mjs`);
const outfile = join(realTmpdir(), `./bundledWorker-${Math.random()}.mjs`);
const bundleResult = await buildRawWorker({
workerScriptPath: entrypoint,
bundle: true,
Expand Down
13 changes: 13 additions & 0 deletions packages/wrangler/src/pages/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import fs from "node:fs";
import os from "node:os";
import type { BundleResult } from "../deployment-bundle/bundle";

export const RUNNING_BUILDERS: BundleResult[] = [];
Expand All @@ -18,3 +20,14 @@ export function isUrl(maybeUrl?: string): maybeUrl is string {
return false;
}
}

let realTmpdirCache: string | undefined;
/**
* Returns the realpath of the temporary directory without symlinks. On macOS,
* `os.tmpdir()` will return a symlink. Running `esbuild` and outputting to
* paths in this symlinked-directory results in invalid relative URLs in source
* maps. Resolving symlinks first ensures we always generate valid source maps.
*/
export function realTmpdir(): string {
return (realTmpdirCache ??= fs.realpathSync(os.tmpdir()));
}

0 comments on commit 3127071

Please sign in to comment.