differentiate between 'top-level' and 'needs context preservation' so that SSR errors occur correctly

aaa
Rich Harris 9 months ago
parent 3be5a88b6f
commit f355eaf9a0

@ -266,7 +266,7 @@ export function analyze_module(ast, options) {
immutable: true, immutable: true,
tracing: analysis.tracing, tracing: analysis.tracing,
async_deriveds: new Set(), async_deriveds: new Set(),
suspenders: new Set() suspenders: new Map()
}; };
} }
@ -455,7 +455,7 @@ export function analyze_component(root, source, options) {
snippets: new Set(), snippets: new Set(),
is_async: false, is_async: false,
async_deriveds: new Set(), async_deriveds: new Set(),
suspenders: new Set() suspenders: new Map()
}; };
if (!runes) { if (!runes) {

@ -8,8 +8,11 @@
export function AwaitExpression(node, context) { export function AwaitExpression(node, context) {
const tla = context.state.ast_type === 'instance' && context.state.function_depth === 1; const tla = context.state.ast_type === 'instance' && context.state.function_depth === 1;
let suspend = tla; let suspend = tla;
let preserve_context = tla;
if (context.state.expression) { if (context.state.expression) {
suspend = true;
// wrap the expression in `(await $.suspend(...)).exit()` if necessary, // wrap the expression in `(await $.suspend(...)).exit()` if necessary,
// i.e. whether anything could potentially be read _after_ the await // i.e. whether anything could potentially be read _after_ the await
let i = context.path.length; let i = context.path.length;
@ -23,7 +26,7 @@ export function AwaitExpression(node, context) {
// TODO make this more accurate — we don't need to call suspend // TODO make this more accurate — we don't need to call suspend
// if this is the last thing that could be read // if this is the last thing that could be read
suspend = true; preserve_context = true;
} }
} }
@ -32,7 +35,7 @@ export function AwaitExpression(node, context) {
throw new Error('TODO runes mode only'); throw new Error('TODO runes mode only');
} }
context.state.analysis.suspenders.add(node); context.state.analysis.suspenders.set(node, preserve_context);
} }
if (context.state.expression) { if (context.state.expression) {

@ -7,7 +7,7 @@ import * as b from '../../../../utils/builders.js';
* @param {Context} context * @param {Context} context
*/ */
export function AwaitExpression(node, context) { export function AwaitExpression(node, context) {
const suspend = context.state.analysis.suspenders.has(node); const suspend = context.state.analysis.suspenders.get(node);
if (!suspend) { if (!suspend) {
return context.next(); return context.next();

@ -7,6 +7,9 @@ import * as b from '../../../../utils/builders.js';
* @param {ComponentContext} context * @param {ComponentContext} context
*/ */
export function AwaitExpression(node, context) { export function AwaitExpression(node, context) {
// `has`, not `get`, because all top-level await expressions should
// block regardless of whether they need context preservation
// in the client output
const suspend = context.state.analysis.suspenders.has(node); const suspend = context.state.analysis.suspenders.has(node);
if (!suspend) { if (!suspend) {

@ -42,8 +42,8 @@ export interface Analysis {
/** A set of deriveds that contain `await` expressions */ /** A set of deriveds that contain `await` expressions */
async_deriveds: Set<CallExpression>; async_deriveds: Set<CallExpression>;
/** A set of `await` expressions that should trigger suspense */ /** A map of `await` expressions that should block, and whether they should preserve context */
suspenders: Set<AwaitExpression>; suspenders: Map<AwaitExpression, boolean>;
} }
export interface ComponentAnalysis extends Analysis { export interface ComponentAnalysis extends Analysis {

Loading…
Cancel
Save