Skip to content

Commit 303e240

Browse files
committed
fix: Use renderChunk for release injection for Rollup/Rolldown/Vite
1 parent dccf8f1 commit 303e240

File tree

1 file changed

+44
-69
lines changed
  • packages/bundler-plugin-core/src

1 file changed

+44
-69
lines changed

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

Lines changed: 44 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -190,63 +190,59 @@ export function sentryCliBinaryExists(): boolean {
190190
return fs.existsSync(SentryCli.getPath());
191191
}
192192

193+
// We need to be careful not to inject the snippet before any `"use strict";`s.
194+
// As an additional complication `"use strict";`s may come after any number of comments.
195+
const COMMENT_USE_STRICT_REGEX =
196+
// Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.
197+
/^(?:\s*|\/\*(?:.|\r|\n)*?\*\/|\/\/.*[\n\r])*(?:"[^"]*";|'[^']*';)?/;
198+
199+
/**
200+
* Simplified `renderChunk` hook type from Rollup.
201+
* We can't reference the type directly because the Vite plugin complains
202+
* about type mismatches
203+
*/
204+
type RenderChunkHook = (
205+
code: string,
206+
chunk: {
207+
fileName: string;
208+
}
209+
) => {
210+
code: string;
211+
map: SourceMap;
212+
} | null;
213+
193214
export function createRollupReleaseInjectionHooks(injectionCode: string): {
194-
resolveId: UnpluginOptions["resolveId"];
195-
load: UnpluginOptions["load"];
196-
transform: UnpluginOptions["transform"];
215+
renderChunk: RenderChunkHook;
197216
} {
198-
const virtualReleaseInjectionFileId = "\0sentry-release-injection-file";
199217
return {
200-
resolveId(id: string) {
201-
if (id === virtualReleaseInjectionFileId) {
202-
return {
203-
id: virtualReleaseInjectionFileId,
204-
external: false,
205-
moduleSideEffects: true,
206-
};
207-
} else {
208-
return null;
209-
}
210-
},
211-
212-
load(id: string) {
213-
if (id === virtualReleaseInjectionFileId) {
214-
return injectionCode;
215-
} else {
216-
return null;
217-
}
218-
},
219-
220-
transform(code: string, id: string) {
221-
if (id === virtualReleaseInjectionFileId) {
222-
return null;
223-
}
224-
225-
// id may contain query and hash which will trip up our file extension logic below
226-
const idWithoutQueryAndHash = stripQueryAndHashFromPath(id);
227-
228-
if (idWithoutQueryAndHash.match(/\\node_modules\\|\/node_modules\//)) {
229-
return null;
230-
}
231-
218+
renderChunk(code: string, chunk: { fileName: string }) {
232219
if (
233-
![".js", ".ts", ".jsx", ".tsx", ".mjs"].some((ending) =>
234-
idWithoutQueryAndHash.endsWith(ending)
220+
// chunks could be any file (html, md, ...)
221+
[".js", ".mjs", ".cjs"].some((ending) =>
222+
stripQueryAndHashFromPath(chunk.fileName).endsWith(ending)
235223
)
236224
) {
237-
return null;
238-
}
225+
const ms = new MagicString(code, { filename: chunk.fileName });
239226

240-
const ms = new MagicString(code);
227+
const match = code.match(COMMENT_USE_STRICT_REGEX)?.[0];
241228

242-
// Appending instead of prepending has less probability of mucking with user's source maps.
243-
// Luckily import statements get hoisted to the top anyways.
244-
ms.append(`\n\n;import "${virtualReleaseInjectionFileId}";`);
229+
if (match) {
230+
// Add injected code after any comments or "use strict" at the beginning of the bundle.
231+
ms.appendLeft(match.length, injectionCode);
232+
} else {
233+
// ms.replace() doesn't work when there is an empty string match (which happens if
234+
// there is neither, a comment, nor a "use strict" at the top of the chunk) so we
235+
// need this special case here.
236+
ms.prepend(injectionCode);
237+
}
245238

246-
return {
247-
code: ms.toString(),
248-
map: ms.generateMap({ hires: "boundary" }),
249-
};
239+
return {
240+
code: ms.toString(),
241+
map: ms.generateMap({ file: chunk.fileName, hires: "boundary" }),
242+
};
243+
} else {
244+
return null; // returning null means not modifying the chunk at all
245+
}
250246
},
251247
};
252248
}
@@ -261,27 +257,6 @@ export function createRollupBundleSizeOptimizationHooks(replacementValues: Sentr
261257
};
262258
}
263259

264-
// We need to be careful not to inject the snippet before any `"use strict";`s.
265-
// As an additional complication `"use strict";`s may come after any number of comments.
266-
const COMMENT_USE_STRICT_REGEX =
267-
// Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.
268-
/^(?:\s*|\/\*(?:.|\r|\n)*?\*\/|\/\/.*[\n\r])*(?:"[^"]*";|'[^']*';)?/;
269-
270-
/**
271-
* Simplified `renderChunk` hook type from Rollup.
272-
* We can't reference the type directly because the Vite plugin complains
273-
* about type mismatches
274-
*/
275-
type RenderChunkHook = (
276-
code: string,
277-
chunk: {
278-
fileName: string;
279-
}
280-
) => {
281-
code: string;
282-
map: SourceMap;
283-
} | null;
284-
285260
export function createRollupDebugIdInjectionHooks(): {
286261
renderChunk: RenderChunkHook;
287262
} {

0 commit comments

Comments
 (0)