From d857f8cf0992fc072df7e630e44bf674969d6ddd Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Tue, 27 Aug 2024 12:44:25 +0200 Subject: [PATCH 1/2] fix(core): Always instantiate global `Error` class for module metadata --- .../sentry-esbuild-debugid-injection-file.js | 2 +- packages/bundler-plugin-core/src/utils.ts | 4 +- .../bundler-plugin-core/test/utils.test.ts | 62 +++++++++++++++++++ .../metadata-injection.test.ts | 4 ++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/bundler-plugin-core/sentry-esbuild-debugid-injection-file.js b/packages/bundler-plugin-core/sentry-esbuild-debugid-injection-file.js index b3cdf857..6135fac3 100644 --- a/packages/bundler-plugin-core/sentry-esbuild-debugid-injection-file.js +++ b/packages/bundler-plugin-core/sentry-esbuild-debugid-injection-file.js @@ -8,7 +8,7 @@ try { ? self : {}; - var stack = new Error().stack; + var stack = new globalObject.Error().stack; if (stack) { globalObject._sentryDebugIds = globalObject._sentryDebugIds || {}; diff --git a/packages/bundler-plugin-core/src/utils.ts b/packages/bundler-plugin-core/src/utils.ts index 18860e2a..ddfce62b 100644 --- a/packages/bundler-plugin-core/src/utils.ts +++ b/packages/bundler-plugin-core/src/utils.ts @@ -351,10 +351,10 @@ export function generateModuleMetadataInjectorCode(metadata: any) { _sentryModuleMetadataGlobal._sentryModuleMetadata = _sentryModuleMetadataGlobal._sentryModuleMetadata || {}; - _sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack] = + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack] = Object.assign( {}, - _sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack], + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack], ${JSON.stringify(metadata)} ); }`; diff --git a/packages/bundler-plugin-core/test/utils.test.ts b/packages/bundler-plugin-core/test/utils.test.ts index 3dcd93e1..aaa9875c 100644 --- a/packages/bundler-plugin-core/test/utils.test.ts +++ b/packages/bundler-plugin-core/test/utils.test.ts @@ -1,4 +1,5 @@ import { + generateModuleMetadataInjectorCode, getDependencies, getPackageJson, parseMajorVersion, @@ -214,3 +215,64 @@ if (false && true) { }); }); }); + +describe("generateModuleMetadataInjectorCode", () => { + it("generates code with empty metadata object", () => { + const generatedCode = generateModuleMetadataInjectorCode({}); + expect(generatedCode).toMatchInlineSnapshot(` + "{ + var _sentryModuleMetadataGlobal = + typeof window !== \\"undefined\\" + ? window + : typeof global !== \\"undefined\\" + ? global + : typeof self !== \\"undefined\\" + ? self + : {}; + + _sentryModuleMetadataGlobal._sentryModuleMetadata = + _sentryModuleMetadataGlobal._sentryModuleMetadata || {}; + + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack] = + Object.assign( + {}, + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack], + {} + ); + }" + `); + }); + + it("generates code with metadata object", () => { + const generatedCode = generateModuleMetadataInjectorCode({ + "file1.js": { + foo: "bar", + }, + "file2.js": { + bar: "baz", + }, + }); + expect(generatedCode).toMatchInlineSnapshot(` + "{ + var _sentryModuleMetadataGlobal = + typeof window !== \\"undefined\\" + ? window + : typeof global !== \\"undefined\\" + ? global + : typeof self !== \\"undefined\\" + ? self + : {}; + + _sentryModuleMetadataGlobal._sentryModuleMetadata = + _sentryModuleMetadataGlobal._sentryModuleMetadata || {}; + + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack] = + Object.assign( + {}, + _sentryModuleMetadataGlobal._sentryModuleMetadata[new _sentryModuleMetadataGlobal.Error().stack], + {\\"file1.js\\":{\\"foo\\":\\"bar\\"},\\"file2.js\\":{\\"bar\\":\\"baz\\"}} + ); + }" + `); + }); +}); diff --git a/packages/integration-tests/fixtures/metadata-injection/metadata-injection.test.ts b/packages/integration-tests/fixtures/metadata-injection/metadata-injection.test.ts index 52243d2c..4b08baf1 100644 --- a/packages/integration-tests/fixtures/metadata-injection/metadata-injection.test.ts +++ b/packages/integration-tests/fixtures/metadata-injection/metadata-injection.test.ts @@ -13,6 +13,10 @@ function checkBundle(bundlePath: string): void { expect(Object.values(map)).toHaveLength(1); // The value should be the expected metadata expect(Object.values(map)).toEqual([{ team: "frontend" }]); + + // The key is the stack trace of the error thrown in the file + expect(Object.keys(map)[0]).toContain("Error"); + expect(Object.keys(map)[0]).toContain("bundle.js"); } describe("metadata injection", () => { From c1e713823aa63ea096d9ddb2c1ca0fe7a135c3c2 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Tue, 27 Aug 2024 13:02:15 +0200 Subject: [PATCH 2/2] fix Error instantiation for debugId injection snippet --- packages/bundler-plugin-core/src/index.ts | 2 +- packages/bundler-plugin-core/test/index.test.ts | 10 ++++++++++ .../debug-id-injection/debug-id-injection.test.ts | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 packages/bundler-plugin-core/test/index.test.ts diff --git a/packages/bundler-plugin-core/src/index.ts b/packages/bundler-plugin-core/src/index.ts index 794b67c9..88211562 100644 --- a/packages/bundler-plugin-core/src/index.ts +++ b/packages/bundler-plugin-core/src/index.ts @@ -666,7 +666,7 @@ export function createComponentNameAnnotateHooks() { } export function getDebugIdSnippet(debugId: string): string { - return `;!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}")}catch(e){}}();`; + return `;!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}")}catch(e){}}();`; } export { stringToUUID, replaceBooleanFlagsInCode } from "./utils"; diff --git a/packages/bundler-plugin-core/test/index.test.ts b/packages/bundler-plugin-core/test/index.test.ts new file mode 100644 index 00000000..51d0fd57 --- /dev/null +++ b/packages/bundler-plugin-core/test/index.test.ts @@ -0,0 +1,10 @@ +import { getDebugIdSnippet } from "../src"; + +describe("getDebugIdSnippet", () => { + it("returns the debugId injection snippet for a passed debugId", () => { + const snippet = getDebugIdSnippet("1234"); + expect(snippet).toMatchInlineSnapshot( + `";!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]=\\"1234\\",e._sentryDebugIdIdentifier=\\"sentry-dbid-1234\\")}catch(e){}}();"` + ); + }); +}); diff --git a/packages/integration-tests/fixtures/debug-id-injection/debug-id-injection.test.ts b/packages/integration-tests/fixtures/debug-id-injection/debug-id-injection.test.ts index 96f39589..c3605db7 100644 --- a/packages/integration-tests/fixtures/debug-id-injection/debug-id-injection.test.ts +++ b/packages/integration-tests/fixtures/debug-id-injection/debug-id-injection.test.ts @@ -13,6 +13,8 @@ function checkBundle(bundlePath1: string, bundlePath2: string): string[] { expect.stringMatching(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/) ); + expect(Object.keys(debugIdMap1)[0]).toContain("Error"); + const process2Output = childProcess.execSync(`node ${bundlePath2}`, { encoding: "utf-8" }); const debugIdMap2 = JSON.parse(process2Output) as Record; const debugIds2 = Object.values(debugIdMap2); @@ -21,6 +23,8 @@ function checkBundle(bundlePath1: string, bundlePath2: string): string[] { expect.stringMatching(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/) ); + expect(Object.keys(debugIdMap2)[0]).toContain("Error"); + expect(debugIds1).not.toEqual(debugIds2); return [...debugIds1, ...debugIds2];