diff --git a/integration/error-sanitization-test.ts b/integration/error-sanitization-test.ts index 7c3cd1bc0a8..a26e407275e 100644 --- a/integration/error-sanitization-test.ts +++ b/integration/error-sanitization-test.ts @@ -140,9 +140,12 @@ test.describe("Error Sanitization", () => { test.describe("serverMode=production", () => { test.beforeAll(async () => { - fixture = await createFixture({ - files: routeFiles, - }); + fixture = await createFixture( + { + files: routeFiles, + }, + ServerMode.Production + ); }); test("renders document without errors", async () => { @@ -183,7 +186,7 @@ test.describe("Error Sanitization", () => { expect(html).toMatch("Defer Route"); expect(html).toMatch("RESOLVED"); expect(html).not.toMatch("MESSAGE:"); - expect(html).not.toMatch(/stack/i); + expect(html).not.toMatch(/"stack":/i); }); test("sanitizes defer errors in document requests", async () => { @@ -191,9 +194,8 @@ test.describe("Error Sanitization", () => { let html = await response.text(); expect(html).toMatch("Defer Error"); expect(html).not.toMatch("RESOLVED"); - // TODO: is this expected or should we get "Unexpected Server Error" here? - expect(html).toMatch('{"message":"REJECTED"}'); - expect(html).not.toMatch(/stack/i); + expect(html).toMatch('{"message":"Unexpected Server Error"}'); + expect(html).not.toMatch(/"stack":/i); }); test("returns data without errors", async () => { @@ -291,7 +293,7 @@ test.describe("Error Sanitization", () => { expect(html).toMatch("Defer Route"); expect(html).toMatch("RESOLVED"); expect(html).not.toMatch("MESSAGE:"); - expect(html).not.toMatch(/stack/i); + expect(html).not.toMatch(/"stack":/i); }); test("does not sanitize defer errors in document requests", async () => { @@ -299,9 +301,8 @@ test.describe("Error Sanitization", () => { let html = await response.text(); expect(html).toMatch("Defer Error"); expect(html).not.toMatch("RESOLVED"); - expect(html).toMatch('{"message":"REJECTED"}'); - // TODO: I think we should be getting the stack here too? - expect(html).toMatch(/stack/i); + // TODO: Is our ServerMode.Development not making it into the build somehow? + expect(html).toMatch('{"message":"REJECTED","stack":"}'); }); test("returns data without errors", async () => { diff --git a/integration/helpers/create-fixture.ts b/integration/helpers/create-fixture.ts index d5828db1f59..ff390ea226f 100644 --- a/integration/helpers/create-fixture.ts +++ b/integration/helpers/create-fixture.ts @@ -35,7 +35,7 @@ export function json(value: JsonObject) { } export async function createFixture(init: FixtureInit, mode?: ServerMode) { - let projectDir = await createFixtureProject(init); + let projectDir = await createFixtureProject(init, mode); let buildPath = path.resolve(projectDir, "build"); let app: ServerBuild = await import(buildPath); let handler = createRequestHandler(app, mode || ServerMode.Production); @@ -141,7 +141,8 @@ export async function createAppFixture(fixture: Fixture, mode?: ServerMode) { //////////////////////////////////////////////////////////////////////////////// export async function createFixtureProject( - init: FixtureInit = {} + init: FixtureInit = {}, + mode?: ServerMode ): Promise { let template = init.template ?? "node-template"; let integrationTemplateDir = path.join(__dirname, template); @@ -193,17 +194,30 @@ export async function createFixtureProject( } await writeTestFiles(init, projectDir); - build(projectDir, init.buildStdio, init.sourcemap); + build(projectDir, init.buildStdio, init.sourcemap, mode); return projectDir; } -function build(projectDir: string, buildStdio?: Writable, sourcemap?: boolean) { +function build( + projectDir: string, + buildStdio?: Writable, + sourcemap?: boolean, + mode?: ServerMode +) { let buildArgs = ["node_modules/@remix-run/dev/dist/cli.js", "build"]; if (sourcemap) { buildArgs.push("--sourcemap"); } - let buildSpawn = spawnSync("node", buildArgs, { cwd: projectDir }); + + console.log("Building with NODE_ENV =", mode || ServerMode.Production); + let buildSpawn = spawnSync("node", buildArgs, { + cwd: projectDir, + env: { + ...process.env, + NODE_ENV: mode || ServerMode.Production, + }, + }); // These logs are helpful for debugging. Remove comments if needed. // console.log("spawning @remix-run/dev/cli.js `build`:\n"); diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx index 092d4e52e6f..f854ff5aa72 100644 --- a/packages/remix-react/components.tsx +++ b/packages/remix-react/components.tsx @@ -815,8 +815,9 @@ export function Scripts(props: ScriptProps) { : [ "__remixContext.p = function(v,e,p,x) {", " if (typeof e !== 'undefined') {", - " x=new Error(e.message);", - process.env.NODE_ENV === "development" ? `x.stack=e.stack;` : "", + process.env.NODE_ENV === "development" + ? " x=new Error(e.message);\n x.stack=e.stack;" + : ' x=new Error("Unexpected Server Error");\n x.stack=undefined;', " p=Promise.reject(x);", " } else {", " p=Promise.resolve(v);", @@ -835,8 +836,9 @@ export function Scripts(props: ScriptProps) { "__remixContext.r = function(i,k,v,e,p,x) {", " p = __remixContext.t[i][k];", " if (typeof e !== 'undefined') {", - " x=new Error(e.message);", - process.env.NODE_ENV === "development" ? `x.stack=e.stack;` : "", + process.env.NODE_ENV === "development" + ? " x=new Error(e.message);\n x.stack=e.stack;" + : ' x=new Error("Unexpected Server Error");\n x.stack=undefined;', " p.e(x);", " } else {", " p.r(v);", @@ -866,13 +868,16 @@ export function Scripts(props: ScriptProps) { } else { let trackedPromise = deferredData.data[key] as TrackedPromise; if (typeof trackedPromise._error !== "undefined") { - let toSerialize: { message: string; stack?: string } = { - message: trackedPromise._error.message, - stack: undefined, - }; - if (process.env.NODE_ENV === "development") { - toSerialize.stack = trackedPromise._error.stack; - } + let toSerialize: { message: string; stack?: string } = + process.env.NODE_ENV === "development" + ? { + message: trackedPromise._error.message, + stack: trackedPromise._error.stack, + } + : { + message: "Unexpected Server Error", + stack: undefined, + }; return `${JSON.stringify( key )}:__remixContext.p(!1, ${escapeHtml( @@ -1078,13 +1083,16 @@ function ErrorDeferredHydrationScript({ routeId: string; }) { let error = useAsyncError() as Error; - let toSerialize: { message: string; stack?: string } = { - message: error.message, - stack: undefined, - }; - if (process.env.NODE_ENV === "development") { - toSerialize.stack = error.stack; - } + let toSerialize: { message: string; stack?: string } = + process.env.NODE_ENV === "development" + ? { + message: error.message, + stack: error.stack, + } + : { + message: "Unexpected Server Error", + stack: undefined, + }; return (