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
22 changes: 21 additions & 1 deletion packages/cloudflare/src/vite/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ function wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state
// MagicString positions are always relative to the original source. Only the `export default`
// keywords are replaced, so parentheses around the expression stay.
const source = state.ms.original;
const keywordsEnd = node.start + source.slice(node.start, decl.start).lastIndexOf('default') + 'default'.length;
const keywordsEnd = exportDefaultKeywordsEnd(source, node.start);
const declaredName =
decl.type === 'ClassDeclaration' || decl.type === 'FunctionDeclaration'
? (decl as ClassDeclarationNode).id?.name
Expand Down Expand Up @@ -425,6 +425,26 @@ function wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state
state.autoWrapped.add(DEFAULT_EXPORT);
}

/**
* Offset just past the `default` keyword of the `export default` statement at `start`. Comments can
* sit between `export`, `default` and the expression, and may themselves contain the word `default`.
*/
function exportDefaultKeywordsEnd(source: string, start: number): number {
let index = start + 'export'.length;
while (index < source.length && !source.startsWith('default', index)) {
if (source.startsWith('//', index)) {
const lineEnd = source.indexOf('\n', index);
index = lineEnd === -1 ? source.length : lineEnd;
} else if (source.startsWith('/*', index)) {
const commentEnd = source.indexOf('*/', index + 2);
index = commentEnd === -1 ? source.length : commentEnd + 2;
} else {
index++;
}
}
return index + 'default'.length;
}

function isAnonymousFunctionOrClass(node: BaseNode): boolean {
if (node.type === 'ArrowFunctionExpression') return true;
const isFunctionOrClass = [
Expand Down
27 changes: 27 additions & 0 deletions packages/cloudflare/test/vite/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,33 @@ describe('default export wrapping', () => {
);
});

it('wraps a default export with a comment that mentions `default`', () => {
const code = 'export /* the default */ default /* default handler */ { fetch() {} };';

expect(transform(code, ctx)!.code).toBe(
[
"import * as __SENTRY__ from '@sentry/cloudflare';",
'var __SENTRY_DEFAULT_EXPORT__ = /* default handler */ { fetch() {} };',
'export { __SENTRY_DEFAULT_EXPORT__ as default };',
'__SENTRY_DEFAULT_EXPORT__ = __SENTRY__.withSentry((env) => ({}), __SENTRY_DEFAULT_EXPORT__);',
].join('\n'),
);
});

it('wraps a default export with a line comment that mentions `default`', () => {
const code = ['export // the default', 'default // default handler', '{ fetch() {} };'].join('\n');

expect(transform(code, ctx)!.code).toBe(
[
"import * as __SENTRY__ from '@sentry/cloudflare';",
'var __SENTRY_DEFAULT_EXPORT__ = // default handler',
'{ fetch() {} };',
'export { __SENTRY_DEFAULT_EXPORT__ as default };',
'__SENTRY_DEFAULT_EXPORT__ = __SENTRY__.withSentry((env) => ({}), __SENTRY_DEFAULT_EXPORT__);',
].join('\n'),
);
});

it('keeps the module binding of a named default class', () => {
const code = ['export default class Handler { fetch() {} }', 'Handler.ready = true;'].join('\n');

Expand Down
Loading