-
Notifications
You must be signed in to change notification settings - Fork 650
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5cc3648
commit 491413d
Showing
11 changed files
with
349 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@marko/runtime-tags": patch | ||
--- | ||
|
||
Add await tag ssr. |
26 changes: 26 additions & 0 deletions
26
...ages/runtime-tags/src/__tests__/fixtures/await-tag/__snapshots__/dom.expected/template.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
export const _template_ = "<div><button>Inc</button></div>"; | ||
export const _walks_ = /* next(1), get, out(1) */"D l"; | ||
import { resolveAfter } from "../../utils/resolve"; | ||
import * as _$ from "@marko/runtime-tags/debug/dom"; | ||
const _value$await_content3 = /* @__PURE__ */_$.value("value", (_scope, value) => _$.data(_scope["#text/0"], value)); | ||
const _params_4$await_content = /* @__PURE__ */_$.value("_params_4", (_scope, _params_4) => _value$await_content3(_scope, _params_4[0])); | ||
const _count$await_content3 = /* @__PURE__ */_$.closure("count", (_scope, count) => _$.data(_scope["#text/1"], count)); | ||
const _await_content3 = _$.register("__tests__/template.marko_3_renderer", /* @__PURE__ */_$.createRenderer("Got: <!> <!>", /* over(1), replace, over(2), replace */"b%c%", void 0, () => [_count$await_content3], () => _params_4$await_content)); | ||
const _value$await_content2 = /* @__PURE__ */_$.value("value", (_scope, value) => _$.data(_scope["#text/0"], value)); | ||
const _params_3$await_content = /* @__PURE__ */_$.value("_params_3", (_scope, _params_3) => _value$await_content2(_scope, _params_3[0])); | ||
const _count$await_content2 = /* @__PURE__ */_$.closure("count", (_scope, count) => _$.data(_scope["#text/1"], count)); | ||
const _await_content2 = _$.register("__tests__/template.marko_2_renderer", /* @__PURE__ */_$.createRenderer("Got: <!> <!>", /* over(1), replace, over(2), replace */"b%c%", void 0, () => [_count$await_content2], () => _params_3$await_content)); | ||
const _value$await_content = /* @__PURE__ */_$.value("value", (_scope, value) => _$.data(_scope["#text/0"], value)); | ||
const _params_2$await_content = /* @__PURE__ */_$.value("_params_2", (_scope, _params_2) => _value$await_content(_scope, _params_2[0])); | ||
const _count$await_content = /* @__PURE__ */_$.closure("count", (_scope, count) => _$.data(_scope["#text/1"], count)); | ||
const _await_content = _$.register("__tests__/template.marko_1_renderer", /* @__PURE__ */_$.createRenderer("Got: <!> <!>", /* over(1), replace, over(2), replace */"b%c%", void 0, () => [_count$await_content], () => _params_2$await_content)); | ||
const _count_effect = _$.effect("__tests__/template.marko_0_count", (_scope, { | ||
count | ||
}) => _$.on(_scope["#button/0"], "click", function () { | ||
_count(_scope, count + 1), count; | ||
})); | ||
const _count = /* @__PURE__ */_$.state("count", (_scope, count) => _count_effect(_scope), () => _$.intersections([_count$await_content, _count$await_content2, _count$await_content3])); | ||
export function _setup_(_scope) { | ||
_count(_scope, 0); | ||
} | ||
export default /* @__PURE__ */_$.createTemplate("__tests__/template.marko", _template_, _walks_, _setup_); |
34 changes: 34 additions & 0 deletions
34
...ges/runtime-tags/src/__tests__/fixtures/await-tag/__snapshots__/html.expected/template.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { resolveAfter } from "../../utils/resolve"; | ||
import * as _$ from "@marko/runtime-tags/debug/html"; | ||
const _renderer = /* @__PURE__ */_$.createRenderer((input, _tagVar) => { | ||
const _scope0_id = _$.nextScopeId(); | ||
const count = 0; | ||
_$.write("<div>"); | ||
_$.fork(Promise.resolve("a"), value => { | ||
const _scope1_id = _$.nextScopeId(); | ||
_$.write(`Got: ${_$.escapeXML(value)} <!>${_$.escapeXML(count)}${_$.markResumeNode(_scope1_id, "#text/1")}`); | ||
_$.writeScope(_scope1_id, { | ||
"_": _$.ensureScopeWithId(_scope0_id) | ||
}); | ||
}); | ||
_$.fork(resolveAfter("b", 2), value => { | ||
const _scope2_id = _$.nextScopeId(); | ||
_$.write(`Got: ${_$.escapeXML(value)} <!>${_$.escapeXML(count)}${_$.markResumeNode(_scope2_id, "#text/1")}`); | ||
_$.writeScope(_scope2_id, { | ||
"_": _$.ensureScopeWithId(_scope0_id) | ||
}); | ||
}); | ||
_$.fork(resolveAfter("c", 1), value => { | ||
const _scope3_id = _$.nextScopeId(); | ||
_$.write(`Got: ${_$.escapeXML(value)} <!>${_$.escapeXML(count)}${_$.markResumeNode(_scope3_id, "#text/1")}`); | ||
_$.writeScope(_scope3_id, { | ||
"_": _$.ensureScopeWithId(_scope0_id) | ||
}); | ||
}); | ||
_$.write(`<button>Inc</button>${_$.markResumeNode(_scope0_id, "#button/0")}</div>`); | ||
_$.writeEffect(_scope0_id, "__tests__/template.marko_0_count"); | ||
_$.writeScope(_scope0_id, { | ||
"count": count | ||
}); | ||
}); | ||
export default /* @__PURE__ */_$.createTemplate("__tests__/template.marko", _renderer); |
9 changes: 9 additions & 0 deletions
9
...e-tags/src/__tests__/fixtures/await-tag/__snapshots__/ssr-sanitized.expected.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Render "End" | ||
```html | ||
<div> | ||
Got: a 0Got: b 0Got: c 0 | ||
<button> | ||
Inc | ||
</button> | ||
</div> | ||
``` |
76 changes: 76 additions & 0 deletions
76
...ges/runtime-tags/src/__tests__/fixtures/await-tag/__snapshots__/ssr.expected.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Write | ||
<div>Got: a <!>0<!--M_*1 #text/1--><script>WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b={0:_.a={count:0},1:{_:_.a}})]</script> | ||
|
||
|
||
# Write | ||
<script>M._.r.push(_=>(_.c={2:{_:_.a}}))</script> | ||
|
||
|
||
# Write | ||
Got: b <!>0<!--M_*3 #text/1-->Got: c <!>0<!--M_*2 #text/1--><button>Inc</button><!--M_*0 #button/0--></div><script>M._.r.push(_=>(_.d={3:{_:_.a}}),0,"__tests__/template.marko_0_count",0);M._.w()</script> | ||
|
||
|
||
# Render "End" | ||
```html | ||
<html> | ||
<head /> | ||
<body> | ||
<div> | ||
Got: a | ||
<!----> | ||
0 | ||
<!--M_*1 #text/1--> | ||
<script> | ||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b={0:_.a={count:0},1:{_:_.a}})] | ||
</script> | ||
<script> | ||
M._.r.push(_=>(_.c={2:{_:_.a}})) | ||
</script> | ||
Got: b | ||
<!----> | ||
0 | ||
<!--M_*3 #text/1--> | ||
Got: c | ||
<!----> | ||
0 | ||
<!--M_*2 #text/1--> | ||
<button> | ||
Inc | ||
</button> | ||
<!--M_*0 #button/0--> | ||
</div> | ||
<script> | ||
M._.r.push(_=>(_.d={3:{_:_.a}}),0,"__tests__/template.marko_0_count",0);M._.w() | ||
</script> | ||
</body> | ||
</html> | ||
``` | ||
|
||
# Mutations | ||
``` | ||
inserted #document/html0 | ||
inserted #document/html0/head0 | ||
inserted #document/html0/body1 | ||
inserted #document/html0/body1/div0 | ||
inserted #document/html0/body1/div0/#text0 | ||
inserted #document/html0/body1/div0/#comment1 | ||
inserted #document/html0/body1/div0/#text2 | ||
inserted #document/html0/body1/div0/#comment3 | ||
inserted #document/html0/body1/div0/script4 | ||
inserted #document/html0/body1/div0/script4/#text0 | ||
inserted #document/html0/body1/div0/script5 | ||
inserted #document/html0/body1/div0/script5/#text0 | ||
inserted #document/html0/body1/div0/#text6 | ||
inserted #document/html0/body1/div0/#comment7 | ||
inserted #document/html0/body1/div0/#text8 | ||
inserted #document/html0/body1/div0/#comment9 | ||
inserted #document/html0/body1/div0/#text10 | ||
inserted #document/html0/body1/div0/#comment11 | ||
inserted #document/html0/body1/div0/#text12 | ||
inserted #document/html0/body1/div0/#comment13 | ||
inserted #document/html0/body1/div0/button14 | ||
inserted #document/html0/body1/div0/button14/#text0 | ||
inserted #document/html0/body1/div0/#comment15 | ||
inserted #document/html0/body1/script1 | ||
inserted #document/html0/body1/script1/#text0 | ||
``` |
22 changes: 22 additions & 0 deletions
22
packages/runtime-tags/src/__tests__/fixtures/await-tag/template.marko
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { resolveAfter } from "../../utils/resolve"; | ||
|
||
<let/count = 0/> | ||
<div> | ||
<await|value|=Promise.resolve("a")> | ||
Got: ${value} ${count} | ||
</await> | ||
|
||
<await|value|=resolveAfter("b", 2)> | ||
Got: ${value} ${count} | ||
</await> | ||
|
||
<await|value|=resolveAfter("c", 1)> | ||
Got: ${value} ${count} | ||
</await> | ||
|
||
<button onClick() { | ||
count++ | ||
}> | ||
Inc | ||
</button> | ||
</div> |
7 changes: 7 additions & 0 deletions
7
packages/runtime-tags/src/__tests__/fixtures/await-tag/test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const skip_csr = true; | ||
|
||
export const steps = [{}, click, click, click]; | ||
|
||
function click(container: Element) { | ||
container.querySelector("button")!.click(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import { types as t } from "@marko/compiler"; | ||
import { | ||
assertNoArgs, | ||
assertNoAttributeTags, | ||
assertNoVar, | ||
type Tag, | ||
} from "@marko/compiler/babel-utils"; | ||
|
||
import { assertNoSpreadAttrs } from "../util/assert"; | ||
import evaluate from "../util/evaluate"; | ||
import { isStatefulReferences } from "../util/is-stateful"; | ||
import { BindingType, trackParamsReferences } from "../util/references"; | ||
import { callRuntime } from "../util/runtime"; | ||
import runtimeInfo from "../util/runtime-info"; | ||
import { | ||
checkStatefulClosures, | ||
getOrCreateSection, | ||
getSectionForBody, | ||
setSectionParentIsOwner, | ||
} from "../util/sections"; | ||
import { | ||
setForceResumeScope, | ||
setSubscriberBuilder, | ||
writeHTMLResumeStatements, | ||
} from "../util/signals"; | ||
import { toFirstExpressionOrBlock } from "../util/to-first-expression-or-block"; | ||
import { translateByTarget } from "../util/visitors"; | ||
import * as writer from "../util/writer"; | ||
|
||
export default { | ||
analyze(tag: t.NodePath<t.MarkoTag>) { | ||
assertNoVar(tag); | ||
assertNoArgs(tag); | ||
assertNoSpreadAttrs(tag); | ||
assertNoAttributeTags(tag); | ||
const { node } = tag; | ||
const [valueAttr] = node.attributes; | ||
|
||
if (!valueAttr) { | ||
throw tag | ||
.get("name") | ||
.buildCodeFrameError("The `await` tag requires a value."); | ||
} | ||
|
||
if ( | ||
node.attributes.length > 1 || | ||
!t.isMarkoAttribute(valueAttr) || | ||
valueAttr.name !== "value" | ||
) { | ||
throw tag | ||
.get("name") | ||
.buildCodeFrameError( | ||
"The `await` tag only supports the `value` attribute.", | ||
); | ||
} | ||
|
||
if (!node.body.body.length) { | ||
throw tag | ||
.get("name") | ||
.buildCodeFrameError("The `await` tag requires body content."); | ||
} | ||
|
||
if ( | ||
node.body.params.length && | ||
(node.body.params.length > 1 || t.isSpreadElement(node.body.params[0])) | ||
) { | ||
throw tag | ||
.get("name") | ||
.buildCodeFrameError( | ||
"The `await` tag only supports a single parameter.", | ||
); | ||
} | ||
|
||
getOrCreateSection(tag); | ||
trackParamsReferences( | ||
tag.get("body"), | ||
BindingType.derived, | ||
undefined, | ||
evaluate(valueAttr.value), | ||
); | ||
}, | ||
translate: translateByTarget({ | ||
html: { | ||
enter(tag) { | ||
const tagBody = tag.get("body"); | ||
const bodySection = getSectionForBody(tagBody); | ||
|
||
if (!bodySection) { | ||
tag.remove(); | ||
return; | ||
} | ||
|
||
setSectionParentIsOwner(bodySection, true); | ||
writer.flushBefore(tag); | ||
}, | ||
exit(tag) { | ||
const { node } = tag; | ||
const [valueAttr] = node.attributes; | ||
const tagBody = tag.get("body"); | ||
const bodySection = getSectionForBody(tagBody)!; | ||
|
||
if ( | ||
isStatefulReferences(valueAttr.extra?.referencedBindings) || | ||
checkStatefulClosures(bodySection, true) | ||
) { | ||
setForceResumeScope(bodySection); | ||
} | ||
|
||
writer.flushInto(tag); | ||
// TODO: this is a hack to get around the fact that we don't have a way to | ||
// know if a scope requires dynamic subscriptions | ||
setSubscriberBuilder(tag, (() => {}) as any); | ||
writeHTMLResumeStatements(tagBody); | ||
|
||
tag | ||
.replaceWith( | ||
t.expressionStatement( | ||
callRuntime( | ||
"fork", | ||
valueAttr.value, | ||
t.arrowFunctionExpression( | ||
node.body.params, | ||
toFirstExpressionOrBlock(node.body.body), | ||
), | ||
), | ||
), | ||
)[0] | ||
.skip(); | ||
}, | ||
}, | ||
dom: { | ||
enter(tag) { | ||
const tagBody = tag.get("body"); | ||
const bodySection = getSectionForBody(tagBody); | ||
|
||
if (!bodySection) { | ||
tag.remove(); | ||
return; | ||
} | ||
|
||
setSectionParentIsOwner(bodySection, true); | ||
// TODO: this is a hack to get around the fact that we don't have a way to | ||
// know if a scope requires dynamic subscriptions | ||
setSubscriberBuilder(tag, (signal) => signal); | ||
}, | ||
exit(tag) { | ||
tag.remove(); | ||
}, | ||
}, | ||
}), | ||
attributes: {}, | ||
autocomplete: [ | ||
{ | ||
description: "Use to consume asynchronous an data.", | ||
descriptionMoreURL: "https://markojs.com/docs/core-tags/#await", | ||
}, | ||
], | ||
types: runtimeInfo.name + "/tag-types/await.d.marko", | ||
} as Tag; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** File for types only, not actual implementation **/ | ||
|
||
export interface Input<T> { | ||
value: T; | ||
content: Marko.Body<[Awaited<T>]> | ||
} | ||
|
||
return=input.value |