fix: ensure serizlie reason is set before child call

This commit is contained in:
Ryan Turnquist 2025-10-02 09:45:14 -07:00
parent e16cc81208
commit c5ccff4ff0
19 changed files with 499 additions and 13 deletions

View File

@ -0,0 +1,5 @@
---
"@marko/runtime-tags": patch
---
Ensure serialize reason is set before child call in server compilation

View File

@ -7,6 +7,11 @@ export default _._template("__tests__/template.marko", input => {
x
} = input;
const $childScope = _._peek_scope_id();
_._set_serialize_reason({
/* input.thing.x, input.thing.content */0: _._serialize_guard($serialize, /* x */0),
/* input.thing.x */1: _._serialize_guard($serialize, /* x */0),
/* input.thing.content */2: _._serialize_guard($serialize, /* x */0)
});
let $thing;
if (x) {
$thing = _.attrTag({
@ -25,11 +30,6 @@ export default _._template("__tests__/template.marko", input => {
})
});
}
_._set_serialize_reason({
/* input.thing.x, input.thing.content */0: _._serialize_guard($serialize, /* x */0),
/* input.thing.x */1: _._serialize_guard($serialize, /* x */0),
/* input.thing.content */2: _._serialize_guard($serialize, /* x */0)
});
_customTag({
thing: $thing
});

View File

@ -4,6 +4,7 @@ export default _._template("__tests__/template.marko", input => {
const $scope0_id = _._scope_id();
let x = true;
const $childScope = _._peek_scope_id();
_._set_serialize_reason(/* state: x */1);
let $item;
if (x) {
$item = _.attrTag({
@ -15,7 +16,6 @@ export default _._template("__tests__/template.marko", input => {
})
});
}
_._set_serialize_reason(/* state: x */1);
_hello({
item: $item
});

View File

@ -0,0 +1,13 @@
{
"vars": {
"props": {
"$_": "m",
"$init": "o",
"$$count__script": "r",
"$$count": "t",
"$$if_content": "n",
"$$if": "_",
"$$input_value": "a"
}
}
}

View File

@ -0,0 +1,43 @@
# Render
```html
<button>
1
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
2
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
3
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
4
</button>
<span />
```

View File

@ -0,0 +1,72 @@
# Render
```html
<button>
1
</button>
<!---->
<span />
<!---->
<!---->
```
# Mutations
```
INSERT button, #comment0, span, #comment1, #comment2
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
2
</button>
<!---->
<span />
<!---->
<!---->
```
# Mutations
```
UPDATE button/#text "1" => "2"
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
3
</button>
<!---->
<span />
<!---->
<!---->
```
# Mutations
```
UPDATE button/#text "2" => "3"
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
4
</button>
<!---->
<span />
<!---->
<!---->
```
# Mutations
```
UPDATE button/#text "3" => "4"
```

View File

@ -0,0 +1,11 @@
export const $template = "<!><!><!>";
export const $walks = /* over(1), replace, over(2) */"b%c";
import * as _ from "@marko/runtime-tags/debug/dom";
const $if_content = /* @__PURE__ */_._content_branch("<span></span>", /* over(1) */"b");
const $if = /* @__PURE__ */_._if("#text/0", $if_content);
export const $input_value = /* @__PURE__ */_._const("input_value", ($scope, input_value) => $if($scope, input_value ? 0 : 1));
export function $setup($scope) {
_._return($scope, 1);
}
export const $input = /* @__PURE__ */_._const("input", ($scope, input) => $input_value($scope, input.value));
export default /* @__PURE__ */_._template("__tests__/tags/child.marko", $template, $walks, $setup, $input);

View File

@ -0,0 +1,17 @@
// size: 244 (min) 173 (brotli)
const $if_content = _._content_branch("<span></span>", "b"),
$if = _._if(0, $if_content),
$input_value = _._const(3, ($scope, input_value) =>
$if($scope, input_value ? 0 : 1),
),
$count__script = _._script("b0", ($scope, { 4: count }) =>
_._on($scope[0], "click", function () {
$count($scope, ++count);
}),
),
$count = _._let(4, ($scope, count) => {
(_._text($scope[1], count),
$input_value($scope[2], count),
$count__script($scope));
});
(_._var_resume("b1", ($scope) => {}), init());

View File

@ -0,0 +1,21 @@
export const $template = `<button> </button>${_child_template}<!>`;
export const $walks = /* get, next(1), get, out(1), beginChildWithVar, _child_walks, endChild, over(1) */` D l0${_child_walks}&b`;
import * as _ from "@marko/runtime-tags/debug/dom";
import { $setup as _child, $input_value as _child_input_value, $template as _child_template, $walks as _child_walks } from "./tags/child.marko";
const $count__script = _._script("__tests__/template.marko_0_count", ($scope, {
count
}) => _._on($scope["#button/0"], "click", function () {
$count($scope, ++count);
}));
const $count = /* @__PURE__ */_._let("count/4", ($scope, count) => {
_._text($scope["#text/1"], count);
_child_input_value($scope["#childScope/2"], count);
$count__script($scope);
});
export function $setup($scope) {
_._var($scope, "#childScope/2", $x);
_child($scope["#childScope/2"]);
$count($scope, 1);
}
const $x = _._var_resume("__tests__/template.marko_0_x/var", $scope => {});
export default /* @__PURE__ */_._template("__tests__/template.marko", $template, $walks, $setup);

View File

@ -0,0 +1,16 @@
import * as _ from "@marko/runtime-tags/debug/html";
export default _._template("__tests__/tags/child.marko", input => {
const $serialize = _._get_serialize_reason();
const $scope0_id = _._scope_id();
_._if(() => {
if (input.value) {
const $scope1_id = _._scope_id();
_._html("<span></span>");
_._serialize_guard($serialize, /* input.value */0) && _._scope($scope1_id, {}, "__tests__/tags/child.marko", "1:2");
return 0;
}
}, $scope0_id, "#text/0", _._serialize_guard($serialize, /* input.value */0), _._serialize_guard($serialize, /* input.value */0), _._serialize_guard($serialize, /* input.value */0), 0, 1);
const $return = 1;
_._serialize_guard($serialize, /* input.value */0) && _._scope($scope0_id, {}, "__tests__/tags/child.marko", 0);
return $return;
});

View File

@ -0,0 +1,21 @@
import * as _ from "@marko/runtime-tags/debug/html";
import _child from "./tags/child.marko";
export default _._template("__tests__/template.marko", input => {
const $scope0_id = _._scope_id();
let count = 1;
_._html(`<button>${_._escape(count)}${_._el_resume($scope0_id, "#text/1")}</button>${_._el_resume($scope0_id, "#button/0")}`);
const $childScope = _._peek_scope_id();
_._set_serialize_reason(/* state: count */1);
let x = _child({
value: count
});
_._var($scope0_id, "#scopeOffset/3", $childScope, "__tests__/template.marko_0_x/var");
_._script($scope0_id, "__tests__/template.marko_0_count");
_._scope($scope0_id, {
count,
"#childScope/2": _._existing_scope($childScope)
}, "__tests__/template.marko", 0, {
count: "1:6"
});
_._resume_branch($scope0_id);
});

View File

@ -0,0 +1,43 @@
# Render
```html
<button>
1
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
2
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
3
</button>
<span />
```
# Render
```js
container.querySelector("button").click();
```
```html
<button>
4
</button>
<span />
```

View File

@ -0,0 +1,154 @@
# Render
```html
<html>
<head />
<body>
<button>
1
<!--M_*1 #text/1-->
</button>
<!--M_*1 #button/0-->
<span />
<!--M_|2 #text/0 3-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
"#scopeOffset/3": 4,
count: 1,
"#childScope/2": _.b = {
"ConditionalScope:#text/0": _.c = {}
}
}, _.b, _.c], _.b["#TagVariable"] = _._[
"__tests__/template.marko_0_x/var"
](_.a), _.d),
"__tests__/template.marko_0_count",
1
];
M._.w()
</script>
</body>
</html>
```
# Render
```js
container.querySelector("button").click();
```
```html
<html>
<head />
<body>
<button>
2
<!--M_*1 #text/1-->
</button>
<!--M_*1 #button/0-->
<span />
<!--M_|2 #text/0 3-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
"#scopeOffset/3": 4,
count: 1,
"#childScope/2": _.b = {
"ConditionalScope:#text/0": _.c = {}
}
}, _.b, _.c], _.b["#TagVariable"] = _._[
"__tests__/template.marko_0_x/var"
](_.a), _.d),
"__tests__/template.marko_0_count",
1
];
M._.w()
</script>
</body>
</html>
```
# Mutations
```
UPDATE html/body/button/#text "1" => "2"
INSERT html/body/span
REMOVE span after html/body/span
```
# Render
```js
container.querySelector("button").click();
```
```html
<html>
<head />
<body>
<button>
3
<!--M_*1 #text/1-->
</button>
<!--M_*1 #button/0-->
<span />
<!--M_|2 #text/0 3-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
"#scopeOffset/3": 4,
count: 1,
"#childScope/2": _.b = {
"ConditionalScope:#text/0": _.c = {}
}
}, _.b, _.c], _.b["#TagVariable"] = _._[
"__tests__/template.marko_0_x/var"
](_.a), _.d),
"__tests__/template.marko_0_count",
1
];
M._.w()
</script>
</body>
</html>
```
# Mutations
```
UPDATE html/body/button/#text "2" => "3"
```
# Render
```js
container.querySelector("button").click();
```
```html
<html>
<head />
<body>
<button>
4
<!--M_*1 #text/1-->
</button>
<!--M_*1 #button/0-->
<span />
<!--M_|2 #text/0 3-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
"#scopeOffset/3": 4,
count: 1,
"#childScope/2": _.b = {
"ConditionalScope:#text/0": _.c = {}
}
}, _.b, _.c], _.b["#TagVariable"] = _._[
"__tests__/template.marko_0_x/var"
](_.a), _.d),
"__tests__/template.marko_0_count",
1
];
M._.w()
</script>
</body>
</html>
```
# Mutations
```
UPDATE html/body/button/#text "3" => "4"
```

View File

@ -0,0 +1,7 @@
# Render End
```html
<button>
1
</button>
<span />
```

View File

@ -0,0 +1,51 @@
# Write
```html
<button>1<!--M_*1 #text/1--></button><!--M_*1 #button/0--><span></span><!--M_|2 #text/0 3--><script>WALKER_RUNTIME("M")("_");M._.r=[_=>(_.d=[0,_.a={"#scopeOffset/3":4,count:1,"#childScope/2":_.b={"ConditionalScope:#text/0":_.c={}}},_.b,_.c],_.b["#TagVariable"]=_._["__tests__/template.marko_0_x/var"](_.a),_.d),"__tests__/template.marko_0_count",1];M._.w()</script>
```
# Render End
```html
<html>
<head />
<body>
<button>
1
<!--M_*1 #text/1-->
</button>
<!--M_*1 #button/0-->
<span />
<!--M_|2 #text/0 3-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
"#scopeOffset/3": 4,
count: 1,
"#childScope/2": _.b = {
"ConditionalScope:#text/0": _.c = {}
}
}, _.b, _.c], _.b["#TagVariable"] = _._[
"__tests__/template.marko_0_x/var"
](_.a), _.d),
"__tests__/template.marko_0_count",
1
];
M._.w()
</script>
</body>
</html>
```
# Mutations
```
INSERT html
INSERT html/head
INSERT html/body
INSERT html/body/button
INSERT html/body/button/#text
INSERT html/body/button/#comment
INSERT html/body/#comment0
INSERT html/body/span
INSERT html/body/#comment1
INSERT html/body/script
INSERT html/body/script/#text
```

View File

@ -0,0 +1,4 @@
<if=input.value>
<span />
</if>
<return=1>

View File

@ -0,0 +1,3 @@
<let/count=1>
<button onClick() { count++ }>${count}</button>
<child/x=count />

View File

@ -0,0 +1,5 @@
export const steps = [{}, click, click, click];
function click(container: Element) {
container.querySelector("button")!.click();
}

View File

@ -182,12 +182,6 @@ export function knownTagTranslateHTML(
childScopeBinding,
);
const childSerializeReasonExpr = getParamGroupsSerializeGuard(
contentSection,
tagExtra[kKnownExprs]!,
contentSection.params,
);
if (childScopeSerializeReason) {
const peekScopeId = generateUidIdentifier(childScopeBinding?.name);
tag.insertBefore(
@ -223,8 +217,14 @@ export function knownTagTranslateHTML(
}
}
const childSerializeReasonExpr = getParamGroupsSerializeGuard(
contentSection,
tagExtra[kKnownExprs]!,
contentSection.params,
);
if (childSerializeReasonExpr) {
statements.push(
tag.insertBefore(
t.expressionStatement(
callRuntime("_set_serialize_reason", childSerializeReasonExpr),
),