refactor: walks are stored using new section data storage

This commit is contained in:
Michael Rawlings 2022-02-02 21:06:28 -08:00
parent cc49795d82
commit 7efe440f2e
6 changed files with 53 additions and 22 deletions

View File

@ -1,6 +1,6 @@
let _item;
const _if = _createRenderer("", "%", _apply);
const _if = _createRenderer("", "", _apply);
_hello({
item: _item

View File

@ -1,4 +1,5 @@
import type { types as t } from "@marko/compiler";
import { currentProgramPath } from "../visitors/program";
import analyzeTagNameType, { TagNameTypes } from "./tag-name-type";
export interface Section {
@ -142,8 +143,12 @@ export function compareReserves(a: Reserve, b: Reserve) {
}
export function getParentSectionId(path: t.NodePath) {
return getSectionId(path.parentPath!);
}
export function getSectionId(path: t.NodePath) {
let sectionId: number;
let currentPath = path.parentPath!;
let currentPath = path;
while (
(sectionId = currentPath.node.extra?.sectionId as number) === undefined
) {
@ -164,3 +169,11 @@ export function getSectionById<S extends Section>(
const sections = program.node.extra.sections!;
return sections[reference.sectionId] as S;
}
export function createSectionGetter<T = unknown>(key: string, init: () => T) {
return (sectionId: number): T => {
const arrayOfSectionData = (currentProgramPath.state[key] ??= []);
const sectionData = (arrayOfSectionData[sectionId] ??= init());
return sectionData as T;
};
}

View File

@ -1,9 +1,20 @@
import { types as t } from "@marko/compiler";
import { ReserveType, getSectionById } from "../util/sections";
import {
ReserveType,
createSectionGetter,
getSectionId,
} from "../util/sections";
import { isOutputHTML } from "./marko-config";
import { callRuntime } from "./runtime";
import { appendLiteral } from "./to-template-string-or-literal";
import { SectionTranslate, writeTo } from "./writer";
import toTemplateOrStringLiteral, {
appendLiteral,
} from "./to-template-string-or-literal";
import { writeTo } from "./writer";
const getWalks = createSectionGetter<(string | t.Expression)[]>("walks", () => [
"",
]);
const getSteps = createSectionGetter<Step[]>("steps", () => []);
export enum WalkCodes {
Get = 32,
@ -54,19 +65,19 @@ type VisitCodes =
| WalkCodes.Replace;
export function enter(path: t.NodePath<any>) {
getSectionById<SectionTranslate>(path).steps.push(Step.enter);
getSteps(getSectionId(path)).push(Step.enter);
}
export function exit(path: t.NodePath<any>) {
getSectionById<SectionTranslate>(path).steps.push(Step.exit);
getSteps(getSectionId(path)).push(Step.exit);
}
export function enterShallow(path: t.NodePath<any>) {
getSectionById<SectionTranslate>(path).steps.push(Step.enter, Step.exit);
getSteps(getSectionId(path)).push(Step.enter, Step.exit);
}
export function injectWalks(path: t.NodePath<any>, expr: t.Expression) {
getSectionById<SectionTranslate>(path).walks.push(expr, "");
getWalks(getSectionId(path)).push(expr, "");
}
export function visit(
@ -80,7 +91,10 @@ export function visit(
);
}
const section = getSectionById<SectionTranslate>(path);
const sectionId = getSectionId(path);
const steps = getSteps(sectionId);
const walks = getWalks(sectionId);
if (isOutputHTML(path)) {
writeTo(path)`${callRuntime(
path,
@ -90,11 +104,11 @@ export function visit(
} else {
let walkString = "";
if (section.steps.length) {
if (steps.length) {
const walks: WalkCodes[] = [];
let depth = 0;
for (const step of section.steps) {
for (const step of steps) {
if (step === Step.enter) {
depth++;
walks.push(WalkCodes.Next);
@ -127,12 +141,12 @@ export function visit(
}
walkString += nCodeString(current, count);
section.steps = [];
steps.length = 0;
}
if (code !== undefined) {
if (code !== WalkCodes.Get) {
appendLiteral(section.writes, "<!>");
writeTo(path)`<!>`;
}
walkString += String.fromCharCode(code);
}
@ -141,7 +155,7 @@ export function visit(
walkString += nCodeString(WalkCodes.Skip, reserve.size);
}
appendLiteral(section.walks, walkString);
appendLiteral(walks, walkString);
}
}
@ -176,3 +190,7 @@ function toCharString(number: number, startCode: number, rangeSize: number) {
result += String.fromCharCode(startCode + number);
return result;
}
export function getWalkString(sectionId: number) {
return toTemplateOrStringLiteral(getWalks(sectionId)) || t.stringLiteral("");
}

View File

@ -13,7 +13,7 @@ import { callRuntime, callRead } from "./runtime";
import toTemplateOrStringLiteral, {
appendLiteral,
} from "./to-template-string-or-literal";
import type { Step } from "./walks";
import { getWalkString } from "./walks";
interface ReferenceGroup {
identifier: t.Identifier;
references: References;
@ -25,8 +25,6 @@ export interface SectionTranslate extends Section {
apply: ReferenceGroup[];
hydrate: ReferenceGroup[];
writes: (string | t.Expression)[];
walks: (string | t.Expression)[];
steps: Step[];
}
export function start(path: t.NodePath<any>, type?: "if" | "for") {
@ -227,7 +225,7 @@ export function getSectionMeta(section: SectionTranslate) {
firstApply && !firstApply.references && firstApply.identifier;
return {
apply: defaultApply || t.nullLiteral(),
walks: toTemplateOrStringLiteral(section.walks) || t.stringLiteral(""),
walks: getWalkString(section.id),
writes: toTemplateOrStringLiteral(section.writes) || t.stringLiteral(""),
};
}

View File

@ -5,9 +5,12 @@ import programDOM from "./dom";
import type { SectionTranslate } from "../../util/writer";
import { startSection, assignFinalIds } from "../../util/sections";
export let currentProgramPath: t.NodePath<t.Program>;
export default {
analyze: {
enter(program: t.NodePath<t.Program>) {
currentProgramPath = program;
startSection(program);
},
@ -17,6 +20,7 @@ export default {
},
translate: {
enter(program: t.NodePath<t.Program>) {
currentProgramPath = program;
program.node.extra.sections = program.node.extra.sections!.map(
(section) =>
({
@ -24,8 +28,6 @@ export default {
apply: [],
hydrate: [],
writes: [""],
walks: [""],
steps: [],
} as SectionTranslate)
);

View File

@ -223,8 +223,8 @@ export default {
.skip();
}
tag.remove();
walks.exit(tag);
tag.remove();
},
},
};