feat: call queue function for let assignments

This commit is contained in:
Dylan Piercey 2022-01-13 12:53:34 -07:00 committed by Dylan Piercey
parent 9cc4ed81c8
commit e614acb044
7 changed files with 79 additions and 50 deletions

View File

@ -19,7 +19,24 @@ container.querySelector("button").click();
```html
<div>
<button>
0
1
</button>
</div>
```
# Mutations
```
div0/button0/#text0: "0" => "1"
```
# Render
container.querySelector("button").click();
```html
<div>
<button>
1
</button>
</div>
```
@ -36,24 +53,7 @@ container.querySelector("button").click();
```html
<div>
<button>
0
</button>
</div>
```
# Mutations
```
```
# Render
container.querySelector("button").click();
```html
<div>
<button>
0
1
</button>
</div>
```

View File

@ -1,4 +1,4 @@
import { write as _write, read as _read, on as _on, data as _data, bind as _bind, createRenderFn as _createRenderFn } from "@marko/runtime-fluurt/src/dom";
import { queue as _queue, write as _write, read as _read, on as _on, data as _data, bind as _bind, createRenderFn as _createRenderFn } from "@marko/runtime-fluurt/src/dom";
function _apply() {
_apply_clickCount(0);
@ -7,7 +7,7 @@ function _apply() {
const _onclick = function () {
const clickCount = _read(2);
clickCount++;
_queue(_apply_clickCount, 2, clickCount + 1);
};
function _apply_clickCount(clickCount) {

View File

@ -1,4 +1,6 @@
<div>
<let/clickCount = 0/>
<button onclick() { clickCount++ }>${clickCount}</button>
<button onclick() {
clickCount++
}>${clickCount}</button>
</div>

View File

@ -47,7 +47,7 @@ export default function enter(tag: t.NodePath<t.MarkoTag>) {
identifiers.length === 1
? t.expressionStatement(
t.callExpression(
writer.getApplyId(tag, identifiers[0].extra.binding!),
writer.bindingToApplyId(tag, identifiers[0].extra.binding!),
[defaultAttr.value]
)
)
@ -58,7 +58,7 @@ export default function enter(tag: t.NodePath<t.MarkoTag>) {
...identifiers.map((identifier) =>
t.expressionStatement(
t.callExpression(
writer.getApplyId(tag, identifier.extra.binding!),
writer.bindingToApplyId(tag, identifier.extra.binding!),
[t.identifier(identifier.name)]
)
)

View File

@ -4,21 +4,24 @@ import { assertNoBodyContent } from "../util/assert";
import translateVar from "../util/translate-var";
import { isOutputDOM } from "../util/marko-config";
import * as writer from "../util/writer";
import { callRuntime } from "../util/runtime";
import replaceAssignments from "../util/replace-assignments";
export default function enter(tag: t.NodePath<t.MarkoTag>) {
const { node } = tag;
const tagVar = node.var;
const [defaultAttr] = node.attributes;
assertNoParams(tag);
assertNoBodyContent(tag);
if (!node.var) {
if (!tagVar) {
throw tag
.get("name")
.buildCodeFrameError("The 'let' tag requires a tag variable.");
}
if (!t.isIdentifier(node.var)) {
if (!t.isIdentifier(tagVar)) {
throw tag
.get("var")
.buildCodeFrameError("The 'let' cannot be destructured.");
@ -43,16 +46,19 @@ export default function enter(tag: t.NodePath<t.MarkoTag>) {
}
if (isOutputDOM(tag)) {
const binding = tagVar.extra.binding!;
const applyId = writer.bindingToApplyId(tag, binding);
const scopeId = writer.bindingToScopeId(tag, binding);
// TODO: add defined guard if bindings exist.
writer.addStatement(
"apply",
tag,
defaultAttr.extra?.valueReferences,
t.expressionStatement(
t.callExpression(writer.getApplyId(tag, node.var.extra.binding!), [
defaultAttr.value,
])
)
t.expressionStatement(t.callExpression(applyId, [defaultAttr.value]))
);
replaceAssignments(tag.scope.getBinding(binding.name)!, (v) =>
callRuntime(tag, "queue", applyId, scopeId, v)
);
} else {
translateVar(tag, defaultAttr.value);

View File

@ -0,0 +1,33 @@
import { types as t } from "@marko/compiler";
export default function replaceAssignments(
binding: t.Binding,
map: (value: t.Expression) => t.Expression
): void {
for (const assignment of binding.constantViolations) {
let value: t.Expression | undefined;
if (assignment.isUpdateExpression()) {
value = t.binaryExpression(
assignment.node.operator === "++" ? "+" : "-",
binding.identifier,
t.numericLiteral(1)
);
} else if (assignment.isAssignmentExpression()) {
value =
assignment.node.operator === "="
? assignment.node.right
: t.binaryExpression(
assignment.node.operator.slice(
0,
-1
) as t.BinaryExpression["operator"],
binding.identifier,
assignment.node.right
);
}
if (value) {
assignment.parentPath!.replaceWith(map(value));
}
}
}

View File

@ -283,7 +283,7 @@ export function addStatement(
path,
"queue",
identifier,
t.numericLiteral(bindingToScopeId(path, binding))
bindingToScopeId(path, binding)
)
)
);
@ -300,7 +300,7 @@ export function addStatement(
}
}
export function getApplyId(path: t.NodePath<any>, binding: Binding) {
export function bindingToApplyId(path: t.NodePath<any>, binding: Binding) {
const section = path.state.section as Section;
const groupIndex = sorted.findIndex(compareReferenceGroups, section.apply, {
references: [binding],
@ -332,11 +332,7 @@ function writeApplyGroups(path: t.NodePath<any>, groups: ReferenceGroup[]) {
params = references.map((binding) =>
t.assignmentPattern(
t.identifier(binding.name),
callRuntime(
path,
"read",
t.numericLiteral(bindingToScopeId(path, binding))
)
callRuntime(path, "read", bindingToScopeId(path, binding))
)
);
body = t.blockStatement(statements);
@ -348,7 +344,7 @@ function writeApplyGroups(path: t.NodePath<any>, groups: ReferenceGroup[]) {
callRuntime(
path,
"write",
t.numericLiteral(bindingToScopeId(path, references)),
bindingToScopeId(path, references),
param
),
statements.length === 1
@ -381,11 +377,7 @@ function writeHydrateGroups(path: t.NodePath<any>, groups: ReferenceGroup[]) {
? (Array.isArray(references) ? references : [references]).map((binding) =>
t.assignmentPattern(
t.identifier(binding.name),
callRuntime(
path,
"read",
t.numericLiteral(bindingToScopeId(path, binding))
)
callRuntime(path, "read", bindingToScopeId(path, binding))
)
)
: [];
@ -475,7 +467,7 @@ export function bindingToScopeId(
path: t.NodePath<any>,
{ sectionIndex, bindingIndex }: Binding
) {
return (
return t.numericLiteral(
path.hub.file.path.node.extra.sections![sectionIndex].visits + bindingIndex
);
}
@ -536,11 +528,7 @@ function bindFunction(
(Array.isArray(references) ? references : [references]).map((binding) =>
t.variableDeclarator(
t.identifier(binding.name),
callRuntime(
fn,
"read",
t.numericLiteral(bindingToScopeId(fn, binding))
)
callRuntime(fn, "read", bindingToScopeId(fn, binding))
)
)
)