Skip to content

Commit 1d24d11

Browse files
committed
feat: Combine injection snippets
1 parent cd26b63 commit 1d24d11

File tree

9 files changed

+93
-58
lines changed

9 files changed

+93
-58
lines changed

packages/bundler-plugin-core/src/index.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { createDebugIdUploadFunction } from "./debug-id-upload";
1212
import { Logger } from "./logger";
1313
import { Options, SentrySDKBuildFlags } from "./types";
1414
import {
15+
CodeInjection,
1516
containsOnlyImports,
1617
generateGlobalInjectorCode,
1718
generateModuleMetadataInjectorCode,
@@ -21,7 +22,7 @@ import {
2122
} from "./utils";
2223

2324
type InjectionPlugin = (
24-
injectionCode: string,
25+
injectionCode: CodeInjection,
2526
debugIds: boolean,
2627
logger: Logger
2728
) => UnpluginOptions;
@@ -101,7 +102,7 @@ export function sentryUnpluginFactory({
101102
plugins.push(bundleSizeOptimizationsPlugin(bundleSizeOptimizationReplacementValues));
102103
}
103104

104-
let injectionCode = "";
105+
const injectionCode = new CodeInjection();
105106

106107
if (!options.release.inject) {
107108
logger.debug(
@@ -117,24 +118,24 @@ export function sentryUnpluginFactory({
117118
injectBuildInformation: options._experiments.injectBuildInformation || false,
118119
});
119120
if (typeof injectionPlugin !== "function") {
120-
plugins.push(injectionPlugin.releaseInjectionPlugin(code));
121+
plugins.push(injectionPlugin.releaseInjectionPlugin(code.code()));
121122
} else {
122-
injectionCode += code;
123+
injectionCode.append(code);
123124
}
124125
}
125126

126127
if (Object.keys(sentryBuildPluginManager.bundleMetadata).length > 0) {
127128
const code = generateModuleMetadataInjectorCode(sentryBuildPluginManager.bundleMetadata);
128129
if (typeof injectionPlugin !== "function") {
129-
plugins.push(injectionPlugin.moduleMetadataInjectionPlugin(code));
130+
plugins.push(injectionPlugin.moduleMetadataInjectionPlugin(code.code()));
130131
} else {
131-
injectionCode += code;
132+
injectionCode.append(code);
132133
}
133134
}
134135

135136
if (
136137
typeof injectionPlugin === "function" &&
137-
(injectionCode !== "" || options.sourcemaps?.disable !== true)
138+
(!injectionCode.isEmpty() || options.sourcemaps?.disable !== true)
138139
) {
139140
plugins.push(injectionPlugin(injectionCode, options.sourcemaps?.disable !== true, logger));
140141
}
@@ -286,7 +287,7 @@ export function createRollupBundleSizeOptimizationHooks(replacementValues: Sentr
286287
}
287288

288289
export function createRollupInjectionHooks(
289-
injectionCode: string,
290+
injectionCode: CodeInjection,
290291
debugIds: boolean
291292
): {
292293
renderChunk: RenderChunkHook;
@@ -302,8 +303,6 @@ export function createRollupInjectionHooks(
302303
return null;
303304
}
304305

305-
let codeToInject = injectionCode;
306-
307306
if (debugIds) {
308307
// Check if a debug ID has already been injected to avoid duplicate injection (e.g. by another plugin or Sentry CLI)
309308
const chunkStartSnippet = code.slice(0, 6000);
@@ -316,7 +315,7 @@ export function createRollupInjectionHooks(
316315
)
317316
) {
318317
const debugId = stringToUUID(code); // generate a deterministic debug ID
319-
codeToInject += getDebugIdSnippet(debugId);
318+
injectionCode.append(getDebugIdSnippet(debugId));
320319
}
321320
}
322321

@@ -325,12 +324,12 @@ export function createRollupInjectionHooks(
325324

326325
if (match) {
327326
// Add injected code after any comments or "use strict" at the beginning of the bundle.
328-
ms.appendLeft(match.length, codeToInject);
327+
ms.appendLeft(match.length, injectionCode.code());
329328
} else {
330329
// ms.replace() doesn't work when there is an empty string match (which happens if
331330
// there is neither, a comment, nor a "use strict" at the top of the chunk) so we
332331
// need this special case here.
333-
ms.prepend(codeToInject);
332+
ms.prepend(injectionCode.code());
334333
}
335334

336335
return {
@@ -447,11 +446,13 @@ export function createComponentNameAnnotateHooks(ignoredComponents?: string[]):
447446
};
448447
}
449448

450-
export function getDebugIdSnippet(debugId: string): string {
451-
return `;{try{(function(){var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"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){}};`;
449+
export function getDebugIdSnippet(debugId: string): CodeInjection {
450+
return new CodeInjection(
451+
`var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}");`
452+
);
452453
}
453454

454455
export type { Logger } from "./logger";
455456
export type { Options, SentrySDKBuildFlags } from "./types";
456-
export { replaceBooleanFlagsInCode, stringToUUID } from "./utils";
457+
export { CodeInjection, replaceBooleanFlagsInCode, stringToUUID } from "./utils";
457458
export { createSentryBuildPluginManager } from "./build-plugin-manager";

packages/bundler-plugin-core/src/utils.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -311,33 +311,27 @@ export function generateGlobalInjectorCode({
311311
}: {
312312
release: string;
313313
injectBuildInformation: boolean;
314-
}): string {
315-
// The code below is mostly ternary operators because it saves bundle size.
316-
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
317-
let code = `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};`;
318-
319-
code += `e.SENTRY_RELEASE={id:${JSON.stringify(release)}};`;
314+
}): CodeInjection {
315+
let code = `e.SENTRY_RELEASE={id:${JSON.stringify(release)}};`;
320316

321317
if (injectBuildInformation) {
322318
const buildInfo = getBuildInformation();
323319

324320
code += `e.SENTRY_BUILD_INFO=${JSON.stringify(buildInfo)};`;
325321
}
326322

327-
code += "}catch(e){}}();";
328-
329-
return code;
323+
return new CodeInjection(code);
330324
}
331325

332326
// eslint-disable-next-line @typescript-eslint/no-explicit-any
333-
export function generateModuleMetadataInjectorCode(metadata: any): string {
334-
// The code below is mostly ternary operators because it saves bundle size.
335-
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
327+
export function generateModuleMetadataInjectorCode(metadata: any): CodeInjection {
336328
// We are merging the metadata objects in case modules are bundled twice with the plugin
337329
// Use try-catch to avoid issues when bundlers rename global variables like 'window' to 'k'
338-
return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${JSON.stringify(
339-
metadata
340-
)})}catch(e){}}();`;
330+
return new CodeInjection(
331+
`e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${JSON.stringify(
332+
metadata
333+
)});`
334+
);
341335
}
342336

343337
export function getBuildInformation(): {
@@ -459,3 +453,36 @@ export function containsOnlyImports(code: string): boolean {
459453

460454
return codeWithoutImports.length === 0;
461455
}
456+
457+
export class CodeInjection {
458+
// The code below is mostly ternary operators because it saves bundle size.
459+
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
460+
private readonly header = `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};`;
461+
private readonly footer = "}catch(e){}}();";
462+
463+
constructor(private body: string = "") {}
464+
465+
public code(): string {
466+
if (this.isEmpty()) {
467+
return "";
468+
}
469+
470+
return this.header + this.body + this.footer;
471+
}
472+
473+
public isEmpty(): boolean {
474+
return this.body.length === 0;
475+
}
476+
477+
public append(code: CodeInjection | string): void {
478+
if (code instanceof CodeInjection) {
479+
this.body += code.body;
480+
} else {
481+
this.body += code;
482+
}
483+
}
484+
485+
public clear(): void {
486+
this.body = "";
487+
}
488+
}

packages/bundler-plugin-core/test/__snapshots__/utils.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ exports[`generateGlobalInjectorCode generates code with release 1`] = `"!functio
44

55
exports[`generateGlobalInjectorCode generates code with release and build information 1`] = `"!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{};e.SENTRY_RELEASE={id:\\"1.2.3\\"};e.SENTRY_BUILD_INFO={\\"deps\\":[\\"myDep\\",\\"rollup\\"],\\"depsVersions\\":{\\"rollup\\":3},\\"nodeVersion\\":18};}catch(e){}}();"`;
66

7-
exports[`generateModuleMetadataInjectorCode generates code with empty metadata object 1`] = `"!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],{})}catch(e){}}();"`;
7+
exports[`generateModuleMetadataInjectorCode generates code with empty metadata object 1`] = `"!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],{});}catch(e){}}();"`;
88
9-
exports[`generateModuleMetadataInjectorCode generates code with metadata object 1`] = `"!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],{\\"file1.js\\":{\\"foo\\":\\"bar\\"},\\"file2.js\\":{\\"bar\\":\\"baz\\"}})}catch(e){}}();"`;
9+
exports[`generateModuleMetadataInjectorCode generates code with metadata object 1`] = `"!function(){try{var e=\\"undefined\\"!=typeof window?window:\\"undefined\\"!=typeof global?global:\\"undefined\\"!=typeof globalThis?globalThis:\\"undefined\\"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],{\\"file1.js\\":{\\"foo\\":\\"bar\\"},\\"file2.js\\":{\\"bar\\":\\"baz\\"}});}catch(e){}}();"`;

0 commit comments

Comments
 (0)