UNPKG

marko

Version:

Optimized runtime for Marko templates.

151 lines (150 loc) • 7.54 kB
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;