diff --git a/.changeset/khaki-wolves-return.md b/.changeset/khaki-wolves-return.md new file mode 100644 index 000000000000..312d8f838037 --- /dev/null +++ b/.changeset/khaki-wolves-return.md @@ -0,0 +1,5 @@ +--- +'@astrojs/cloudflare': patch +--- + +Fixes an issue where existing KV namespace bindings were silently removed when session support was enabled. diff --git a/packages/astro/src/vite-plugin-astro/compile.ts b/packages/astro/src/vite-plugin-astro/compile.ts index c1c62efbe695..cb3ffbd1abca 100644 --- a/packages/astro/src/vite-plugin-astro/compile.ts +++ b/packages/astro/src/vite-plugin-astro/compile.ts @@ -4,7 +4,7 @@ import type { AstroLogger } from '../core/logger/core.js'; import type { AstroConfig } from '../types/public/config.js'; import { getFileInfo } from '../vite-plugin-utils/index.js'; import type { CompileMetadata } from './types.js'; -import { frontmatterRE } from './utils.js'; +import { frontmatterRE, replaceTopLevelReturns } from './utils.js'; import type { SourceMapInput } from 'rollup'; interface CompileAstroOption { @@ -109,10 +109,8 @@ async function enhanceCompileError({ // If frontmatter is valid or cannot be parsed, then continue. const scannedFrontmatter = frontmatterRE.exec(source); if (scannedFrontmatter) { - // Top-level return is not supported, so replace `return` with throw - const frontmatter = scannedFrontmatter[1] - .replace(/\breturn\s*;/g, 'throw 0;') - .replace(/\breturn\b/g, 'throw '); + // Top-level return is not supported, so replace `return` with `throw`. + const frontmatter = replaceTopLevelReturns(scannedFrontmatter[1]); // If frontmatter does not actually include the offending line, skip if (lineText && !frontmatter.includes(lineText)) throw err; diff --git a/packages/astro/src/vite-plugin-astro/utils.ts b/packages/astro/src/vite-plugin-astro/utils.ts index f1a5923409dc..181a5eedad74 100644 --- a/packages/astro/src/vite-plugin-astro/utils.ts +++ b/packages/astro/src/vite-plugin-astro/utils.ts @@ -3,6 +3,19 @@ import type { PluginContainer } from 'vite'; export const frontmatterRE = /^---(.*?)^---/ms; +// Matches tokens to skip (strings, template literals, comments) OR a top-level `return`. +// The first alternative is preserved as-is; only the second is rewritten. +// Negative lookbehind `(? { + if (skip !== undefined) return skip; + return tail.trim() === ';' ? 'throw 0;' : 'throw '; + }); +} + export async function loadId(pluginContainer: PluginContainer, id: string) { const result = await pluginContainer.load(id, { ssr: true }); diff --git a/packages/integrations/cloudflare/src/esbuild-plugin-astro-frontmatter.ts b/packages/integrations/cloudflare/src/esbuild-plugin-astro-frontmatter.ts index ef2c14a316ef..3f9805e68c21 100644 --- a/packages/integrations/cloudflare/src/esbuild-plugin-astro-frontmatter.ts +++ b/packages/integrations/cloudflare/src/esbuild-plugin-astro-frontmatter.ts @@ -3,6 +3,19 @@ import type { DepOptimizationConfig } from 'vite'; const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/; +// Matches tokens to skip (strings, template literals, comments) OR a top-level `return`. +// The first alternative is preserved as-is; only the second is rewritten. +// Negative lookbehind `(? { + if (skip !== undefined) return skip; + return tail.trim() === ';' ? 'throw 0;' : 'throw '; + }); +} + // Not exposed as a type from Vite, so need to grab this way. type ESBuildPlugin = NonNullable< NonNullable['plugins'] @@ -27,12 +40,7 @@ export function astroFrontmatterScanPlugin(): ESBuildPlugin { // Replace `return` with `throw` to avoid esbuild's "Top-level return" error during scanning. // This aligns with Astro's core compiler logic for frontmatter error handling. // See: packages/astro/src/vite-plugin-astro/compile.ts - // - // Known Limitation: Using regex /\breturn\b/ will incorrectly match - // identifiers like `$return` or aliases like `import { return as ret }`. - const contents = frontmatterMatch[1] - .replace(/\breturn\s*;/g, 'throw 0;') - .replace(/\breturn\b/g, 'throw '); + const contents = replaceTopLevelReturns(frontmatterMatch[1]); // Append `export default {}` so that default imports of .astro files // (e.g. `import MyComponent from './MyComponent.astro'`) resolve correctly