Skip to content

Commit ae214cd

Browse files
committed
hydration
1 parent d0f5fd1 commit ae214cd

File tree

2 files changed

+44
-79
lines changed

2 files changed

+44
-79
lines changed
Lines changed: 26 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
/** @import { BlockStatement, Identifier, Statement, Expression, MaybeNamedFunctionDeclaration, Pattern } from 'estree' */
22
/** @import { AST } from '#compiler' */
33
/** @import { ComponentContext } from '../types' */
4-
import { attr } from 'svelte/internal/client';
5-
import { BLOCK_CLOSE, BLOCK_OPEN } from '../../../../../internal/server/hydration.js';
64
import * as b from '../../../../utils/builders.js';
75
import { extract_identifiers } from '../../../../utils/ast.js';
86

@@ -20,8 +18,6 @@ export function SvelteBoundary(node, context) {
2018
/** @type {AST.ConstTag[]} */
2119
let const_tags = [];
2220

23-
/** @type {Statement[]} */
24-
const init_body = [];
2521
const nodes = [];
2622

2723
const payload = b.id('$$payload'); // correct ?
@@ -61,60 +57,34 @@ export function SvelteBoundary(node, context) {
6157
}
6258
}
6359

64-
if (snippet && has_const_referenced(context, snippet, const_tags)) {
65-
const const_values = b.id(context.state.scope.generate('const_values'));
66-
statements.push(b.declaration('const', [b.declarator(const_values, b.object([]))]));
67-
for (const tag of const_tags) {
68-
const identifiers = extract_identifiers(tag.declaration.declarations[0].id);
69-
70-
statements.push(
71-
b.declaration(
72-
'let',
73-
identifiers.map((id) => b.declarator(id))
74-
)
75-
);
76-
for (const id of identifiers) {
77-
statements.push(b.stmt(b.call('console.log', id)));
78-
}
79-
80-
context.visit(tag, { ...context.state, init: init_body });
81-
for (const id of identifiers) {
82-
init_body.push(b.stmt(b.assignment('=', const_values, id)));
83-
init_body.push(b.stmt(b.call('console.log', const_values)));
84-
}
85-
86-
// statements.push(b.declaration('const', [b.declarator(tmp, b.arrow([], b.block(init)))]));
87-
88-
// nodes.unshift(b.declaration('let', [b.declarator(b.array_pattern(identifiers), tmp)]));
89-
// // b.declaration('let', [b.declarator(b.array_pattern(identifiers), tmp)]);
60+
let max_referenced_const_tag = -1;
9061

91-
// const c = server_const(() => {
92-
// const { t, x } = { x: name, y: 'x' };
93-
// if (true) {
94-
// throw new Error('badaboum');
95-
// }
96-
// return { t, x };
97-
// });
62+
if (snippet) {
63+
const references = context.state.scopes.get(snippet)?.references;
64+
if (references != null && references.size) {
65+
const keys = new Set(references.keys());
9866

99-
///** @type {Statement[]} */
100-
//const init = [];
101-
//context.visit(tag, { ...context.state, init });
102-
//statements.push(...init);
67+
const_tags.forEach((tag, index) => {
68+
if (has_reference(keys, tag)) {
69+
max_referenced_const_tag = index + 1;
70+
}
71+
});
10372
}
104-
} else if (const_tags.length) {
105-
nodes.unshift(...const_tags);
10673
}
10774

108-
if (init_body.length) {
109-
//nodes.unshift(...init_body);
75+
if (max_referenced_const_tag < 0) {
76+
nodes.unshift(...const_tags);
77+
} else if (max_referenced_const_tag === const_tags.length) {
78+
const_tags.forEach((tag) => context.visit(tag, { ...context.state, init: statements }));
79+
} else {
80+
const_tags
81+
.slice(0, max_referenced_const_tag)
82+
.forEach((tag) => context.visit(tag, { ...context.state, init: statements }));
83+
nodes.unshift(...const_tags.slice(max_referenced_const_tag));
11084
}
11185

11286
const body_block = /** @type {BlockStatement} */ (context.visit({ ...node.fragment, nodes }));
11387

114-
if (init_body.length) {
115-
body_block.body.unshift(...init_body);
116-
}
117-
11888
const body = b.arrow([b.id('$$payload')], body_block);
11989

12090
statements.push(b.stmt(b.call('$.boundary', payload, body, failed)));
@@ -127,38 +97,16 @@ export function SvelteBoundary(node, context) {
12797
}
12898

12999
/**
130-
*
131-
* @param {ComponentContext} context
132-
* @param {AST.SnippetBlock} snippet
133-
* @param {AST.ConstTag[]} const_tags
100+
* @param {Set<string>} keys
101+
* @param {AST.ConstTag} tag
134102
*/
135-
function has_const_referenced(context, snippet, const_tags) {
136-
if (const_tags.length === 0) {
137-
return false;
138-
}
139-
140-
const references = context.state.scopes.get(snippet)?.references;
141-
if (references == null || references.size === 0) {
142-
return false;
143-
}
144-
145-
const identifiers = new Set();
146-
for (const tag of const_tags) {
147-
for (const declaration of tag.declaration.declarations) {
148-
for (const id of extract_identifiers(declaration.id)) {
149-
identifiers.add(id.name);
103+
function has_reference(keys, tag) {
104+
for (const declaration of tag.declaration.declarations) {
105+
for (const id of extract_identifiers(declaration.id)) {
106+
if (keys.has(id.name)) {
107+
return true;
150108
}
151109
}
152110
}
153-
154-
if (identifiers.size === 0) {
155-
return false;
156-
}
157-
158-
for (const reference of references.keys()) {
159-
if (identifiers.has(reference)) {
160-
return true;
161-
}
162-
}
163111
return false;
164112
}

packages/svelte/src/internal/client/dom/blocks/boundary.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @import { Effect, TemplateNode, } from '#client' */
22

3+
import { HYDRATION_START } from '../../../../constants.js';
34
import { BOUNDARY_EFFECT, EFFECT_TRANSPARENT } from '../../constants.js';
45
import { component_context, set_component_context } from '../../context.js';
56
import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';
@@ -17,7 +18,8 @@ import {
1718
hydrating,
1819
next,
1920
remove_nodes,
20-
set_hydrate_node
21+
set_hydrate_node,
22+
set_hydrating
2123
} from '../hydration.js';
2224
import { queue_micro_task } from '../task.js';
2325

@@ -119,12 +121,27 @@ export function boundary(node, props, boundary_fn) {
119121
}
120122
};
121123

124+
let mismatch = false;
125+
122126
if (hydrating) {
127+
const data = /** @type {Comment} */ (anchor).data;
123128
hydrate_next();
129+
if (data !== HYDRATION_START) {
130+
anchor = remove_nodes();
131+
132+
set_hydrate_node(anchor);
133+
set_hydrating(false);
134+
mismatch = true;
135+
}
124136
}
125137

126138
boundary_effect = branch(() => boundary_fn(anchor));
127139
reset_is_throwing_error();
140+
141+
if (mismatch) {
142+
// continue in hydration mode
143+
set_hydrating(true);
144+
}
128145
}, EFFECT_TRANSPARENT | BOUNDARY_EFFECT);
129146

130147
if (hydrating) {

0 commit comments

Comments
 (0)