Skip to content

Commit f2aaa35

Browse files
committed
fix: crash in some cases where internal references were wrong
1 parent b0f915a commit f2aaa35

File tree

2 files changed

+34
-27
lines changed

2 files changed

+34
-27
lines changed

src/block_compiler.ts

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ interface IntermediateTree {
113113
nextSibling: IntermediateTree | null;
114114
el: Node;
115115
info: DynamicInfo[];
116-
forceRef?: boolean;
116+
isRef?: boolean;
117117
refIdx?: number;
118118
refN: number;
119119
currentNS: string | null;
@@ -127,7 +127,6 @@ function buildTree(
127127
switch (node.nodeType) {
128128
case Node.ELEMENT_NODE: {
129129
// HTMLElement
130-
let isActive = false;
131130
let currentNS = parent && parent.currentNS;
132131
const tagName = (node as Element).tagName;
133132
let el: Node | undefined = undefined;
@@ -136,14 +135,14 @@ function buildTree(
136135
const index = parseInt(tagName.slice(11), 10);
137136
info.push({ type: "text", idx: index });
138137
el = document.createTextNode("");
139-
isActive = true;
140138
}
141139
if (tagName.startsWith("block-child-")) {
142-
domParentTree!.forceRef = true;
140+
if (!domParentTree!.isRef) {
141+
addRef(domParentTree!);
142+
}
143143
const index = parseInt(tagName.slice(12), 10);
144144
info.push({ type: "child", idx: index });
145145
el = document.createTextNode("");
146-
isActive = true;
147146
}
148147
const attrs = (node as Element).attributes;
149148
const ns = attrs.getNamedItem("block-ns");
@@ -161,15 +160,13 @@ function buildTree(
161160
const attrName = attrs[i].name;
162161
const attrValue = attrs[i].value;
163162
if (attrName.startsWith("block-handler-")) {
164-
isActive = true;
165163
const idx = parseInt(attrName.slice(14), 10);
166164
info.push({
167165
type: "handler",
168166
idx,
169167
event: attrValue,
170168
});
171169
} else if (attrName.startsWith("block-attribute-")) {
172-
isActive = true;
173170
const idx = parseInt(attrName.slice(16), 10);
174171
info.push({
175172
type: "attribute",
@@ -178,13 +175,11 @@ function buildTree(
178175
tag: tagName,
179176
});
180177
} else if (attrName === "block-attributes") {
181-
isActive = true;
182178
info.push({
183179
type: "attributes",
184180
idx: parseInt(attrValue, 10),
185181
});
186182
} else if (attrName === "block-ref") {
187-
isActive = true;
188183
info.push({
189184
type: "ref",
190185
idx: parseInt(attrValue, 10),
@@ -201,7 +196,7 @@ function buildTree(
201196
nextSibling: null,
202197
el,
203198
info,
204-
refN: isActive ? 1 : 0,
199+
refN: 0,
205200
currentNS,
206201
};
207202

@@ -215,8 +210,6 @@ function buildTree(
215210
const tagName = (childNode as Element).tagName;
216211
const index = parseInt(tagName.slice(12), 10);
217212
info.push({ idx: index, type: "child", isOnlyChild: true });
218-
isActive = true;
219-
tree.refN = 1;
220213
} else {
221214
tree.firstChild = buildTree(node.firstChild, tree, tree);
222215
el.appendChild(tree.firstChild.el);
@@ -229,11 +222,8 @@ function buildTree(
229222
}
230223
}
231224
}
232-
if (isActive) {
233-
let cur: IntermediateTree | null = tree;
234-
while ((cur = cur.parent)) {
235-
cur.refN++;
236-
}
225+
if (tree.info.length) {
226+
addRef(tree);
237227
}
238228
return tree;
239229
}
@@ -258,6 +248,13 @@ function buildTree(
258248
throw new Error("boom");
259249
}
260250

251+
function addRef(tree: IntermediateTree) {
252+
tree.isRef = true;
253+
do {
254+
tree.refN++;
255+
} while ((tree = tree.parent as any));
256+
}
257+
261258
function parentTree(tree: IntermediateTree): IntermediateTree | null {
262259
let parent = tree.parent;
263260
while (parent && parent.nextSibling === tree) {
@@ -304,21 +301,15 @@ interface BlockCtx {
304301
cbRefs: number[];
305302
}
306303

307-
function buildContext(
308-
tree: IntermediateTree,
309-
ctx?: BlockCtx,
310-
fromIdx?: number,
311-
toIdx?: number
312-
): BlockCtx {
304+
function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx {
313305
if (!ctx) {
314306
const children = new Array(tree.info.filter((v) => v.type === "child").length);
315307
ctx = { collectors: [], locations: [], children, cbRefs: [], refN: tree.refN };
316308
fromIdx = 0;
317-
toIdx = tree.refN - 1;
318309
}
319310
if (tree.refN) {
320311
const initialIdx = fromIdx!;
321-
const isRef = tree.forceRef || tree.info.length > 0;
312+
const isRef = tree.isRef;
322313
const firstChild = tree.firstChild ? tree.firstChild.refN : 0;
323314
const nextSibling = tree.nextSibling ? tree.nextSibling.refN : 0;
324315

@@ -336,13 +327,13 @@ function buildContext(
336327
if (nextSibling) {
337328
const idx = fromIdx! + firstChild;
338329
ctx.collectors.push({ idx, prevIdx: initialIdx, getVal: nodeGetNextSibling });
339-
buildContext(tree.nextSibling!, ctx, idx, toIdx);
330+
buildContext(tree.nextSibling!, ctx, idx);
340331
}
341332

342333
// left
343334
if (firstChild) {
344335
ctx.collectors.push({ idx: fromIdx!, prevIdx: initialIdx, getVal: nodeGetFirstChild });
345-
buildContext(tree.firstChild!, ctx, fromIdx!, toIdx! - nextSibling);
336+
buildContext(tree.firstChild!, ctx, fromIdx!);
346337
}
347338
}
348339

tests/block.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,22 @@ describe("misc", () => {
227227
expect(fixture.innerHTML).toBe("<p>() =&gt; 3tostring</p>");
228228
});
229229

230+
test("block with 2 subblocks: variation", async () => {
231+
const block = createBlock("<a><b><c><block-child-0/>2</c></b><block-child-1/></a>");
232+
const tree = block([], [text("1"), text("3")]);
233+
mount(tree, fixture);
234+
expect(fixture.innerHTML).toBe("<a><b><c>12</c></b>3</a>");
235+
});
236+
237+
test("block with 2 subblocks: another variation", async () => {
238+
const block = createBlock(
239+
`<a block-attribute-0="hello"><b><c><block-child-0/>2</c></b><block-child-1/></a>`
240+
);
241+
const tree = block(["world"], [text("1"), text("3")]);
242+
mount(tree, fixture);
243+
expect(fixture.innerHTML).toBe(`<a hello="world"><b><c>12</c></b>3</a>`);
244+
});
245+
230246
// test.skip("reusing a block skips patching process", async () => {
231247
// const block = createBlock('<div><block-text-0/></div>');
232248
// const foo = block(["foo"]);

0 commit comments

Comments
 (0)