Skip to content

Commit

Permalink
Showing 16 changed files with 121 additions and 141 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-jobs-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@marko/runtime-tags": patch
---

Fix async runtime placeholder duplication and race condition.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Render "End"
```html
aERROR!efg
aERROR!def
```
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@


# Write
<!--M_!a-->efg<style M_>t{display:none}</style><t c M_=a>ERROR!</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>
<!--M_!a-->def<style M_>t{display:none}</style><t M_=a>ERROR!</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>


# Render "End"
@@ -17,7 +17,7 @@
</style>
</head>
<body>
aERROR!efg
aERROR!def
<script>
WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()
</script>
Original file line number Diff line number Diff line change
@@ -13,15 +13,15 @@ const renderer = () => {
() => {
write("b");
fork(rejectAfter(new Error("ERROR!"), 2), write);
write("d");
write("c");
},
(err) => {
write((err as Error).message);
},
);
write("e");
fork(resolveAfter("f", 1), write);
write("g");
write("d");
fork(resolveAfter("e", 1), write);
write("f");
};

export default createTemplate("", renderer);
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ const firstComponent = () => {
write("d");
},
() => {
write("e...");
write("_A_");
},
);
write("e");
@@ -30,18 +30,18 @@ const firstComponent = () => {
};

const secondComponent = () => {
write("v");
write("1");
tryPlaceholder(
() => {
write("w");
fork(resolveAfter("x", 2), write);
write("y");
write("2");
fork(resolveAfter("3", 2), write);
write("4");
},
() => {
write("z...");
write("_B_");
},
);
write("z");
write("5");
};

export default createTemplate("", renderer);
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
# Render "End"
```html
abdfgh
<t
c=""
m_="b"
>
cd
</t>
abcdefg
```
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Write
a<!--M_!^a-->e...<!--M_!a-->f<style M_>t{display:none}</style><t M_=a>b<!--M_#b-->d</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>
a<!--M_!^a-->_A_<!--M_!a-->e<style M_>t{display:none}</style><t M_=a>b<!--M_#b-->d</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>


# Write
gh
fg


# Write
<t c M_=b>cd</t><script>M._.w()</script>
<t M_=b>c</t><script>M._.w()</script>


# Render "End"
@@ -21,19 +21,11 @@
</style>
</head>
<body>
ab
<!--M_#b-->
df
abcde
<script>
WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()
</script>
gh
<t
c=""
m_="b"
>
cd
</t>
fg
<script>
M._.w()
</script>
@@ -55,23 +47,27 @@ inserted #document/html0/head0/style0
inserted #document/html0/head0/style0/#text0
inserted t
inserted #document/html0/body1/#text1
inserted #document/html0/body1/#comment2
inserted #comment
inserted #document/html0/body1/#text3
inserted #document/html0/body1/script5
inserted #document/html0/body1/script5/#text0
removed #document/html0/head0/style0 after #document/html0/body1/#text4
inserted #document/html0/head0/style0
inserted #document/html0/body1/#text6
inserted #document/html0/body1/t7
inserted #document/html0/body1/t7/#text0
inserted #document/html0/body1/script8
inserted #document/html0/body1/script8/#text0
inserted t
inserted #document/html0/body1/#text2
inserted #document/html0/body1/script7
inserted #document/html0/body1/script7/#text0
removed #document/html0/body1/#text2 in t
removed #comment after #document/html0/body1/#text1
inserted #document/html0/body1/#text2
removed t after #document/html0/body1/#text6
removed #text after #comment
removed #comment after #comment
removed #document/html0/body1/#text1 before #document/html0/body1/#comment2
removed #document/html0/body1/#comment2 before #document/html0/body1/#text3
removed #document/html0/body1/#text1 before #document/html0/body1/#text2
removed #document/html0/body1/#text2 before #document/html0/body1/#text3
removed #document/html0/body1/#text3 in t
removed #comment after #document/html0/body1/#text0
inserted #document/html0/body1/#text1, #document/html0/body1/#comment2, #document/html0/body1/#text3
inserted #document/html0/body1/#text1, #document/html0/body1/#text2, #document/html0/body1/#text3
removed t after #document/html0/body1/#text4
```
Original file line number Diff line number Diff line change
@@ -16,12 +16,12 @@ const renderer = () => {
write("d");
},
() => {
write("e...");
write("_A_");
},
);
write("f");
fork(resolveAfter("g", 1), write);
write("h");
write("e");
fork(resolveAfter("f", 1), write);
write("g");
};

export default createTemplate("", renderer);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Render "End"
```html
abdef
abcde
```
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Write
abd
abc


# Write
ef
de


# Render "End"
```html
<html>
<head />
<body>
abdef
abcde
</body>
</html>
```
Original file line number Diff line number Diff line change
@@ -14,12 +14,12 @@ const renderer = () => {
write("b");
},
() => {
write("c...");
write("_A_");
},
);
write("d");
fork(resolveAfter("e", 1), write);
write("f");
write("c");
fork(resolveAfter("d", 1), write);
write("e");
};

export default createTemplate("", renderer);
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
# Render "End"
```html
abdeg
<t
c=""
m_="d"
>
fg
</t>
abcdefghij
```
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Write
a<!--M_!^a-->i...<!--M_!a-->j<style M_>t{display:none}</style><t M_=a>b<!--M_#b-->d<!--M_!^c-->h...<!--M_!c--></t><t M_=c>e<!--M_#d-->g</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>
a<!--M_!^a-->_B_<!--M_!a-->h<style M_>t{display:none}</style><t M_=a>b<!--M_#b-->d<!--M_!^c-->_A_<!--M_!c--></t><t M_=c>e<!--M_#d-->g</t><script>WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()</script>


# Write
kl
ij


# Write
<t c M_=b>cd<!--M_!^c-->h...<!--M_!c--></t><script>M._.w()</script>
<t M_=b>c</t><script>M._.w()</script>


# Write
<t c M_=d>fg</t><script>M._.w()</script>
<t M_=d>f</t><script>M._.w()</script>


# Render "End"
@@ -25,20 +25,14 @@
</style>
</head>
<body>
ab
<!--M_#b-->
de
<!--M_#d-->
g
abcdefgh
<script>
WALKER_RUNTIME("M")("_");REORDER_RUNTIME(M._);M._.w()
</script>
ij
<script>
M._.w()
</script>
<t
c=""
m_="d"
>
fg
</t>
<script>
M._.w()
</script>
@@ -55,54 +49,58 @@ inserted #document/html0/body1/#text0
inserted #comment
inserted #text
inserted #comment
inserted #text
inserted #document/html0/body1/#text7
inserted #document/html0/head0/style0
inserted #document/html0/head0/style0/#text0
inserted t
inserted #document/html0/body1/#text1
inserted #document/html0/body1/#comment2
inserted #comment
inserted #document/html0/body1/#text3
inserted #comment
inserted #text
inserted #comment
inserted t
inserted #document/html0/body1/#text4
inserted #document/html0/body1/#comment5
inserted #comment
inserted #document/html0/body1/#text6
inserted script
inserted script/#text0
removed #document/html0/head0/style0 after #text
inserted #document/html0/body1/script8
inserted #document/html0/body1/script8/#text0
removed #document/html0/head0/style0 after #document/html0/body1/#text7
inserted #document/html0/head0/style0
inserted #text
inserted #document/html0/body1/#text9
inserted t
inserted t/#text0
inserted t/#comment1
inserted t/#text2
inserted t/#comment3
inserted #document/html0/body1/script7
inserted #document/html0/body1/script7/#text0
inserted #document/html0/body1/#text2
inserted #document/html0/body1/script10
inserted #document/html0/body1/script10/#text0
removed #document/html0/body1/#text2 in t
removed #comment after #document/html0/body1/#text1
inserted #document/html0/body1/#text2
removed t after #document/html0/body1/#text9
removed #text after #comment
removed #comment after #comment
removed #document/html0/body1/#text1 before #document/html0/body1/#comment2
removed #document/html0/body1/#comment2 before #document/html0/body1/#text3
removed #document/html0/body1/#text1 before #document/html0/body1/#text2
removed #document/html0/body1/#text2 before #document/html0/body1/#text3
removed #document/html0/body1/#text3 before #comment
removed #comment before #text
removed #text before #comment
removed #comment in t
removed #comment after #document/html0/body1/#text0
inserted #document/html0/body1/#text1, #document/html0/body1/#comment2, #document/html0/body1/#text3, #comment, #text, #comment
removed t after #text
inserted #document/html0/body1/t8
inserted #document/html0/body1/t8/#text0
inserted #document/html0/body1/script9
inserted #document/html0/body1/script9/#text0
inserted #document/html0/body1/#text1, #document/html0/body1/#text2, #document/html0/body1/#text3, #comment, #text, #comment
removed t after #document/html0/body1/#text7
inserted t
inserted #document/html0/body1/#text5
inserted #document/html0/body1/script11
inserted #document/html0/body1/script11/#text0
removed #document/html0/body1/#text5 in t
removed #comment after #document/html0/body1/#text4
inserted #document/html0/body1/#text5
removed t after #document/html0/body1/script10
removed #text after #comment
removed #comment after #comment
removed #text after #comment
removed t after #comment
removed script after #comment
removed #text after #comment
removed t after #comment
removed #document/html0/body1/#text4 before #document/html0/body1/#text5
removed #document/html0/body1/#text5 before #document/html0/body1/#text6
removed #document/html0/body1/#text6 in t
removed #comment after #document/html0/body1/#text3
inserted #document/html0/body1/#text4, #document/html0/body1/#comment5, #document/html0/body1/#text6
inserted #document/html0/body1/#text4, #document/html0/body1/#text5, #document/html0/body1/#text6
removed t after #document/html0/body1/#text7
```
Original file line number Diff line number Diff line change
@@ -21,17 +21,17 @@ const renderer = () => {
write("g");
},
() => {
write("h...");
write("_A_");
},
);
},
() => {
write("i...");
write("_B_");
},
);
write("h");
fork(resolveAfter("i", 1), write);
write("j");
fork(resolveAfter("k", 1), write);
write("l");
};

export default createTemplate("", renderer);
51 changes: 22 additions & 29 deletions packages/runtime-tags/src/html/inlined-runtimes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const WALKER_RUNTIME_CODE = MARKO_DEBUG
? `((runtimeId) =>
? /* js */ `((runtimeId) =>
(self[runtimeId] =
self[runtimeId] ||
((renderId) => {
@@ -36,13 +36,12 @@ export const WALKER_RUNTIME_CODE = MARKO_DEBUG
}),
prefix = renderId.length;
})))`
: `(e=>self[e]=self[e]||(l=>{let t,d={},f=[],s=document,a=s.createTreeWalker(s,129),r=self[e][l]={i:l=e+l,d:s,l:d,v:f,x(){},w(e){for(;e=a.nextNode();)this.x(r=(r=e.data)&&!r.indexOf(l)&&(d[t=r.slice(x+1)]=e,r[x]),t,e),r>"#"&&f.push(e)}},x=l.length}))`;
: `(e=>self[e]=self[e]||(l=>{let t,d={},s=[],f=document,i=f.createTreeWalker(f,129),n=self[e][l]={i:l=e+l,d:f,l:d,v:s,x(){},w(e){for(;e=i.nextNode();)this.x(n=(n=e.data)&&!n.indexOf(l)&&(d[t=n.slice(x+1)]=e,n[x]),t,e),n>"#"&&s.push(e)}},x=l.length}))`;
export const REORDER_RUNTIME_CODE = MARKO_DEBUG
? `((runtime) => {
let insertOne,
? /* js */ `((runtime) => {
let onNextSibling,
placeholder,
nextSibling,
previousSibling,
placeholders = {},
replace = (marker, container) => {
marker.replaceWith(...container.childNodes);
@@ -53,21 +52,19 @@ runtime.d.head.append(
);
runtime.j = {};
runtime.x = (op, id, node, start, placeholderCallback) => {
// "node" and "end" are all closed over and can't be repurposed. "start" is too but only in the new placeholder case
if (op == "#") {
(placeholders[id] = placeholder).i++;
} else if (node == nextSibling) {
insertOne();
onNextSibling();
}
if (node.tagName == "T" && (id = node.getAttribute(runtime.i))) {
start = runtime.l["^" + id];
if (start) {
placeholder = placeholders[id] = {
i: 0,
c(end = runtime.l[id] || previousSibling || node) {
placeholders[id] = {
i: 1,
c(end = runtime.l[id] || node) {
while (end.parentNode !== start.parentNode) {
end = end.parentNode;
}
@@ -80,27 +77,23 @@ runtime.x = (op, id, node, start, placeholderCallback) => {
replace(start, node);
},
};
} else {
insertOne = () => {
previousSibling = node.previousSibling;
replace(runtime.l[id], node);
if (!--start.i) {
start.c();
}
};
// repurpose "start" to hold this placeholder
start = placeholder = placeholders[id];
nextSibling = node.nextElementSibling || insertOne();
}
// repurpose "op" for callbacks ...carefully
placeholderCallback = placeholder.c;
(op = runtime.j[id]) &&
(placeholder.c = () => placeholderCallback() + op(runtime));
nextSibling = node.nextSibling;
placeholder = placeholders[id];
onNextSibling = () => {
start || replace(runtime.l[id], node);
if (!--placeholder.i) {
placeholder.c();
}
};
if (node.attributes.c) placeholder.c();
// repurpose "op" for callbacks ...carefully
if (op = runtime.j[id]) {
placeholderCallback = placeholder.c;
placeholder.c = () => placeholderCallback() + op(runtime);
}
}
};
})`
: `(e=>{let i,t,r,l,d={},n=(e,i)=>{e.replaceWith(...i.childNodes),i.remove()};e.d.head.append(e.d.querySelector("style["+e.i+"]")||""),e.j={},e.x=(o,a,c,p,b)=>{"#"==o?(d[a]=t).i++:c==r&&i(),"T"==c.tagName&&(a=c.getAttribute(e.i))&&((p=e.l["^"+a])?t=d[a]={i:0,c(i=e.l[a]||l||c){for(;i.parentNode!==p.parentNode;)i=i.parentNode;for(;i!=r;(r=p.nextSibling).remove());n(p,c)}}:(i=()=>{l=c.previousSibling,n(e.l[a],c),--p.i||p.c()},p=t=d[a],r=c.nextElementSibling||i()),b=t.c,(o=e.j[a])&&(t.c=()=>b()+o(e)),c.attributes.c&&t.c())}})`;
: `(e=>{let i,t,r,l={},o=(e,i)=>{e.replaceWith(...i.childNodes),i.remove()};e.d.head.append(e.d.querySelector("style["+e.i+"]")||""),e.j={},e.x=(d,n,a,c,p)=>{"#"==d?(l[n]=t).i++:a==r&&i(),"T"==a.tagName&&(n=a.getAttribute(e.i))&&((c=e.l["^"+n])&&(l[n]={i:1,c(i=e.l[n]||a){for(;i.parentNode!==c.parentNode;)i=i.parentNode;for(;i!=r;(r=c.nextSibling).remove());o(c,a)}}),r=a.nextSibling,t=l[n],i=()=>{c||o(e.l[n],a),--t.i||t.c()},(d=e.j[n])&&(p=t.c,t.c=()=>p()+d(e)))}})`;
10 changes: 5 additions & 5 deletions packages/runtime-tags/src/html/writer.ts
Original file line number Diff line number Diff line change
@@ -610,15 +610,16 @@ export function prepareChunk(chunk: Chunk) {

for (const reorderedChunk of state.writeReorders) {
const { reorderId } = reorderedChunk;
let isSync = true;
let reorderHTML = "";
let reorderEffects = "";
let reorderScripts = "";
let cur = reorderedChunk;
reorderedChunk.reorderId = null;

for (;;) {
const { next } = cur;
cur.flushPlaceholder();
cur.consumed = true;
reorderHTML += cur.html;
reorderEffects = concatEffects(reorderEffects, cur.effects);
reorderScripts = concatScripts(reorderScripts, cur.scripts);
@@ -629,11 +630,11 @@ export function prepareChunk(chunk: Chunk) {
(cur.reorderId = state.nextReorderId()),
);
cur.html = cur.effects = cur.scripts = "";
isSync = false;
cur.next = null;
}

if (cur.next) {
cur = cur.next;
if (next) {
cur = next;
} else {
break;
}
@@ -668,7 +669,6 @@ export function prepareChunk(chunk: Chunk) {

html +=
"<t " +
(isSync ? "c " : "") +
state.commentPrefix +
"=" +
reorderId +

0 comments on commit 5cc3648

Please sign in to comment.