Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ interface ProgramNode {
// tree-shakes to just the helper and the factories actually referenced.
const DEFAULT_IMPORT_SPECIFIER = '@sentry/server-utils';

/**
* Assignment target that keeps the injected call from being tree-shaken. See
* {@link moduleInjectedSnippet}. The value written is always `undefined`; only
* the assignment matters.
*/
const MODULE_INJECTED_SINK = 'globalThis.__SENTRY_ORCHESTRION_INJECT__';

/**
* Entry-chunk banner that marks "the bundler plugin ran" for
* `detectOrchestrionSetup()`. Merge-only (`g.bundler = g.bundler || []`) so it
Expand Down Expand Up @@ -50,6 +57,13 @@ export const ORCHESTRION_BUNDLER_MARKER_BANNER =
* inside a transformed `node_modules` file can't resolve (Turbopack under
* isolated installs); it's embedded via `JSON.stringify` so absolute Windows
* paths survive.
*
* The call result is assigned to a global rather than discarded. The helper
* returns `void` and `@sentry/server-utils` is `sideEffects: false`, so a bare
* call statement is something a bundler can prove droppable: rollup >= 4.63.0
* does exactly that and removes the whole registration, leaving the module
* instrumented but unsubscribed. Writing to a property of `globalThis` is a
* side effect no bundler can shake out, so the call survives.
*/
function moduleInjectedSnippet(
moduleName: string,
Expand All @@ -63,7 +77,7 @@ function moduleInjectedSnippet(
: `const { ${bindings} } = require(${JSON.stringify(importSpecifier)});`;

const args = exportName ? `${JSON.stringify(moduleName)}, ${exportName}` : JSON.stringify(moduleName);
return `${importStmt}\norchestrionModuleInjected(${args});`;
return `${importStmt}\n${MODULE_INJECTED_SINK} = orchestrionModuleInjected(${args});`;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ describe('module-injected transform', () => {
// needed at runtime and the lazy-subscription event matches what channel
// integrations wait for.
expect(result!.code).toContain('orchestrionModuleInjected("mysql", mysqlIntegration)');
// The result is assigned to a global. `@sentry/server-utils` is `sideEffects: false` and the
// helper returns `void`, so a bare call statement is one a bundler can prove droppable.
// rollup >= 4.63.0 removes it, leaving the module instrumented but unsubscribed.
expect(result!.code).toContain('globalThis.__SENTRY_ORCHESTRION_INJECT__ = orchestrionModuleInjected(');
// No separate @sentry/core import at the injection site — the helper owns that.
expect(result!.code).not.toContain('@sentry/core');
// It imports ONLY the mysql factory — no central dispatch pulling in others.
Expand Down
Loading