From a6647c73cb756e459a3686e548962feed0aefbcd Mon Sep 17 00:00:00 2001 From: Michael Rawlings Date: Thu, 17 Feb 2022 13:21:37 -0800 Subject: [PATCH] feat: switch to using queuePriority based on referenceGroup order --- .../__snapshots__/dom.expected.js | 2 +- .../__snapshots__/dom.expected.js | 6 ++-- .../__snapshots__/dom.expected.js | 4 +-- .../__snapshots__/dom.expected.js | 10 +++--- .../__snapshots__/dom.expected.js | 2 +- .../if-tag/__snapshots__/dom.expected.js | 8 ++--- .../let-tag/__snapshots__/dom.expected.js | 6 ++-- .../translator/src/core/condition/else-if.ts | 5 +-- .../translator/src/core/condition/else.ts | 5 +-- packages/translator/src/core/condition/if.ts | 33 +++++++------------ packages/translator/src/core/const.ts | 8 +++-- packages/translator/src/core/for.ts | 28 ++++++++-------- packages/translator/src/core/let.ts | 7 ++-- packages/translator/src/util/apply-hydrate.ts | 28 +++++++++------- packages/translator/src/util/runtime.ts | 21 ++++-------- 15 files changed, 79 insertions(+), 94 deletions(-) diff --git a/packages/translator/src/__tests__/fixtures/basic-counter/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-counter/__snapshots__/dom.expected.js index 716654417..8b7ba5910 100644 --- a/packages/translator/src/__tests__/fixtures/basic-counter/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-counter/__snapshots__/dom.expected.js @@ -7,7 +7,7 @@ function _hydrate_clickCount(clickCount = _read(2)) { const _onclick = function () { const clickCount = _read(2); - _queue(_apply_clickCount, 2, clickCount + 1); + _queue(_apply_clickCount, 0, clickCount + 1); }; function _apply_clickCount(clickCount) { diff --git a/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/dom.expected.js index 5efebbe0b..0e3e0480b 100644 --- a/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/dom.expected.js @@ -15,7 +15,7 @@ function _applyWith_selected_num(selected = _readInOwner(4), num = _read(2)) { const _onclick = function () { const num = _read(2); - _queueInOwner(_apply_selected, 4, num); + _queueInOwner(_apply_selected, 0, num); }; function _apply_num(num) { @@ -31,11 +31,11 @@ function _apply_num(num) { } function _apply_selected2(selected = _readInOwner(4)) { - _queue(_applyWith_selected_num, 4); + _queue(_applyWith_selected_num, 2); } function _apply_selected(selected) { - if (_write(4, selected)) _queueForEach(0, _apply_selected2, 4); + if (_write(4, selected)) _queueForEach(0, _apply_selected2, 0); } function _apply() { diff --git a/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/dom.expected.js index 05620e263..363d060a9 100644 --- a/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/dom.expected.js @@ -9,7 +9,7 @@ function _hydrate_clickCount(clickCount = _readInOwner(4)) { const _onclick = function () { const clickCount = _readInOwner(4); - _queueInOwner(_apply_clickCount, 4, clickCount + 1); + _queueInOwner(_apply_clickCount, 0, clickCount + 1); }; function _apply_clickCount2(clickCount = _readInOwner(4)) { @@ -24,7 +24,7 @@ function _apply_clickCount(clickCount) { if (_write(4, clickCount)) { _setConditionalRenderer(0, clickCount < 3 ? _if : null); - _queueInBranch(0, _if, _apply_clickCount2, 4); + _queueInBranch(0, _if, _apply_clickCount2, 0); } } diff --git a/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/dom.expected.js index f791cac99..9d1762cab 100644 --- a/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/dom.expected.js @@ -21,9 +21,9 @@ const _onclick = function () { // TODO: nested writes ([...items, id++]) don't work const nextId = id + 1; - _queue(_apply_id, 6, nextId); + _queue(_apply_id, 0, nextId); - _queue(_apply_items, 7, [...items, nextId]); + _queue(_apply_items, 1, [...items, nextId]); }; function _applyWith_id_items(id = _read(6), items = _read(7)) { @@ -35,7 +35,7 @@ function _applyWith_id_items(id = _read(6), items = _read(7)) { const _onclick2 = function () { const items = _read(7); - _queue(_apply_items, 7, items.slice(0, -1)); + _queue(_apply_items, 1, items.slice(0, -1)); }; function _apply_items(items) { @@ -46,12 +46,12 @@ function _apply_items(items) { _hydrate_items(); - _queue(_applyWith_id_items, 7); + _queue(_applyWith_id_items, 2); } } function _apply_id(id) { - if (_write(6, id)) _queue(_applyWith_id_items, 6); + if (_write(6, id)) _queue(_applyWith_id_items, 2); } function _apply() { diff --git a/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/dom.expected.js index 28d56d4e9..ff9c3dd2e 100644 --- a/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/dom.expected.js @@ -9,7 +9,7 @@ function _hydrate_show(show = _read(5)) { const _onclick = function () { const show = _read(5); - _queue(_apply_show, 5, !show); + _queue(_apply_show, 0, !show); }; function _apply_show(show) { diff --git a/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/dom.expected.js index e80794433..d0d51037d 100644 --- a/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/dom.expected.js @@ -19,19 +19,19 @@ function _applyWith_a_b(a = _read(12), b = _read(13)) { } function _apply_y(y) { - if (_write(15, y)) _queue(_applyWith_x_y, 15); + if (_write(15, y)) _queue(_applyWith_x_y, 5); } function _apply_x(x) { - if (_write(14, x)) _queue(_applyWith_x_y, 14); + if (_write(14, x)) _queue(_applyWith_x_y, 5); } function _apply_b(b) { - if (_write(13, b)) _queue(_applyWith_a_b, 13); + if (_write(13, b)) _queue(_applyWith_a_b, 4); } function _apply_a(a) { - if (_write(12, a)) _queue(_applyWith_a_b, 12); + if (_write(12, a)) _queue(_applyWith_a_b, 4); } export const template = "
"; diff --git a/packages/translator/src/__tests__/fixtures/let-tag/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/let-tag/__snapshots__/dom.expected.js index 17a685bec..5101cabb0 100644 --- a/packages/translator/src/__tests__/fixtures/let-tag/__snapshots__/dom.expected.js +++ b/packages/translator/src/__tests__/fixtures/let-tag/__snapshots__/dom.expected.js @@ -5,7 +5,7 @@ function _hydrateWith_x_y(x = _read(3), y = _read(4)) { } function _applyWith_x_y(x = _read(3), y = _read(4)) { - _write(5, _queue(_apply_x, 3, y = x + y)); + _write(5, _queue(_apply_x, 0, y = x + y)); _hydrateWith_x_y(); } @@ -14,7 +14,7 @@ function _apply_y(y) { if (_write(4, y)) { _data(2, y); - _queue(_applyWith_x_y, 4); + _queue(_applyWith_x_y, 2); } } @@ -22,7 +22,7 @@ function _apply_x(x) { if (_write(3, x)) { _data(1, x); - _queue(_applyWith_x_y, 3); + _queue(_applyWith_x_y, 2); } } diff --git a/packages/translator/src/core/condition/else-if.ts b/packages/translator/src/core/condition/else-if.ts index 9d747bc3e..81fa1fd40 100644 --- a/packages/translator/src/core/condition/else-if.ts +++ b/packages/translator/src/core/condition/else-if.ts @@ -1,7 +1,6 @@ import { types as t } from "@marko/compiler"; import { Tag, assertNoParams, assertNoVar } from "@marko/babel-utils"; -import { exitBranch, queueBranchBuilder } from "./if"; -import { setQueueBuilder } from "../../util/apply-hydrate"; +import { exitBranch } from "./if"; export default { translate: { @@ -35,8 +34,6 @@ export default { ); } } - - setQueueBuilder(tag, queueBranchBuilder); }, exit(tag) { exitBranch(tag); diff --git a/packages/translator/src/core/condition/else.ts b/packages/translator/src/core/condition/else.ts index eb9af2bf9..08534e734 100644 --- a/packages/translator/src/core/condition/else.ts +++ b/packages/translator/src/core/condition/else.ts @@ -1,7 +1,6 @@ import type { types as t } from "@marko/compiler"; import { Tag, assertNoParams, assertNoVar } from "@marko/babel-utils"; -import { setQueueBuilder } from "../../util/apply-hydrate"; -import { exitBranch, queueBranchBuilder } from "./if"; +import { exitBranch } from "./if"; export default { translate: { @@ -30,8 +29,6 @@ export default { ); } } - - setQueueBuilder(tag, queueBranchBuilder); }, exit(tag) { exitBranch(tag); diff --git a/packages/translator/src/core/condition/if.ts b/packages/translator/src/core/condition/if.ts index dc22c3ac3..ef0930373 100644 --- a/packages/translator/src/core/condition/if.ts +++ b/packages/translator/src/core/condition/if.ts @@ -3,11 +3,7 @@ import { Tag, assertNoParams, assertNoVar } from "@marko/babel-utils"; import * as writer from "../../util/writer"; import * as walks from "../../util/walks"; import * as sorted from "../../util/sorted-arr"; -import { - addStatement, - queueBuilder, - setQueueBuilder, -} from "../../util/apply-hydrate"; +import { addStatement, setQueueBuilder } from "../../util/apply-hydrate"; import { callRuntime } from "../../util/runtime"; import { isCoreTagName } from "../../util/is-core-tag"; import toFirstStatementOrBlock from "../../util/to-first-statement-or-block"; @@ -72,7 +68,6 @@ export default { walks.visit(tag, walks.WalkCodes.Replace); walks.enterShallow(tag); - setQueueBuilder(tag, queueBranchBuilder); if (isOutputHTML()) { writer.flushBefore(tag); } @@ -99,21 +94,6 @@ const BRANCHES_LOOKUP = new WeakMap< }[] >(); -export const queueBranchBuilder: queueBuilder = ( - binding, - functionIdentifier, - targetSectionId -) => { - const renderer = writer.getRenderer(targetSectionId); - return callRuntime( - "queueInBranch", - t.numericLiteral(0), - renderer, - functionIdentifier, - t.numericLiteral(binding.id) - ); -}; - export function exitBranch(tag: t.NodePath) { const bodySectionId = getSectionId(tag.get("body")); const nextTag = tag.getNextSibling(); @@ -121,12 +101,23 @@ export function exitBranch(tag: t.NodePath) { isCoreTagName(nextTag, "else") || isCoreTagName(nextTag, "else-if") ); const branches = BRANCHES_LOOKUP.get(tag) || []; + const reserve = tag.node.extra.reserve!; branches.push({ tag, sectionId: bodySectionId, }); + setQueueBuilder(tag, ({ identifier, queuePriority }) => + callRuntime( + "queueInBranch", + t.numericLiteral(reserve.id), + writer.getRenderer(bodySectionId), + identifier, + queuePriority + ) + ); + if (isOutputHTML()) { writer.flushInto(tag); } diff --git a/packages/translator/src/core/const.ts b/packages/translator/src/core/const.ts index 6b21fa323..113919a7c 100644 --- a/packages/translator/src/core/const.ts +++ b/packages/translator/src/core/const.ts @@ -4,7 +4,7 @@ import { assertNoBodyContent } from "../util/assert"; import translateVar from "../util/translate-var"; import { isOutputDOM } from "../util/marko-config"; import { getSectionId } from "../util/sections"; -import { addStatement, bindingToApplyId } from "../util/apply-hydrate"; +import { addStatement, bindingToApplyGroup } from "../util/apply-hydrate"; export default { translate(tag) { @@ -50,7 +50,8 @@ export default { identifiers.length === 1 ? t.expressionStatement( t.callExpression( - bindingToApplyId(identifiers[0].extra.reserve!, sectionId), + bindingToApplyGroup(identifiers[0].extra.reserve!, sectionId) + .identifier, [defaultAttr.value] ) ) @@ -61,7 +62,8 @@ export default { ...identifiers.map((identifier) => t.expressionStatement( t.callExpression( - bindingToApplyId(identifier.extra.reserve!, sectionId), + bindingToApplyGroup(identifier.extra.reserve!, sectionId) + .identifier, [t.identifier(identifier.name)] ) ) diff --git a/packages/translator/src/core/for.ts b/packages/translator/src/core/for.ts index 88284137d..229993ca5 100644 --- a/packages/translator/src/core/for.ts +++ b/packages/translator/src/core/for.ts @@ -5,8 +5,7 @@ import * as writer from "../util/writer"; import * as walks from "../util/walks"; import { addStatement, - bindingToApplyId, - queueBuilder, + bindingToApplyGroup, setQueueBuilder, } from "../util/apply-hydrate"; import { getOrCreateSectionId, getSectionId } from "../util/sections"; @@ -45,7 +44,6 @@ export default { walks.visit(tag, walks.WalkCodes.Replace); walks.enterShallow(tag); - setQueueBuilder(tag, queueEachBuilder); if (isOutputHTML()) { writer.flushBefore(tag); } @@ -131,10 +129,20 @@ const translateDOM = { const { attributes, body: { params }, + extra: { reserve }, } = node; const ofAttr = findName(attributes, "of"); const byAttr = findName(attributes, "by"); + setQueueBuilder(tag, ({ identifier, queuePriority }) => { + return callRuntime( + "queueForEach", + t.numericLiteral(reserve!.id), + identifier, + queuePriority + ); + }); + if (ofAttr) { const ofAttrValue = ofAttr.value!; const [valParam] = params; @@ -163,11 +171,12 @@ const translateDOM = { t.expressionStatement( callRuntime( "setLoopOf", - t.numericLiteral(node.extra.reserve!.id), + t.numericLiteral(reserve!.id), ofAttrValue, rendererId, byAttr ? byAttr.value! : t.nullLiteral(), - bindingToApplyId(valParam.extra.reserve!, bodySectionId) + bindingToApplyGroup(valParam.extra.reserve!, bodySectionId) + .identifier ) ) ); @@ -175,15 +184,6 @@ const translateDOM = { }, }; -const queueEachBuilder: queueBuilder = (binding, functionIdentifier) => { - return callRuntime( - "queueForEach", - t.numericLiteral(0), - functionIdentifier, - t.numericLiteral(binding.id) - ); -}; - const translateHTML = { exit(tag: t.NodePath) { const { node } = tag; diff --git a/packages/translator/src/core/let.ts b/packages/translator/src/core/let.ts index 40376c945..fc707d86d 100644 --- a/packages/translator/src/core/let.ts +++ b/packages/translator/src/core/let.ts @@ -3,7 +3,7 @@ import { Tag, assertNoParams } from "@marko/babel-utils"; import { assertNoBodyContent } from "../util/assert"; import translateVar from "../util/translate-var"; import { isOutputDOM } from "../util/marko-config"; -import { addStatement, bindingToApplyId } from "../util/apply-hydrate"; +import { addStatement, bindingToApplyGroup } from "../util/apply-hydrate"; import { callQueue } from "../util/runtime"; import replaceAssignments from "../util/replace-assignments"; import { getSectionId } from "../util/sections"; @@ -50,7 +50,8 @@ export default { if (isOutputDOM()) { const sectionId = getSectionId(tag); const binding = tagVar.extra.reserve!; - const applyId = bindingToApplyId(binding, sectionId); + const applyGroup = bindingToApplyGroup(binding, sectionId); + const applyId = applyGroup.identifier; // TODO: add defined guard if bindings exist. addStatement( "apply", @@ -62,7 +63,7 @@ export default { replaceAssignments( tag.scope.getBinding(binding.name)!, (assignment, value) => - callQueue(applyId, binding, value, getSectionId(assignment)) + callQueue(applyGroup, binding, value, getSectionId(assignment)) ); } else { translateVar(tag, defaultAttr.value); diff --git a/packages/translator/src/util/apply-hydrate.ts b/packages/translator/src/util/apply-hydrate.ts index 27b45f84b..b9690ac8e 100644 --- a/packages/translator/src/util/apply-hydrate.ts +++ b/packages/translator/src/util/apply-hydrate.ts @@ -10,17 +10,14 @@ import * as sorted from "../util/sorted-arr"; import { currentProgramPath } from "../visitors/program"; import { callRuntime, callRead } from "./runtime"; -interface ReferenceGroup { +export interface ReferenceGroup { identifier: t.Identifier; references: References; statements: t.Statement[]; + queuePriority: t.NumericLiteral; } -export type queueBuilder = ( - binding: Reserve, - functionIdentifier: t.Identifier, - targetSectionId: number -) => t.Expression; +export type queueBuilder = (group: ReferenceGroup) => t.Expression; const [getApply] = createSectionState("apply", () => []); const [getHydrate] = createSectionState("hydrate", () => []); @@ -56,12 +53,12 @@ export function addStatement( return isNew ? 1 : 0; } -export function bindingToApplyId(binding: Reserve, sectionId: number) { +export function bindingToApplyGroup(binding: Reserve, sectionId: number) { const applyGroups = getApply(sectionId); const group = getGroupByReferences(applyGroups, binding) ?? createAndInsertGroup("apply", applyGroups, binding); - return group.identifier; + return group; } function createAndInsertGroup( @@ -74,6 +71,7 @@ function createAndInsertGroup( identifier, references, statements: [], + queuePriority: t.numericLiteral(NaN), }; sorted.insert(compareReferenceGroups, groups, group); return group; @@ -98,8 +96,11 @@ export function writeAllStatementGroups() { export function writeApplyGroups(sectionId: number) { const groups = getApply(sectionId); + if (!groups.length) return; + for (let i = groups.length; i--; ) { - const { identifier, references, statements } = groups[i]; + const group = groups[i]; + const { identifier, references, statements, queuePriority } = group; let params: (t.Identifier | t.RestElement | t.Pattern)[]; let body: t.BlockStatement; @@ -120,7 +121,7 @@ export function writeApplyGroups(sectionId: number) { binding, t.expressionStatement( // TODO: might need to queue in a child scope - callRuntime("queue", identifier, t.numericLiteral(binding.id)) + callRuntime("queue", identifier, queuePriority) ) ); } @@ -139,7 +140,7 @@ export function writeApplyGroups(sectionId: number) { "apply", references.sectionId, references, - t.expressionStatement(factory(references, identifier, sectionId)) + t.expressionStatement(factory(group)) ); } } else { @@ -169,6 +170,11 @@ export function writeApplyGroups(sectionId: number) { result.traverse(bindFunctionsVisitor, { root: result, sectionId }); } } + + const offset = groups[0].references ? 0 : 1; + for (let i = offset; i < groups.length; i++) { + groups[i].queuePriority.value = i - offset; + } } export function writeHydrateGroups(sectionId: number) { diff --git a/packages/translator/src/util/runtime.ts b/packages/translator/src/util/runtime.ts index fec94d8a4..e9b2b4b64 100644 --- a/packages/translator/src/util/runtime.ts +++ b/packages/translator/src/util/runtime.ts @@ -3,6 +3,7 @@ import { importNamed } from "@marko/babel-utils"; import { getMarkoOpts } from "./marko-config"; import type { Reserve } from "./reserve"; import { currentProgramPath } from "../visitors/program"; +import type { ReferenceGroup } from "./apply-hydrate"; export function importRuntime(name: string) { const { output } = getMarkoOpts(); @@ -55,7 +56,7 @@ export function callRead(reference: Reserve, targetSectionId: number) { } export function callQueue( - fnIdentifier: t.Identifier, + { identifier, queuePriority }: ReferenceGroup, reference: Reserve, value: t.Expression, targetSectionId: number @@ -63,24 +64,14 @@ export function callQueue( const diff = getScopeDepthDifference(reference, targetSectionId); switch (diff) { case 0: - return callRuntime( - "queue", - fnIdentifier, - t.numericLiteral(reference.id), - value - ); + return callRuntime("queue", identifier, queuePriority, value); case 1: - return callRuntime( - "queueInOwner", - fnIdentifier, - t.numericLiteral(reference.id), - value - ); + return callRuntime("queueInOwner", identifier, queuePriority, value); default: return callRuntime( "queueInOwner", - fnIdentifier, - t.numericLiteral(reference.id), + identifier, + queuePriority, value, t.numericLiteral(diff) );