marko
Version:
Optimized runtime for Marko templates.
151 lines (150 loc) • 7.54 kB
TypeScript
import { types as t } from "@marko/compiler";
import { type Binding, type Intersection, type IntersectionMeta, type ParamBinding, type ReferencedBindings } from "./bindings";
import * as ContentType from "./constants/content-type";
import type * as Step from "./constants/step";
import * as StructureKind from "./constants/structure-kind";
import { type OneMany, type Opt, Sorted, type SortedOpt } from "./optional";
import { type KnownExprs, type Reason } from "./reasons";
import { type Slot } from "./slots";
import { type Sources } from "./sources";
export type ParamReasonGroup = NonNullable<Sources["param"]>;
export type ParamReasonGroups = [ParamReasonGroup, ...ParamReasonGroup[]];
type ContentType = ContentType.Value;
export { ContentType, StructureKind };
export type StructureRef = StructureSectionRef | StructureExportRef;
export interface StructureSectionRef {
kind: typeof StructureKind.SectionRef;
section: Section;
}
export interface StructureExportRef {
kind: typeof StructureKind.ExportRef;
program: t.ProgramExtra;
path: string;
hint: string;
}
export type StructureOp = string | Step.Value | StructureText | StructureNode | StructureChild | StructureModuleRead;
export interface StructureText {
kind: typeof StructureKind.Text;
value: string;
}
export interface StructureNode {
kind: typeof StructureKind.Node;
binding: Binding | undefined;
marker: boolean;
}
export interface StructureChild {
kind: typeof StructureKind.Child;
name: string;
binding: Binding;
renderer?: StructureRef;
}
export interface StructureModuleRead {
kind: typeof StructureKind.ModuleRead;
read: string[];
}
export interface Section {
id: number;
name: string;
loc: t.SourceLocation | undefined;
depth: number;
parent: Section | undefined;
children: Section[];
program: Section;
params: undefined | ParamBinding;
/** The attribute tag `<for>` params this content reads, held as its own
* bindings that the loop binds as it creates it. */
localClosures: ReferencedBindings;
referencedClosures: ReferencedBindings;
bindings: ReferencedBindings;
hoisted: ReferencedBindings;
/** The closures its `<for>` rows read only by comparing them to the row's
* key, which a row selector updates. */
selector: {
key: Binding;
closures: Set<Binding>;
} | undefined;
/** The canonical intersections its work waits on, once ids allocate. */
intersections: Map<Intersection, IntersectionMeta> | undefined;
/** The slots of its scope, its own and its bindings'. */
slots: SortedOpt<Slot>;
/** When client code reads anything in its scope: its slots' reasons merged. */
reason: undefined | Reason;
paramReasonGroups: ParamReasonGroups | undefined;
returnValueExpr: t.NodeExtra | undefined;
isHoistThrough: true | undefined;
branchExpr: t.NodeExtra | undefined;
/** For a `<define>` body or a template rendering itself, the sections whose
* direct calls render it. */
callSections: SortedOpt<Section>;
/** The content's rendering tag (its extra), and each child binding that
* derives from the content, at `properties`. */
derives: {
tag: t.MarkoTagExtra;
binding: OneMany<Binding>;
properties: Opt<string>;
exprs: KnownExprs | undefined;
} | undefined;
/** Content a known child never reads, which no output renders. */
dropped: boolean;
hasAbortSignal: boolean;
/** Count of distinct `$signal` expression roots; analyze allocates each
* root's abort id from this so translates read, never re-derive. */
abortSignalExprs: number;
readsOwner: boolean;
/** Whether analysis found work keyed by setup in the section, or in a
* `<define>` body or template it calls in place. */
hasSetupWork: boolean;
/** Its tag, which renders it in place into branch scopes at the tag's node
* binding, and whether its branch expression's value can leave it unrendered. */
branch: {
nodeBinding: Binding;
optional: boolean;
/** An `<if>` branch's place in its chain, the renderer index it renders as. */
index?: number;
} | undefined;
content: null | {
startType: ContentType;
endType: ContentType;
singleChild: boolean;
};
structure: StructureOp[] | null;
}
declare module "@marko/compiler/dist/types" {
interface ProgramExtra {
section?: Section;
sections?: Section[];
}
interface MarkoTagBodyExtra {
section?: Section;
}
}
export declare const sectionUtil: Sorted<Section>;
export declare function ensureBodySection(path: t.NodePath<t.MarkoTagBody | t.Program>): Section | undefined;
export declare function ensureSection(path: t.NodePath<any>): Section;
export declare function getSectionForBody(body: t.NodePath<t.MarkoTagBody | t.Program>): Section | undefined;
export declare function removeDroppedContent(tag: t.NodePath<t.MarkoTag>): void;
export declare function getSection(path: t.NodePath): Section;
export declare const getScopeIdIdentifier: (section: Section) => t.Identifier;
export declare const getBranchRendererArgs: (section: Section) => [template?: t.Expression | undefined, walks?: t.Expression | undefined, setup?: t.Expression | undefined, params?: t.Expression | undefined], setBranchRendererArgs: (section: Section, value: [template?: t.Expression | undefined, walks?: t.Expression | undefined, setup?: t.Expression | undefined, params?: t.Expression | undefined]) => void;
export declare function forEachSection(fn: (section: Section) => void): void;
export declare function getDynamicTagContentClosures(section: Section): ReferencedBindings;
export declare function forEachAncestorSection<A>(from: Section, to: Section, fn: (section: Section, arg: A) => void, arg: A): void;
export declare function forEachSectionReverse(fn: (section: Section) => void): void;
export declare function getNodeContentType(path: t.NodePath<t.Statement>, edge: "startType" | "endType"): ContentType.Value | null;
export declare function getRendererReason(section: Section): false | Sources;
export declare function isOptionalBranch(section: Section): section is Section & {
branch: NonNullable<Section["branch"]>;
};
export declare function isInParentSection(binding: Binding, section: Section): boolean;
export declare function isDirectClosure(section: Section, closure: Binding): boolean;
export declare function isDynamicClosure(section: Section, closure: Binding): boolean;
export declare function getDynamicClosureIndex(closure: Binding, closureSection: Section): number;
export declare function getDirectClosures(section: Section): SortedOpt<Binding>;
export declare function isSameOrAncestorSection(section: Section, other: Section): boolean;
export declare function getCommonSection(section: Section, other: Section): Section;
export declare function ensureSectionReasonGroups(section: Section): void;
export declare function ensureReasonGroups(reason: Section["reason"]): void;
export declare function getParamReasonGroupIndex(section: Section, group: ParamReasonGroup): number;
export declare function forEachParamGroup(params: Sources["param"], fn: (section: Section, group: ParamReasonGroup) => void): void;
export declare function reduceParamGroups<R>(params: Sources["param"], fn: (acc: R, section: Section, group: ParamReasonGroup) => R, initial: R): R;
export declare function setReadsOwner(from: Section, to: Section): void;