marko
Version:
Optimized runtime for Marko templates.
10,835 lines • 501 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __exportAll = (all, no_symbols) => {
let target = {};
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
return target;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let package_json = require("../../package.json");
package_json = __toESM(package_json, 1);
let _marko_compiler = require("@marko/compiler");
let _marko_compiler_babel_utils = require("@marko/compiler/babel-utils");
let path = require("path");
path = __toESM(path, 1);
let magic_string = require("magic-string");
magic_string = __toESM(magic_string, 1);
let fastest_levenshtein = require("fastest-levenshtein");
let _marko_compiler_internal_babel = require("@marko/compiler/internal/babel");
let _marko_compiler_modules = require("@marko/compiler/modules");
_marko_compiler_modules = __toESM(_marko_compiler_modules, 1);
//#region src/translator/util/runtime-info.ts
var runtime_info_default = {
name: package_json.default.name,
taglibId: "marko-core"
};
//#endregion
//#region src/translator/util/assert.ts
const docsAnchors = {
if: "if--else",
"else-if": "if--else",
else: "if--else",
effect: "",
attrs: ""
};
function coreTagDocsURL(tagName) {
const anchor = docsAnchors[tagName] ?? tagName;
return `https://markojs.com/docs/reference/core-tag${anchor && "#" + anchor}`;
}
function assertNoSpreadAttrs(tag) {
for (const attr of tag.get("attributes")) if (attr.isMarkoSpreadAttribute()) {
const tagName = tag.get("name").node.value;
throw attr.buildCodeFrameError(`The [\`<${tagName}>\`](${coreTagDocsURL(tagName)}) tag does not support \`...spread\` attributes.`);
}
}
function assertNoTagVarMutation(tag) {
const tagVar = tag.node.var;
if (tagVar?.type === "Identifier") {
const constantViolations = tag.scope.getBinding(tagVar.name)?.constantViolations;
if (constantViolations?.length) {
for (const assignment of constantViolations) if (assignment.type !== "MarkoTag") throw assignment.buildCodeFrameError(`${tagVar.name} is readonly and cannot be mutated.`);
}
}
}
function assertNoBodyContent(tag) {
if (tag.node.body.body.length) {
const tagName = tag.get("name");
const tagNameLiteral = tagName.node.value;
throw tagName.buildCodeFrameError(`The [\`<${tagNameLiteral}>\`](${coreTagDocsURL(tagNameLiteral)}) tag does not support body content.`);
}
}
//#endregion
//#region src/translator/core/attrs.ts
var attrs_default = {
migrate: [(tag) => {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
(0, _marko_compiler_babel_utils.assertNoAttributes)(tag);
assertNoBodyContent(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
(0, _marko_compiler_babel_utils.diagnosticDeprecate)(tag, {
label: "The `attrs` tag is deprecated, prefer destructuring `input` via the `const` tag.",
fix() {
const tagVar = tag.node.var;
if (tagVar && !(tagVar.type === "Identifier" && tagVar.name === "input")) {
const constTag = _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", _marko_compiler.types.identifier("input"))], _marko_compiler.types.markoTagBody([]));
constTag.var = tagVar;
tag.replaceWith(constTag);
} else tag.remove();
}
});
}],
attributes: {},
autocomplete: [{
displayText: "attrs/{ ... }",
description: "Use to receive the attributes passed into this template.",
snippet: "attrs/{ $1 }$2"
}]
};
//#endregion
//#region src/common/constants/accessor-prefix.debug.ts
var accessor_prefix_debug_exports = /* @__PURE__ */ __exportAll({
BranchScopes: () => BranchScopes$3,
ClosureScopes: () => ClosureScopes$1,
ClosureSignalIndex: () => ClosureSignalIndex$1,
ConditionalRenderer: () => ConditionalRenderer$1,
ControlledHandler: () => ControlledHandler$1,
ControlledObserver: () => ControlledObserver$1,
ControlledType: () => ControlledType$1,
ControlledValue: () => ControlledValue$1,
DynamicHTMLLastChild: () => DynamicHTMLLastChild$1,
EventAttributes: () => EventAttributes$1,
IdFallback: () => IdFallback$1,
KeyedScopes: () => KeyedScopes$1,
Lifecycle: () => Lifecycle$1,
Promise: () => Promise$2,
TagVariableChange: () => TagVariableChange$3
});
const BranchScopes$3 = "BranchScopes:";
const ClosureScopes$1 = "ClosureScopes:";
const ClosureSignalIndex$1 = "ClosureSignalIndex:";
const ConditionalRenderer$1 = "ConditionalRenderer:";
const ControlledObserver$1 = "ControlledObserver:";
const ControlledHandler$1 = "ControlledHandler:";
const ControlledType$1 = "ControlledType:";
const ControlledValue$1 = "ControlledValue:";
const DynamicHTMLLastChild$1 = "DynamicHTMLLastChild:";
const EventAttributes$1 = "EventAttributes:";
const IdFallback$1 = "IdFallback:";
const KeyedScopes$1 = "KeyedScopes:";
const Lifecycle$1 = "Lifecycle:";
const Promise$2 = "Promise:";
const TagVariableChange$3 = "TagVariableChange:";
//#endregion
//#region src/common/constants/accessor-prop.debug.ts
var accessor_prop_debug_exports = /* @__PURE__ */ __exportAll({
AbortControllers: () => AbortControllers$1,
AbortScopes: () => AbortScopes$1,
AwaitCounter: () => AwaitCounter$1,
BranchAccessor: () => BranchAccessor$1,
BranchScopes: () => BranchScopes$2,
CatchContent: () => CatchContent$1,
ClosestBranch: () => ClosestBranch$1,
ClosestBranchId: () => ClosestBranchId$1,
DetachedAwait: () => DetachedAwait$1,
EndNode: () => EndNode$1,
Gen: () => Gen$1,
Global: () => Global$1,
Id: () => "#Id",
Load: () => Load$1,
LoopIndex: () => LoopIndex$1,
LoopKey: () => LoopKey$1,
Owner: () => "_",
ParentBranch: () => ParentBranch$1,
PendingEffects: () => PendingEffects$1,
PendingRenders: () => PendingRenders$1,
PendingScopes: () => PendingScopes$1,
PlaceholderBranch: () => PlaceholderBranch$1,
PlaceholderContent: () => PlaceholderContent$1,
Renderer: () => Renderer$1,
StartNode: () => StartNode$1,
Subscriptions: () => Subscriptions$1,
TagVariable: () => TagVariable$1,
TagVariableChange: () => TagVariableChange$2
});
const Global$1 = "$global";
const AbortControllers$1 = "#AbortControllers";
const AbortScopes$1 = "#AbortScopes";
const AwaitCounter$1 = "#AwaitCounter";
const BranchAccessor$1 = "#BranchAccessor";
const BranchScopes$2 = "#BranchScopes";
const CatchContent$1 = "#CatchContent";
const ClosestBranch$1 = "#ClosestBranch";
const ClosestBranchId$1 = "#ClosestBranchId";
const Gen$1 = "#Gen";
const DetachedAwait$1 = "#DetachedAwait";
const EndNode$1 = "#EndNode";
const Load$1 = "#Load";
const LoopKey$1 = "#LoopKey";
const LoopIndex$1 = "#LoopIndex";
const ParentBranch$1 = "#ParentBranch";
const PendingEffects$1 = "#PendingEffects";
const PendingRenders$1 = "#PendingRenders";
const PendingScopes$1 = "#PendingScopes";
const PlaceholderBranch$1 = "#PlaceholderBranch";
const PlaceholderContent$1 = "#PlaceholderContent";
const Renderer$1 = "#Renderer";
const StartNode$1 = "#StartNode";
const Subscriptions$1 = "#Subscriptions";
const TagVariable$1 = "#TagVariable";
const TagVariableChange$2 = "#TagVariableChange";
//#endregion
//#region src/translator/util/evaluate.ts
function evaluate(value) {
let { extra } = value;
if (!extra) extra = value.extra = {};
if (extra.confident === void 0) {
const computed = (0, _marko_compiler_babel_utils.computeNode)(value);
if (computed) {
extra.computed = computed.value;
extra.confident = true;
extra.nullable = computed.value == null;
} else {
extra.computed = void 0;
extra.confident = false;
extra.nullable = isNullableExpr(value);
}
}
return extra;
}
function isNullableExpr(expr) {
switch (expr.type) {
case "ArrayExpression":
case "ArrowFunctionExpression":
case "BigIntLiteral":
case "BinaryExpression":
case "BooleanLiteral":
case "ClassExpression":
case "FunctionExpression":
case "NewExpression":
case "NumericLiteral":
case "ObjectExpression":
case "RegExpLiteral":
case "StringLiteral":
case "TemplateLiteral":
case "UpdateExpression": return false;
case "AssignmentExpression": switch (expr.operator) {
case "=": return isNullableExpr(expr.right);
case "*=":
case "/=":
case "%=":
case "+=":
case "-=":
case "<<=":
case ">>=":
case ">>>=":
case "&=":
case "^=":
case "|=":
case "**=": return false;
case "||=":
case "??=": return isNullableExpr(expr.right);
case "&&=": return isNullableExpr(expr.left) || isNullableExpr(expr.right);
default: return true;
}
case "AwaitExpression": return isNullableExpr(expr.argument);
case "ConditionalExpression": return isNullableExpr(expr.consequent) || isNullableExpr(expr.alternate);
case "LogicalExpression": switch (expr.operator) {
case "||":
case "??": return isNullableExpr(expr.right);
case "&&": return isNullableExpr(expr.left) || isNullableExpr(expr.right);
default: return true;
}
case "ParenthesizedExpression": return isNullableExpr(expr.expression);
case "SequenceExpression": return isNullableExpr(expr.expressions[expr.expressions.length - 1]);
case "UnaryExpression": return expr.operator === "void";
default: return true;
}
}
//#endregion
//#region src/common/helpers.ts
const htmlAttrNameReg = /^[^a-z_]|[^a-z0-9._:-]/i;
const userAttrNameReg = /^[^a-z_$]|[^a-z0-9._:-]/i;
const knownWrongAttrs = {
className: "class",
classList: "class",
htmlFor: "for",
acceptCharset: "accept-charset",
httpEquiv: "http-equiv",
defaultValue: "value",
defaultChecked: "checked",
dangerouslySetInnerHTML: "$!{html}",
key: "<for by>",
ref: "<tag/ref>",
"v-if": "<if>",
"v-else": "<else>",
"v-else-if": "<else if>",
"v-for": "<for>",
"v-show": "<if>",
"v-model": "value:=state",
"v-bind": "...attrs",
"v-html": "$!{html}",
"v-text": "${text}"
};
function getWrongAttrSuggestion(name) {
if (Object.hasOwn(knownWrongAttrs, name)) return knownWrongAttrs[name];
const colon = name.indexOf(":");
if (colon > 0) {
const rest = name.slice(colon + 1);
switch (name.slice(0, colon)) {
case "class": return `class={ ${rest}: condition }`;
case "style": return `style={ ${rest}: value }`;
case "on":
case "v-on": return `on${rest.charAt(0).toUpperCase()}${rest.slice(1)}`;
case "bind":
case "v-model": return `${rest}:=state`;
case "v-bind": return rest;
}
}
}
function stringifyClassObject(name, value) {
return value ? name : "";
}
function stringifyStyleObject(name, value) {
return value || value === 0 ? escapeStyleAttr(name) + ":" + escapeStyleAttr(value + "") : "";
}
const unsafeStyleAttrReg = /[\\;]/g;
const replaceUnsafeStyleAttr = (c) => c === ";" ? "\\3B " : "\\\\";
function escapeStyleAttr(str) {
return unsafeStyleAttrReg.test(str) ? str.replace(unsafeStyleAttrReg, replaceUnsafeStyleAttr) : str;
}
const toDelimitedString = function toDelimitedString(val, delimiter, stringify) {
let str = "";
let sep = "";
let part;
if (val) if (typeof val !== "object") str += val;
else if (Array.isArray(val)) for (const v of val) {
part = toDelimitedString(v, delimiter, stringify);
if (part) {
str += sep + part;
sep = delimiter;
}
}
else for (const name in val) {
part = stringify(name, val[name]);
if (part) {
str += sep + part;
sep = delimiter;
}
}
return str;
};
function isEventHandler(name) {
return /^on[A-Z-]/.test(name);
}
function getEventHandlerName(name) {
return name[2] === "-" ? name.slice(3) : name.slice(2).toLowerCase();
}
function isVoid(value) {
return value == null || value === false;
}
const decodeAccessor = (num) => (num + (num < 26 ? 10 : num < 962 ? 334 : 11998)).toString(36);
//#endregion
//#region src/html/serializer.ts
const kTouchedIterator = /* @__PURE__ */ Symbol.for("marko.touchedIterator");
const { hasOwnProperty } = {};
Array.prototype;
const Generator = (/* @__PURE__ */ (function* () {})()).constructor;
const AsyncGenerator = (/* @__PURE__ */ (async function* () {})()).constructor;
patchIteratorNext(Generator.prototype);
patchIteratorNext(AsyncGenerator.prototype);
function toAccess(accessor) {
const start = accessor[0];
return start === "[" ? accessor : start === "\"" || start >= "0" && start <= "9" ? "[" + accessor + "]" : "." + accessor;
}
function patchIteratorNext(proto) {
if (proto.next[kTouchedIterator]) return;
const { next } = proto;
proto.next = function(value) {
this[kTouchedIterator] = 1;
return next.call(this, value);
};
proto.next[kTouchedIterator] = true;
}
//#endregion
//#region src/translator/util/constants/compile-stage.ts
const analyze$1 = "analyze";
const translate$1 = "translate";
//#endregion
//#region src/translator/util/get-compile-stage.ts
function isTranslate() {
return getCompileStage() === translate$1;
}
function isAnalyzing(file) {
return getCompileStage(file) === analyze$1;
}
function getCompileStage(file = (0, _marko_compiler_babel_utils.getFile)()) {
return file.___compileStage;
}
//#endregion
//#region src/translator/util/traverse.ts
const skip = Symbol("skip");
function traverseReplace(container, key, enter, state) {
const node = container[key];
if (node) if (Array.isArray(node)) for (let i = node.length; i--;) traverseReplace(node, i, enter, state);
else {
const keys = _marko_compiler.types.VISITOR_KEYS[node.type];
for (let i = keys.length; i--;) traverseReplace(node, keys[i], enter, state);
const replacement = enter(node, state);
if (replacement) container[key] = replacement;
}
}
function traverseContains(node, check) {
return !!traverseFind(node, check);
}
function traverseFind(node, check) {
if (node) if (Array.isArray(node)) for (const item of node) {
const found = traverseFind(item, check);
if (found) return found;
}
else {
switch (check(node)) {
case true: return node;
case skip: return;
}
for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) {
const found = traverseFind(node[key], check);
if (found) return found;
}
}
}
function traverseFindAwait(node) {
return traverseFind(node, (child) => {
switch (child.type) {
case "ForOfStatement": return child.await;
case "FunctionDeclaration":
case "FunctionExpression":
case "ArrowFunctionExpression":
case "ClassMethod":
case "ObjectMethod":
case "ClassPrivateMethod": return skip;
case "AwaitExpression": return true;
}
});
}
function traverse(visit, node, parent, grandParent) {
if (node) {
if (Array.isArray(node)) for (const item of node) traverse(visit, item, parent, grandParent);
else if (visit(node, parent, grandParent) !== skip) for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) traverse(visit, node[key], node, parent);
}
}
//#endregion
//#region src/translator/util/generate-uid.ts
const countsForFile = /* @__PURE__ */ new WeakMap();
function generateUid(name = "") {
const file = (0, _marko_compiler_babel_utils.getFile)();
let counts = countsForFile.get(file);
if (!counts) {
const { cache } = file.markoOpts;
const { filename } = file.opts;
const cacheKey = `uid-counts:${filename}`;
counts = cache.get(cacheKey);
if (counts) {
if (isTranslate()) counts = new Map(counts);
} else {
counts = getInitialCounts(file);
if (!isTranslate()) cache.set(cacheKey, counts);
}
countsForFile.set(file, counts);
}
name = name.replace(/^[^a-z$_]|[^a-z$_0-9]/gi, "") || "temp";
name = /^\$?(.*?)\d*$/.exec(name)?.[1] || name;
const i = (counts.get(name) || 0) + 1;
const uniqueName = `$${i > 1 ? name + i : name}`;
counts.set(name, i);
return uniqueName;
}
function generateUidIdentifier(name) {
return _marko_compiler.types.identifier(generateUid(name));
}
const sharedUIDsForFile = /* @__PURE__ */ new WeakMap();
function getSharedUid(name, section) {
const file = (0, _marko_compiler_babel_utils.getFile)();
let sharedUIDs = sharedUIDsForFile.get(file);
if (!sharedUIDs) {
const { cache } = file.markoOpts;
const { filename } = file.opts;
let cacheKey = `uid-shared:${filename}`;
if (section) cacheKey += `:${section.id}`;
sharedUIDs = cache.get(cacheKey);
if (sharedUIDs) {
if (isTranslate()) sharedUIDs = new Map(sharedUIDs);
} else {
sharedUIDs = /* @__PURE__ */ new Map();
if (!isTranslate()) cache.set(cacheKey, sharedUIDs);
}
sharedUIDsForFile.set(file, sharedUIDs);
}
const nameKey = section ? `${section.id}:${name}` : name;
let uniqueName = sharedUIDs.get(nameKey);
if (!uniqueName) {
uniqueName = generateUid(name);
sharedUIDs.set(nameKey, uniqueName);
}
return uniqueName;
}
function usedSharedUid(name) {
return !!sharedUIDsForFile.get((0, _marko_compiler_babel_utils.getFile)())?.has(name);
}
function getInitialCounts(file) {
const counts = /* @__PURE__ */ new Map();
const program = file.path;
const countName = (name) => {
const match = /^\$(.*?)([1-9]\d*)?$/.exec(name);
if (match) {
const name = match[1];
const count = match[2] ? +match[2] + 1 : 1;
counts.set(name, Math.max(counts.get(name) || 0, count));
}
};
for (const name in program.scope.globals) countName(name);
traverse((node, parent, grandParent) => {
if (node.type === "Identifier" && _marko_compiler.types.isBinding(node, parent, grandParent)) countName(node.name);
}, program.node);
return counts;
}
//#endregion
//#region src/translator/util/get-root.ts
function getMarkoRoot(path) {
let curPath = path;
do
curPath = curPath.parentPath;
while (curPath && !isMarko(curPath));
return curPath;
}
function getExprRoot(path) {
let curPath = path;
while (!isMarko(curPath.parentPath)) curPath = curPath.parentPath;
return curPath;
}
function getFnRoot(path) {
let curPath = path;
let fnPath;
while (!isMarko(curPath)) {
if (isFunction(curPath)) fnPath = curPath;
else switch (curPath.type) {
case "OptionalCallExpression":
case "CallExpression":
case "NewExpression":
fnPath = void 0;
break;
}
const parentPath = curPath.parentPath;
if (parentPath) curPath = parentPath;
else break;
}
return fnPath;
}
function getFnParent(path) {
let curPath = path;
while (!isMarko(curPath)) {
if (isFunction(curPath)) return curPath;
const parentPath = curPath.parentPath;
if (parentPath) curPath = parentPath;
else break;
}
}
function getDeclarationRoot(path) {
let curPath = path;
let declPath;
while (!isMarko(curPath)) {
if (isFunctionOrVariableDeclaration(curPath)) declPath = curPath;
const parentPath = curPath.parentPath;
if (parentPath) curPath = parentPath;
else break;
}
return declPath;
}
function isMarko(path) {
switch (path.type) {
case "MarkoTag":
case "MarkoTagBody":
case "MarkoAttribute":
case "MarkoSpreadAttribute":
case "MarkoPlaceholder":
case "MarkoScriptlet":
case "ExportNamedDeclaration":
case "ExportDefaultDeclaration": return true;
default: return false;
}
}
function isFunction(path) {
switch (path.type) {
case "FunctionDeclaration": return !path.node.declare;
case "FunctionExpression":
case "ArrowFunctionExpression":
case "ObjectMethod": return true;
default: return false;
}
}
function isFunctionOrVariableDeclaration(path) {
switch (path.type) {
case "FunctionDeclaration": return !path.node.declare;
case "VariableDeclaration": return true;
default: return false;
}
}
//#endregion
//#region src/translator/util/get-tag-name.ts
function getTagName(tag) {
switch (tag.node.name.type) {
case "StringLiteral": return tag.node.name.value;
case "TemplateLiteral":
if (tag.node.name.quasis.length === 1) return tag.node.name.quasis[0].value.cooked;
break;
}
}
function getStaticTagName(node) {
return _marko_compiler.types.isIdentifier(node.name) ? node.name.name : _marko_compiler.types.isStringLiteral(node.name) ? node.name.value : "tag";
}
//#endregion
//#region src/translator/util/is-core-tag.ts
const { taglibId } = runtime_info_default;
const htmlTaglibId = "marko-html";
function isCoreTag(tag) {
if (tag.isMarkoTag()) {
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
if (tagDef) switch (tagDef.taglibId) {
case taglibId: return true;
case htmlTaglibId:
switch (tagDef.name) {
case "script":
case "style": return true;
}
break;
}
}
return false;
}
function isCoreTagName(tag, name) {
return isCoreTag(tag) && getTagName(tag) === name;
}
function isConditionTag(tag) {
if (isCoreTag(tag)) switch (getTagName(tag)) {
case "if":
case "else-if":
case "else": return true;
}
return false;
}
function isControlFlowTag(tag) {
if (isCoreTag(tag)) switch (getTagName(tag)) {
case "if":
case "else-if":
case "else":
case "for":
case "await":
case "try":
case "show": return true;
}
return false;
}
//#endregion
//#region src/translator/util/is-invoked-function.ts
function isInvokedFunction(expr) {
let curPath = expr;
while (curPath) {
const { parent, node } = curPath;
switch (parent.type) {
case "OptionalCallExpression":
case "CallExpression": return parent.callee === node;
case "TSNonNullExpression":
curPath = curPath.parentPath;
break;
default: return false;
}
}
return false;
}
//#endregion
//#region src/translator/util/constants/structure-kind.ts
const Visit = "visit";
const Text = "text";
const Child = "child";
const SectionRef = "sectionRef";
const ExportRef = "exportRef";
//#endregion
//#region src/translator/util/optional.ts
var Sorted = class {
compare;
constructor(compare) {
this.compare = compare;
}
add(data, item) {
return data !== void 0 ? Array.isArray(data) ? addSorted(this.compare, data, item) : joinRepeatable(this.compare, data, item) : item;
}
union(a, b) {
if (a !== void 0) {
if (Array.isArray(a)) {
if (b !== void 0) if (Array.isArray(b)) return unionSortedRepeatable(this.compare, a, b);
else return addSorted(this.compare, a, b);
return a;
}
if (b !== void 0) {
if (Array.isArray(b)) return addSorted(this.compare, b, a);
return joinRepeatable(this.compare, b, a);
}
return a;
}
return b;
}
find(data, item) {
if (data !== void 0) {
if (Array.isArray(data)) return findSorted(this.compare, data, item);
else if (this.compare(data, item) === 0) return data;
}
}
has(data, item) {
return this.findIndex(data, item) !== -1;
}
findIndex(data, item) {
if (data !== void 0) {
if (Array.isArray(data)) return findIndexSorted(this.compare, data, item);
else if (this.compare(data, item) === 0) return 0;
}
return -1;
}
groupBy(data, cb) {
const group = /* @__PURE__ */ new Map();
if (data !== void 0) if (Array.isArray(data)) for (const item of data) {
const key = cb(item);
group.set(key, this.union(group.get(key), item));
}
else group.set(cb(data), data);
return group;
}
isSuperset(superset, subset) {
if (subset === void 0) return true;
if (!Array.isArray(subset)) return this.findIndex(superset, subset) !== -1;
if (!Array.isArray(superset)) return false;
const subLen = subset.length;
if (subLen > superset.length) return false;
for (let i = subLen; i--;) if (findIndexSorted(this.compare, superset, subset[i]) < i) return false;
return true;
}
};
function push(data, item) {
if (data !== void 0) {
if (Array.isArray(data)) {
data.push(item);
return data;
}
return [data, item];
}
return item;
}
function concat(a, b) {
if (a !== void 0) {
if (b !== void 0) if (Array.isArray(a)) return a.concat(b);
else if (Array.isArray(b)) return [a, ...b];
else return [a, b];
return a;
}
return b;
}
function filter(data, cb) {
if (data !== void 0) {
if (Array.isArray(data)) {
const len = data.length;
let result;
let i = 0;
while (i < len) {
let item = data[i++];
if (cb(item)) {
result = item;
while (i < len) {
item = data[i++];
if (cb(item)) {
result = [result, item];
while (i < len) {
item = data[i++];
if (cb(item)) result.push(item);
}
return result;
}
}
return result;
}
}
return result;
}
if (cb(data)) return data;
}
}
function forEach(data, cb) {
if (data !== void 0) if (Array.isArray(data)) {
let i = 0;
for (const item of data) cb(item, i++);
} else cb(data, 0);
}
function fromIter(data) {
let one;
let many;
for (const item of data) if (many) many.push(item);
else if (one) many = [one, item];
else one = item;
return many || one;
}
function* toIter(data) {
if (data !== void 0) if (Array.isArray(data)) yield* data;
else yield data;
}
function includes(data, item) {
return data !== void 0 ? Array.isArray(data) ? data.includes(item) : data === item : false;
}
function find(data, cb) {
if (data !== void 0) {
if (Array.isArray(data)) return data.find(cb);
if (cb(data, 0)) return data;
}
}
function some(data, cb) {
return data !== void 0 ? Array.isArray(data) ? data.some(cb) : !!cb(data, 0) : false;
}
function toArray(data, cb) {
return data !== void 0 ? Array.isArray(data) ? data.map(cb) : [cb(data, 0)] : [];
}
function mapToString(data, sep, cb) {
if (data !== void 0) {
if (Array.isArray(data)) {
let str = "";
let curSep = "";
for (let i = 0; i < data.length; i++) {
str += curSep + cb(data[i], i);
curSep = sep;
}
return str;
}
return cb(data, 0);
}
return "";
}
function findSorted(compare, data, item) {
let max = data.length;
let pos = 0;
while (pos < max) {
const mid = pos + max >>> 1;
const cur = data[mid];
const compareResult = compare(cur, item);
if (compareResult === 0) return cur;
if (compareResult > 0) max = mid;
else pos = mid + 1;
}
}
function findIndexSorted(compare, data, item) {
let max = data.length;
let pos = 0;
while (pos < max) {
const mid = pos + max >>> 1;
const compareResult = compare(data[mid], item);
if (compareResult === 0) return mid;
if (compareResult > 0) max = mid;
else pos = mid + 1;
}
return -1;
}
function addSorted(compare, data, item) {
const len = data.length;
let max = len;
let pos = 0;
while (pos < max) {
const mid = pos + max >>> 1;
const compareResult = compare(data[mid], item);
if (compareResult === 0) return data;
if (compareResult > 0) max = mid;
else pos = mid + 1;
}
const result = new Array(len + 1);
for (let i = 0; i < pos; i++) result[i] = data[i];
let cur = item;
while (pos < len) {
const next = cur;
cur = data[pos];
result[pos++] = next;
}
result[len] = cur;
return result;
}
function unionSortedRepeatable(compare, a, b) {
const aLen = a.length;
const bLen = b.length;
const result = [];
let aIndex = 0;
let bIndex = 0;
let same = true;
while (aIndex < aLen && bIndex < bLen) {
const aValue = a[aIndex];
const bValue = b[bIndex];
const delta = compare(aValue, bValue);
if (delta === 0) {
aIndex++;
bIndex++;
result.push(aValue);
} else if (delta < 0) {
same = false;
aIndex++;
result.push(aValue);
} else {
same = false;
bIndex++;
result.push(bValue);
}
}
if (same && aLen === bLen) return a;
while (aIndex < aLen) result.push(a[aIndex++]);
while (bIndex < bLen) result.push(b[bIndex++]);
return result;
}
function joinRepeatable(compare, a, b) {
const compareResult = compare(a, b);
return compareResult === 0 ? a : compareResult < 0 ? [a, b] : [b, a];
}
//#endregion
//#region src/common/constants/accessor-prefix.ts
var accessor_prefix_exports = /* @__PURE__ */ __exportAll({
BranchScopes: () => "A",
ClosureScopes: () => "B",
ClosureSignalIndex: () => "C",
ConditionalRenderer: () => "D",
ControlledHandler: () => "E",
ControlledObserver: () => "N",
ControlledType: () => "F",
ControlledValue: () => "G",
DynamicHTMLLastChild: () => "H",
EventAttributes: () => "I",
IdFallback: () => "J",
KeyedScopes: () => "O",
Lifecycle: () => "K",
Promise: () => "L",
TagVariableChange: () => "M"
});
//#endregion
//#region src/common/constants/accessor-prop.ts
var accessor_prop_exports = /* @__PURE__ */ __exportAll({
AbortControllers: () => "A",
AbortScopes: () => "B",
AwaitCounter: () => "O",
BranchAccessor: () => "C",
BranchScopes: () => "D",
CatchContent: () => "E",
ClosestBranch: () => "F",
ClosestBranchId: () => "G",
DetachedAwait: () => "V",
EndNode: () => "K",
Gen: () => "H",
Global: () => "$",
Id: () => "L",
Load: () => "X",
LoopIndex: () => "I",
LoopKey: () => "M",
Owner: () => "_",
ParentBranch: () => "N",
PendingEffects: () => "J",
PendingRenders: () => "W",
PendingScopes: () => "Y",
PlaceholderBranch: () => "P",
PlaceholderContent: () => "Q",
Renderer: () => "R",
StartNode: () => "S",
Subscriptions: () => "Z",
TagVariable: () => "T",
TagVariableChange: () => "U"
});
//#endregion
//#region src/translator/util/marko-config.ts
function isOutputHTML() {
return getMarkoOpts().output === "html";
}
function isOutputDOM() {
return getMarkoOpts().output === "dom";
}
function getMarkoOpts() {
return (0, _marko_compiler_babel_utils.getFile)().markoOpts;
}
function isOptimize() {
return getMarkoOpts().optimize;
}
function getReadyId(file = (0, _marko_compiler_babel_utils.getFile)()) {
const { markoOpts } = file;
if (!markoOpts.linkAssets) return void 0;
return (markoOpts.optimize ? "_" : "ready:") + (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, file.opts.filename);
}
//#endregion
//#region src/translator/util/get-accessor-enums.ts
function getAccessorPrefix() {
return isOptimize() ? accessor_prefix_exports : accessor_prefix_debug_exports;
}
function getAccessorProp() {
return isOptimize() ? accessor_prop_exports : accessor_prop_debug_exports;
}
//#endregion
//#region src/translator/util/serialize-reasons.ts
const sourcesUtil = new Sorted(compareSources);
function isSameReason(a, b) {
return a === b || (a && b ? a !== true && b !== true && compareSources(a, b) === 0 : false);
}
function isForceSerialized(section, prop, prefix) {
return true === (prop ? section.serializeReasons.get(getPropKey(section, prop, prefix)) : section.serializeReason);
}
function addSerializeReason(section, reason, prop, prefix) {
if (reason) {
if (reason !== true) addProvenance(section, reason, prop && getPropKey(section, prop, prefix));
if (prop) {
const key = getPropKey(section, prop, prefix);
const curReason = section.serializeReasons.get(key);
if (curReason !== true) if (reason === true) forcePropSerialize(section, key);
else {
const newReason = mergeSerializeReasons(curReason, reason);
if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
}
} else {
const curReason = section.serializeReason;
if (curReason !== true) if (reason === true) forceSerialize(section);
else {
const newReason = mergeSerializeReasons(curReason, reason);
if (curReason !== newReason) setSerializeReason(section, newReason);
}
}
}
}
function addSerializeExpr(section, expr, prop, prefix) {
if (expr) if (prop) {
const key = getPropKey(section, prop, prefix);
if (expr === true) {
if (section.serializeReasons.get(key) !== true) forcePropSerialize(section, key);
} else {
const curExprs = section.propSerializeExprs ??= /* @__PURE__ */ new Map();
const curExpr = curExprs.get(key);
curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
}
} else if (expr === true) {
if (section.serializeReason !== true) forceSerialize(section);
} else {
const curExpr = section.serializeExprs;
section.serializeExprs = curExpr ? concat(curExpr, expr) : expr;
}
}
function addOwnerSerializeReason(from, to, reason) {
if (reason) {
let cur = from;
while (cur !== to && cur.parent) {
addSerializeReason(cur, reason, getAccessorProp().Owner);
cur = cur.parent;
}
}
}
function isReasonDynamic(reason) {
return !!reason && reason !== true && !reason.state;
}
function isStaticSerializeReason(reason) {
return !!reason && !isReasonDynamic(reason);
}
function isStateSerializeReason(reason) {
return !!reason && reason !== true && !!reason.state;
}
function getSerializeReason(section, prop, prefix) {
if (prop) return section.serializeReasons.get(getPropKey(section, prop, prefix));
else return section.serializeReason;
}
function getSerializeSourcesForExpr(expr) {
return isReferencedExtra(expr) ? getSerializeSourcesForRef(expr.referencedBindings) : void 0;
}
function getSerializeSourcesForExprs(exprs) {
if (exprs) if (exprs === true) return exprs;
else if (Array.isArray(exprs)) {
let allSources;
for (const expr of exprs) allSources = mergeSources(allSources, getSerializeSourcesForExpr(expr));
return allSources;
} else return getSerializeSourcesForExpr(exprs);
}
function getSerializeSourcesForRef(ref) {
if (ref) {
let allSources;
if (Array.isArray(ref)) {
for (const { sources } of ref) allSources = mergeSources(allSources, sources);
return allSources;
} else return ref.sources;
}
}
function mapCrossProgramReason(program, reason, exprs) {
let params;
let mapped;
let crossProgram = false;
forEach(reason.param, (param) => {
if (param.section.program === program) params = bindingUtil.add(params, param);
else {
crossProgram = true;
mapped = exprs ? mergeSerializeReasons(mapped, getSerializeSourcesForExprs(mapParamBindingToExpr(exprs, param))) : true;
}
});
if (!crossProgram) return reason;
return mergeRemappedSources(reason, params, mapped);
}
function mapDownstreamReason(program, reason, exprs) {
let params;
let mapped;
let downstream = false;
forEach(reason.param, (param) => {
if (param.section.program === program) {
downstream = true;
mapped = mergeSerializeReasons(mapped, getSerializeSourcesForExprs(mapParamBindingToExpr(exprs, param)));
} else params = bindingUtil.add(params, param);
});
if (!downstream) return reason;
return mergeRemappedSources(reason, params, mapped);
}
function mergeRemappedSources(reason, params, mapped) {
if (mapped !== true && (reason.state || reason.global || params)) mapped = mergeSerializeReasons(mapped, createSources(reason.state, params, reason.global));
return mapped;
}
function mergeSerializeReasons(a, b) {
if (a === true || b === true) return true;
return mergeSources(a, b);
}
function applySerializeExprs(section) {
const propExprs = section.propSerializeExprs;
if (propExprs) {
section.propSerializeExprs = void 0;
for (const [key, exprs] of propExprs) {
addProvenance(section, getProvenanceForExprs(exprs), key);
const exprReason = getSerializeSourcesForExprs(exprs);
if (exprReason) {
const curReason = section.serializeReasons.get(key);
const newReason = mergeSerializeReasons(curReason, exprReason);
if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
}
}
}
const scopeExprs = section.serializeExprs;
if (scopeExprs) {
section.serializeExprs = void 0;
addProvenance(section, getProvenanceForExprs(scopeExprs));
const exprReason = getSerializeSourcesForExprs(scopeExprs);
if (exprReason) {
const curReason = section.serializeReason;
const newReason = mergeSerializeReasons(curReason, exprReason);
if (curReason !== newReason) setSerializeReason(section, newReason);
}
}
}
function finalizeSerializeReason(section) {
some(section.bindings, (binding) => {
const reason = binding.type === 0 && getSerializeReason(section, binding);
if (reason) section.domSerializeReasons = reason === true ? true : sourcesUtil.add(section.domSerializeReasons, reason);
return reason === true;
});
const curReason = section.serializeReason;
let newReason = curReason;
if (newReason !== true) {
for (const propReason of section.serializeReasons.values()) {
if (propReason === true) {
newReason = true;
break;
}
newReason = mergeSources(newReason, propReason);
}
if (newReason && curReason !== newReason) setSerializeReason(section, newReason);
}
const propProvenance = section.propSerializeProvenance;
if (propProvenance) for (const provenance of propProvenance.values()) addProvenance(section, provenance);
}
function addProvenance(section, sources, key) {
if (!sources) return;
if (key) {
const provenance = section.propSerializeProvenance ??= /* @__PURE__ */ new Map();
provenance.set(key, mergeSources(provenance.get(key), sources));
} else section.serializeProvenance = mergeSources(section.serializeProvenance, sources);
}
function getProvenanceForExprs(exprs) {
let sources;
forEach(exprs, (expr) => {
sources = mergeSources(sources, getSerializeSourcesForExpr(expr));
forEach(expr.referencedBindingsInFunction, (binding) => {
sources = mergeSources(sources, getSerializeSourcesForRef(binding));
});
});
return sources;
}
function getPropKey(section, prop, prefix) {
if (isStrOrSym(prop)) {
const keys = section.serializePropKeys ??= /* @__PURE__ */ new Map();
let key = keys.get(prop);
if (!key) keys.set(prop, key = Symbol(typeof prop === "symbol" ? `Symbol(${prop.description})` : prop));
if (prefix) throw new Error("Cannot have a scope property reason with a prefix.");
return key;
} else {
const binding = getCanonicalBinding(prop);
const keys = binding.serializePropKeys ??= /* @__PURE__ */ new Map();
let key = keys.get(prefix);
if (!key) keys.set(prefix, key = Symbol((prefix ? typeof prefix === "symbol" ? `Symbol(${prefix.description})` : prefix : "") + binding.name));
return key;
}
}
function forceSerialize(section) {
setSerializeReason(section, true);
}
function forcePropSerialize(section, key) {
setPropSerializeReason(section, key, true);
}
function isStrOrSym(v) {
switch (typeof v) {
case "string":
case "symbol": return true;
default: return false;
}
}
function setSerializeReason(section, reason) {
section.serializeReason = reason;
}
function setPropSerializeReason(section, key, reason) {
section.serializeReasons.set(key, reason);
}
//#endregion
//#region src/translator/util/state.ts
function createProgramState(init) {
const map = /* @__PURE__ */ new WeakMap();
return [() => {
let state = map.get((0, _marko_compiler_babel_utils.getProgram)());
if (!state) map.set((0, _marko_compiler_babel_utils.getProgram)(), state = init());
return state;
}, (value) => {
map.set((0, _marko_compiler_babel_utils.getProgram)(), value);
}];
}
function createSectionState(key, init) {
return [(section) => {
const arrayOfSectionData = (0, _marko_compiler_babel_utils.getProgram)().state[key] ??= {};
return arrayOfSectionData[section.id] ??= init && init(section);
}, (section, value) => {
const arrayOfSectionData = (0, _marko_compiler_babel_utils.getProgram)().state[key] ??= {};
arrayOfSectionData[section.id] = value;
}];
}
//#endregion
//#region src/translator/util/tag-name-type.ts
const MARKO_FILE_REG = /^<.*>$|\.marko$/;
const TAG_NAME_IDENTIFIER_REG$1 = /^[A-Z][a-zA-Z0-9_$]*$/;
function analyzeTagNameType(tag, allowDynamic) {
const extra = tag.node.extra ??= {};
if (extra.tagNameType === void 0) {
const name = tag.get("name");
if (name.isStringLiteral()) {
extra.tagNameType = name.node.value[0] === "@" ? 3 : (0, _marko_compiler_babel_utils.isNativeTag)(tag) ? 0 : 1;
extra.tagNameNullable = extra.tagNameDynamic = false;
} else if (name.isTemplateLiteral() && name.node.quasis.length === 1) {
extra.tagNameType = 0;
extra.tagNameNullable = extra.tagNameDynamic = false;
} else if (name.isIdentifier()) {
analyzeExpressionTagName(name, extra);
extra.tagNameDynamic = !extra.tagNameImported;
} else {
analyzeExpressionTagName(name, extra);
extra.tagNameDynamic = true;
}
if (!extra.tagNameDynamic && extra.tagNameType === 1 && !isCoreTag(tag)) {
const childFile = (0, _marko_compiler_babel_utils.loadFileForTag)(tag);
if ((0, _marko_compiler_babel_utils.getTagDef)(tag)?.renderer || childFile?.ast.program.extra.featureType === "class") {
extra.tagNameType = 2;
extra.tagNameDynamic = true;
extra.featureType = "class";
if (childFile?.ast.program.extra?.hydratesTags) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
} else if (!childFile) {
extra.tagNameType = 2;
extra.tagNameDynamic = true;
const tagName = name.node.value;
extra.tagNameUnresolved = !(TAG_NAME_IDENTIFIER_REG$1.test(tagName) && tag.scope.hasBinding(tagName));
} else if (childFile !== (0, _marko_compiler_babel_utils.getFile)() && isAnalyzing(childFile)) {
extra.tagNameType = 2;
extra.tagNameDynamic = true;
}
}
}
return !allowDynamic && extra.tagNameDynamic ? 2 : extra.tagNameType;
}
function analyzeExpressionTagName(name, extra) {
const pending = [name];
const seen = /* @__PURE__ */ new Set();
let path;
let type;
let nullable = false;
let tagNameImported;
let tagNameLoad;
while ((path = pending.pop()) && type !== 2) {
if (seen.has(path.node)) continue;
seen.add(path.node);
if (path.isConditionalExpression()) {
pending.push(path.get("consequent"));
if (path.node.alternate) pending.push(path.get("alternate"));
} else if (path.isLogicalExpression()) {
if (path.node.operator === "&&") nullable = true;
else pending.push(path.get("left"));
pending.push(path.get("right"));
} else if (path.isAssignmentExpression()) pending.push(path.get("right"));
else if (path.isBinaryExpression()) type = path.node.operator !== "+" || type === void 0 || type === 0 ? 0 : 2;
else if (path.isStringLiteral() || path.isTemplateLiteral()) type = type === void 0 || type === 0 ? 0 : 2;
else if (path.isNullLiteral()) nullable = true;
else if (path.isIdentifier()) {
if (path.node.name === "undefined") {
nullable = true;
continue;
}
const binding = path.scope.getBinding(path.node.name);
if (!binding) {
type = 2;
continue;
}
if (binding.kind === "module") {
const decl = binding.path.parent;
if (MARKO_FILE_REG.test(decl.source.value) && decl.specifiers.some((it) => _marko_compiler.types.isImportDefaultSpecifier(it))) {
const resolvedImport = decl.extra?.tagImport || decl.source.value;
if (type === void 0) {
type = 1;
tagNameImported = resolvedImport;
tagNameLoad = decl.extra?.loadImport;
} else if (type === 0) {
type = 2;
tagNameImported = void 0;
} else if (tagNameImported !== resolvedImport) tagNameImported = void 0;
} else type = 2;
continue;
}
const bindingTag = binding.path;
if (bindingTag.isMarkoTag() && binding.kind === "local") {
const bindingTagName = bindingTag.get("name").node.value;
if (bindingTagName === "const") {
pending.push(bindingTag.get("attributes")[0].get("value"));
continue;
}
if (bindingTagName === "let") {
type = 2;
continue;
}
continue;
}
type = 2;
} else type = 2;
}
extra.tagNameType = type ?? 2;
extra.tagNameNullable = nullable;
if (type === 1 && tagNameImported) {
extra.tagNameImported = tagNameImported;
extra.tagNameLoad = tagNameLoad;
}
}
//#endregion
//#region src/translator/util/sections.ts
const sectionUtil = new Sorted(function compareSections(a, b) {
return a.id - b.id;
});
function startSection(path) {
const extra = path.node.extra ??= {};
let section = extra.section;
if (!section && (path.type === "Program" || path.get("body").length)) {
const parentTag = path.parentPath?.isMarkoTag() ? path.parentPath : void 0;
const parentSection = path.parentPath ? getOrCreateSection(path.parentPath) : void 0;
const sectionName = parentTag ? generateUid((isCoreTagName(parentTag, "define") && _marko_compiler.types.isIdentifier(parentTag.node.var) ? parentTag.node.var.name : parentTag.get("name").toString()) + "_content") : "";
const programExtra = (0, _marko_compiler_babel_utils.getProgram)().node.extra ??= {};
const sections = programExtra.sections ??= [];
section = extra.section = {
id: sections.length,
name: sectionName,
loc: parentTag?.node.name.loc || void 0,
depth: parentSection ? parentSection.depth + 1 : 0,
parent: parentSection,
program: void 0,
sectionAccessor: void 0,
params: void 0,
referencedLocalClosures: void 0,
referencedClosures: void 0,
referencedHoists: void 0,
bindings: void 0,
hoisted: void 0,
hoistedTo: void 0,
isHoistThrough: void 0,
serializeReason: void 0,
serializeReasons: /* @__PURE__ */ new Map(),
domSerializeReasons: void 0,
serializeExprs: void 0,
propSerializeExprs: void 0,
serializeProvenance: void 0,
propSerializeProvenance: void 0,
serializePropKeys: void 0,
paramReasonGroups: void 0,
returnValueExpr: void 0,
returnSerializeReason: void 0,
content: getContentInfo(path),
upstreamExpression: void 0,
downstream: void 0,
hasAbortSignal: false,
abortSignalExprs: 0,
readsOwner: false,
isBranch: false,
structure: parentSection && !parentSection.structure ? null : []
};
section.program = parentSection ? parentSection.program : section;
sections.push(section);
}
return section;
}
function getOrCreateSection(path) {
let cur = path;
while (true) {
if (cur.type === "Program" || cur.type === "MarkoTagBody" && !cur.node.attributeTags && !isNativeNode(cur.parentPath)) return startSection(cur);
cur = cur.parentPath;
}
}
function getSectionForBody(body) {
return body.node.extra?.section;
}
function getSection(path) {
let section;
let currentPath = path;
while ((section = currentPath.node.extra?.section) === void 0) currentPath = currentPath.parentPath;
return section;
}
const [getScopeIdIdentifier] = createSectionState("scopeIdIdentifier", (section) => generateUidIdentifier(`scope${section.id}_id`));
const [getSectionParentIsOwner, setSectionParentIsOwner] = createSectionState("parentIsOwner", () => false);
const [getBranchRendererArgs, setBranchRendererArgs] = createSectionState("rendererExpression");
function forEachSection(fn) {
const { sections } = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
sections?.forEach(fn);
}
function forEachSectionReverse(fn) {
const { sections } = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
for (let i = sections.length; i--;) fn(sections[i]);
}
function getContentInfo(path) {
const body = path.get("body");
const contentInfo = {
startType: null,
endType: null,
singleChild: true
};
for (let endIndex = body.length; endIndex--;) {
const endType = getNodeContentType(body[endIndex], "endType", contentInfo);
if (endType !== null) {
contentInfo.endType = endType;
if (endType === 1) contentInfo.singleChild = false;
for (let startIndex = 0; startIndex < endIndex; startIndex++) {
const startType = getNodeContentType(body[startIndex], "startType");
if (startType !== null) {
contentInfo.startType = startType;
contentInfo.singleChild = false;
return contentInfo;
}
}
contentInfo.startType = getNodeContentType(body[endIndex], "startType");
return contentInfo;
}
}
return null;
}
function getNodeContentType(path, extraMember, contentInfo) {
switch (path.type) {
case "MarkoText": return 4;
case "MarkoPlaceholder": return 2;
case "MarkoScriptlet":
case "MarkoComment":
case "ImportDeclaration":
case "ExportAllDeclaration":
case "ExportNamedDeclaration":
case "ExportDefaultDeclaration": return null;
case "MarkoTag": {
const tag = path;
if (isCoreTag(tag)) switch (tag.node.name.value) {
case "html-comment": return 0;
case "html-script":
case "html-style": return 3;
case "style": return tag.node.body.body.some((child) => _marko_compiler.types.isMarkoPlaceholder(child)) ? 3 : null;
case "for":
case "if":
case "await":
case "try": return 1;
case "show": return 1;
default: return null;
}
else if ((0, _marko_compiler_babel_utils.isNativeTag)(tag)) return 3;
else if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) return null;
else if (_marko_compiler.types.isStringLiteral(tag.node.name)) {
const tagSection = (0, _marko_compiler_babel_utils.loadFileForTag)(tag)?.ast.program.extra.section;
if (tagSection) if (tagSection.content) {
if (contentInfo && !tagSection.content.singleChild) {
if (extraMember === "endType") {
contentInfo.startType = tagSection.content.startType;
contentInfo.singleChild = false;
}
}
return tagSection.content[extraMember];
} else return null;
}
}
}
return 1;
}
function getSectionRegisterReasons(section) {
if (section.isBranch) return false;
const { downstream } = section;
if (downstream?.binding) {
let downstreamReasons = getAllSerializeReasonsForBinding(downstream.binding, downstream.properties);
if (downstreamReasons && downstreamReasons !== true) downstreamReasons = mapCrossProgramReason(section.program, downstreamReasons, downstream.exprs);
if (!downstreamReasons) return false;
if (isReasonDynamic(downstreamReasons) && !section.serializeReason && !section.serializeReasons.size && !section.parent?.serializeReason && !section.parent?.serializeReasons.size) return false;
return downstreamReasons;
} else if (downstream) return false;
return true;
}
function isImmediateOwner(section, binding) {
return section.parent?.id === binding.section.id;
}
function isDirectClosure(section, closure) {
return section.isBranch && isImmediateOwner(section, closure);
}
function isDynamicClosure(section, closure) {
return !isDirectClosure(section, closure);
}
function getDynamicClosureIndex(closure, closureSection) {
let index = 0;
find(closure.closureSections, (section) => {
if (section === closureSection) return true;
if (isDynamicClosure(section, closure)) index++;
return false;
});
return index;
}
function getDirectClosures(section) {
if (section.isBranch) return filter(section.referencedClosures, (closure) => isImmediateOwner(section, closure));
}
function isSameOrChildSection(section, other) {
do
if (other === section) return true;
while (other = other.parent);
return false;
}
function getCommonSection(section, other) {
let ancestor = section;
if (other.depth < section.depth) {
ancestor = other;
other = section;
}
while (ancestor) {
if (other === ancestor || !other.parent) return ancestor;
other = other.parent;
if (other.depth < ancestor.depth) ancestor = ancestor.parent;
}
throw new Error("No common section");
}
function finalizeParamSerializeReasonGroups(section) {
ensureReasonGroups(section.serializeReason);
for (const reason of section.serializeReasons.values()) ensureReasonGroups(reason);
}
function ensureReasonGroups(reason) {
if (isReasonDynamic(reason)) for (const [paramSection, params] of groupParamsBySection(reason.param)) ensureParamReasonGroup(paramSection, params);
}
function ensureParamReasonGroup(section, reason) {
const { paramReasonGroups } = section;
if (paramReasonGroups) {
const found = findSorted(compareParamGroups, paramReasonGroups, { reason });
if (found) return found;
}
const group = {
id: Symbol(getDebugNames(reason)),
reason
};
section.paramReasonGroups = paramReasonGroups ? addSorted(compareParamGroups, paramReasonGroups, group) : [group];
}
function getParamReasonGroupIndex(section, reason) {
const index = section.paramReasonGroups && findIndexSorted(compareParamGroups, section.paramReasonGroups, { reason });
if (index === void 0 || index === -1) throw new Error("Invalid compiler state, cannot ask for a serialize reason group that was not analyzed.");
return index;
}
function groupParamsBySection(params) {
return bindingUtil.groupBy(params, bindingToSection);
}
function bindingToSection(binding) {
return binding.section;
}
function compareParamGroups(a, b) {
return compareReferences(a.reason, b.reason);
}
function isNativeNode(tag) {
if (isCoreTag(tag)) switch (tag.node.name.value) {
case "html-comment":
case "html-script":
case "html-style":
case "show": return true;
case "style": return tag.node.body.body.some((child) => _marko_compiler.types.isMarkoPlaceholder(child));
default: return false;
}
return analyzeTagNameType(tag) === 0;
}
//#endregion
//#region src/translator/visitors/function.ts
const [getReferencesByFn] = createProgramState(() => /* @__PURE__ */ new Map());
const [getReferencesByImportedFn] = createProgramState(() => /* @__PURE__ */ new Map());
var function_default = { analyze(fn) {
const awaitNode = isMarkoAttribute(fn.parentPath) && _marko_compiler.types.isFunctionExpression(fn.node) && !fn.node.async && traverseFindAwait(fn.node.body);
if (awaitNode) {
const file = (0, _marko_compiler_babel_utils.getFile)();
const start = file.code.indexOf("await", awaitNode.start ?? 0);
const highlight = start >= 0 && (awaitNode.end == null || start < awaitNode.end) ? (0, _marko_compiler_babel_utils.withLoc)(file, _marko_compiler.types.cloneNode(awaitNode), start, start + 5) : awaitNode;
throw fn.hub.buildError(highlight, "Attribute methods containing `await` must be `async`. Add `async` before the method name.");
}
if (fn !== getFnRoot(fn)) return;
const { node } = fn;
if ((_marko_compiler.types.isObjectMethod(node) || _marko_compiler.types.isClassMethod(node)) && (node.kind === "get" || node.kind === "set")) return;
const exprRoot = getExprRoot(fn);
const markoRoot = getMarkoRoot(exprRoot);
if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) return;
const section = getSection(fn);
const fnExtra = node.extra ??= {};
fnExtra.section = section;
fnExtra.name = node.id?.name || (isMarkoAttribute(markoRoot) ? markoRoot.node.default ? _marko_compiler.types.toIdentifier((markoRoot.parentPath.has("var") ? markoRoot.parentPath.get("var") : markoRoot.parentPath.get("name")).toString()) : markoRoot.node.name : _marko_compiler.types.isVariableDeclarator(fn.parent) && _marko_compiler.types.isIdentifier(fn.parent.id) ? fn.parent.id.name : _marko_compiler.types.isObjectMethod(node) && _marko_compiler.types.isIdentifier(node.key) ? node.key.name : "anonymous");
reserveExportRegisterId(fnExtra, fn, markoRoot);
if (isStaticRoot(markoRoot)) {
const refs = getStaticDeclRefs(fn);
if (refs === true) registerFunction(fnExtra, true);
else if (refs.size) getReferencesByFn().set(fnExtra, refs);
} else if (shouldAlwaysRegister(markoRoot)) registerFunction(fnExtra, true);
else {
const refs = /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]);
if (getConstTagVarRefs(markoRoot, refs) === true) registerFunction(fnExtra, true);
else getReferencesByFn().set(fnExtra, refs);
}
} };
function getConstTagVarRefs(markoRoot, refs, seen = /* @__PURE__ */ new Set()) {
const tag = getTagFromMarkoRoot(markoRoot);
if (!tag?.node.var || !isCoreTagName(tag, "const") || seen.has(tag.node)) return refs;
seen.add(tag.node);
const ids = tag.get("var").getOuterBindingIdentifiers();
for (const name in ids) {
const binding = tag.scope.getBinding(name);
if (binding && addBindingRefs(binding, refs, seen) === true) return true;
}
return refs;
}
function finalizeFunctionRegistry() {
for (const [fnExtra, exprExtras] of getReferencesByFn()) {
const reason = resolveSerializeReason(exprExtras);
if (reason) registerFunction(fnExtra, reason);
}
for (const [importedFn, exprExtras] of getReferencesByImportedFn()) if (resolveSerializeReason(exprExtras)) registerImportedFn(importedFn);
}
/**
* Tracks a function imported from another template that reserved a register id.
* The importing template registers it (under the reserved id) when its own
* references reach something serialized.
*/
function trackImportedFn(importDecl, local, resolved) {
const binding = importDecl.scope.getBinding(local);
if (!binding) return;
const importedFn = {
...resolved,
node: importDecl.node,
local
};
const refs = /* @__PURE__ */ new Set();
if (addBindingRefs(binding, refs, /* @__PURE__ */ new Set()) === true) registerImportedFn(importedFn);
else if (refs.size) getReferencesByImportedFn().set(importedFn, refs);
}
/**
* Finds the id reserved for an export, following `export ... from` hops. Each
* template only records the exports it declares, so this resolves on demand:
* a template in an import cycle is read while it is still analyzing, and would
* hand out an incomplete map if the ids were pushed ahead of time.
*/
function resolveRegisteredExport(file, exportName, seen = /* @__PURE__ */ new Set()) {
const filename = file.opts.filename;
const key = `${filename}\0${exportName}`;
if (seen.has(key)) return;
seen.add(key);
const reserved = file.ast.program.extra?.registeredExports?.get(exportName);
if (reserved) return {
...reserved,
filename
};
for (const child of file.ast.program.body) {
if (child.type !== "ExportNamedDeclaration" && child.type !== "ExportAllDeclaration" || !child.source || (child.exportKind || "value") !== "value") continue;
const sourceFile = (0, _marko_compiler_babel_utils.loadFileForImport)(file, child.source.value);
if (!sourceFile) continue;
if (child.type === "ExportAllDeclaration") {
const resolved = resolveRegisteredExport(sourceFile, exportName, seen);
if (resolved) return resolved;
continue;
}
for (const specifier of child.specifiers) {
if (specifier.type !== "ExportSpecifier" || (specifier.exportKind || "value") !== "value" || getExportedName(specifier) !== exportName) continue;
const resolved = resolveRegisteredExport(sourceFile, specifier.local.name, seen);
if (resolved) return resolved;
}
}
}
function resolveSerializeReason(exprExtras) {
let reason;
for (const exprExtra of exprExtras) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForExtra(getCanonicalExtra(exprExtra), true));
return reason;
}
function registerImportedFn({ node, ...importedFn }) {
const extra = node.extra ??= {};
extra.registeredImportedFns ??= [];
extra.registeredImportedFns.push(importedFn);
(0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
}
function reserveExportRegisterId(fnExtra, fn, markoRoot) {
if (!isStaticRoot(markoRoot)) return;
const exportNames = getExportNames(fn, markoRoot);
const exportName = exportNames?.find((name) => _marko_compiler.types.isValidIdentifier(name));
if (!exportName) return;
const { markoOpts, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
const programExtra = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
const registerId = (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename, `${fnExtra.section.id}/export/${exportName}`);
fnExtra.exportRegisterId = registerId;
programExtra.registeredExports ??= /* @__PURE__ */ new Map();
for (const name of exportNames) programExtra.registeredExports.set(name, {
registerId,
exportName
});
}
function getExportNames(fn, markoRoot) {
const localName = getExportableName(fn);
if (localName === void 0) return;
const exportNames = markoRoot.isExportNamedDeclaration() && !markoRoot.node.source ? [localName] : [];
const binding = fn.scope.getBinding(localName);
if (binding) for (const ref of binding.referencePaths) {
const specifier = ref.parent;
if (specifier?.type === "ExportSpecifier" && (specifier.exportKind || "value") === "value" && !ref.parentPath.parent.source) {
const exportName = getExportedName(specifier);
if (exportName !== "default") exportNames.push(exportName);
}
}
return exportNames.length ? exportNames : void 0;
}
function getExportableName(fn) {
const { node, parent } = fn;
if (node.type === "FunctionDeclaration") return node.id?.name;
if (_marko_compiler.types.isVariableDeclarator(parent) && parent.init === node && _marko_compiler.types.isIdentifier(parent.id) && _marko_compiler.types.isVariableDeclaration(fn.parentPath.parent, { kind: "const" })) return parent.id.name;
}
function getExportedName(specifier) {
const { exported } = specifier;
return exported.type === "Identifier" ? exported.name : exported.value;
}
function canIgnoreRegister(markoRoot, exprRoot) {
return markoRoot.isMarkoPlaceholder() || markoRoot.isMarkoScriptlet() && (!markoRoot.node.static || markoRoot.node.target === "server") || markoRoot.isMarkoTag() && markoRoot.node.name == exprRoot.node || isMarkoAttribute(markoRoot) && (analyzeTagNameType(markoRoot.parentPath) === 0 && /^on[A-Z-]/.test(markoRoot.node.name) && !hasSpreadAttributeAfter(markoRoot) || isCoreTagName(markoRoot.parentPath, "script") || isCoreTagName(markoRoot.parentPath, "lifecycle") || isCoreTagName(markoRoot.parentPath, "for"));
}
function getStaticDeclRefs(path, refs = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set()) {
const decl = getDeclarationRoot(path);
if (decl && !seen.has(decl.node)) {
seen.add(decl.node);
const ids = decl.getOuterBindingIdentifiers();
if (ids) for (const name in ids) {
const binding = decl.scope.getBinding(name);
if (!binding) continue;
if (addBindingRefs(binding, refs, seen) === true) return true;
}
}
return refs;
}
function addBindingRefs(binding, refs, seen) {
for (const ref of binding.referencePaths) {
if (isInvokedFunction(ref) || ref.parentPath.type === "Program") continue;
const exprRoot = getExprRoot(ref);
const markoRoot = getMarkoRoot(exprRoot);
if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
if (isStaticRoot(markoRoot)) {
if (getStaticDeclRefs(ref, refs, seen) === true) return true;
} else if (shouldAlwaysRegister(markoRoot)) return true;
else {
refs.add(exprRoot.node.extra ??= {});
if (getConstTagVarRefs(markoRoot, refs, seen) === true) return true;
}
}
}
function shouldAlwaysRegister(markoRoot) {
const tag = getTagFromMarkoRoot(markoRoot);
if (!tag) return false;
if (isCoreTagName(tag, "let")) return true;
if (isCoreTagName(tag, "return")) return true;
return analyzeTagNameType(tag) === 0;
}
function hasSpreadAttributeAfter(attr) {
const attrs = attr.parent.attributes;
for (let i = attr.key + 1; i < attrs.length; i++) if (attrs[i].type === "MarkoSpreadAttribute") return true;
return false;
}
function getTagFromMarkoRoot(markoRoot) {
let cur = markoRoot;
do {
if (cur.isMarkoTag()) return cur;
cur = cur.parentPath;
} while (cur);
}
function registerFunction(fnExtra, reason) {
const { markoOpts, path: program, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
program.node.extra.isInteractive = true;
fnExtra.registerReason = reason;
fnExtra.name = generateUid(fnExtra.name);
fnExtra.registerId = fnExtra.exportRegisterId ?? (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename, `${fnExtra.section.id}/${fnExtra.name.slice(1)}`);
}
function isMarkoAttribute(path) {
return path ? path.isMarkoAttribute() : false;
}
function isStaticRoot(path) {
switch (path.type) {
case "MarkoScriptlet": return path.node.static;
case "ExportDefaultDeclaration":
case "ExportNamedDeclaration": return true;
default: return false;
}
}
//#endregion
//#region src/translator/util/analyze-errors.ts
const [getHasAnalyzeErrors, setHasAnalyzeErrors] = createProgramState(() => false);
function reportAnalyzeError(path, error) {
if (!(error instanceof Error)) throw error;
const { label = error.message, loc } = error;
setHasAnalyzeErrors(true);
(0, _marko_compiler_babel_utils.diagnosticError)(path, {
label,
loc: loc ?? path.node.loc ?? void 0
});
}
function hasAnalyzeErrors() {
return getHasAnalyzeErrors();
}
//#endregion
//#region src/translator/util/asset-imports.ts
function addAssetImport(request) {
((0, _marko_compiler_babel_utils.getFile)().metadata.marko.assetImports ??= /* @__PURE__ */ new Set()).add(request);
}
function isClientAssetImport(file, request) {
const { hydrateIncludeImports } = file.markoOpts;
return typeof hydrateIncludeImports === "function" ? hydrateIncludeImports(request) : !!hydrateIncludeImports?.test(request);
}
//#endregion
//#region src/translator/util/binding-has-prop.ts
function isSectionRendererElided(section) {
return !!section.downstream?.binding && !bindingHasProperty(section.downstream.binding, section.downstream.properties);
}
function bindingHasProperty(binding, properties) {
if (binding.pruned) return false;
else if (binding.pruned === void 0) throw new Error("Binding must be pruned before checking properties");
if (binding.reads.size || !properties) return true;
let property;
let rest;
if (Array.isArray(properties)) {
property = properties[0];
rest = properties.length === 2 ? properties[1] : properties.slice(1);
} else property = properties;
const propBinding = binding.propertyAliases.get(property);
if (propBinding && bindingHasProperty(propBinding, rest)) return true;
for (const alias of binding.aliases) if (bindingHasProperty(alias, properties)) return true;
return false;
}
//#endregion
//#region src/translator/util/binding-prop-tree.ts
const kDirectContent = Symbol("direct content");
function getBindingPropTree(binding) {
if (pruneBinding(binding)) return;
binding.exposed = true;
const props = {
binding,
props: void 0,
rest: void 0
};
if (!binding.reads.size) {
if (!binding.aliases.size) {
props.props = Object.create(null);
for (const [property, alias] of binding.propertyAliases) props.props[property] = getBindingPropTree(alias);
} else if (binding.aliases.size === 1) {
const [restAlias] = binding.aliases;
if (hasSupersetExcludeProperties(binding, restAlias.excludeProperties)) {
props.rest = getBindingPropTree(restAlias);
props.props = Object.create(null);
if (restAlias.type === 2) restAlias.export ??= generateUid(restAlias.name);
forEach(restAlias.excludeProperties, (property) => {
const propAlias = binding.propertyAliases.get(property);
if (propAlias) props.props[property] = getBindingPropTree(propAlias);
});
}
}
}
if (binding.type === 2) binding.export ??= generateUid(binding.name);
if (isDirectContentBinding(binding)) binding.directContentExport ??= generateUid(`${binding.name}_direct`);
return props;
}
function isDirectContentBinding(binding) {
if (binding.reads.size !== 1) return false;
const [read] = binding.reads;
return read[kDirectContent] && read.section === binding.section;
}
function hasSupersetExcludeProperties(binding, excludeProperties) {
if (excludeProperties === void 0) return false;
for (const prop of binding.propertyAliases.keys()) if (!propsUtil.has(excludeProperties, prop)) return false;
return true;
}
function getKnownFromPropTree(propTree, name) {
return propTree === true ? true : propTree.props ? propTree.props[name] || (propTree.rest ? getKnownFromPropTree(propTree.rest, name) : void 0) : includes(propTree.binding.excludeProperties, name) ? void 0 : true;
}
function getAllKnownPropNames(propTree) {
const keys = propTree.props ? Object.keys(propTree.props) : [];
if (propTree.rest?.props) for (const key of Object.keys(propTree.rest.props)) keys.push(key);
return keys;
}
function hasAllKnownProps(propTree) {
return propTree.props && (!propTree.rest || !!propTree.rest.props);
}
//#endregion
//#region src/translator/util/resolve-relative-to-entry.ts
function resolveRelativeToEntry(entryFile, file, req) {
return file === entryFile ? (0, _marko_compiler_babel_utils.resolveRelativePath)(file, req) : (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, req[0] === "." ? path.default.join(file.opts.filename, "..", req) : req);
}
//#endregion
//#region src/translator/util/entry-builder.ts
const kState = Symbol();
const builder = {
build(entryFile, exportInit) {
const state = entryFile[kState];
if (!state) throw entryFile.path.buildCodeFrameError("Unable to build hydrate code, no files were visited before finalizing the build");
const body = [];
for (const asset of state.assets) body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(asset)));
if (state.init || state.load) {
const isPage = entryFile.path.node.extra.page;
const initHelper = isPage ? "init" : "initEmbedded";
if (state.init) body.push(_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier(initHelper), _marko_compiler.types.identifier(initHelper))], _marko_compiler.types.stringLiteral(`${runtime_info_default.name}/${entryFile.markoOpts.optimize ? "" : "debug/"}dom`)));
for (const root of state.roots) body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(root)));
if (!state.init) {
if (exportInit) body.push(_marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))));
return body;
}
const { runtimeId } = entryFile.markoOpts;
const readyId = !isPage && (0, _marko_compiler_babel_utils.getTemplateId)(entryFile.markoOpts, entryFile.opts.filename);
const initExpression = _marko_compiler.types.callExpression(_marko_compiler.types.identifier(initHelper), readyId ? runtimeId ? [_marko_compiler.types.stringLiteral(readyId), _marko_compiler.types.stringLiteral(runtimeId)] : [_marko_compiler.types.stringLiteral(readyId)] : runtimeId ? [_marko_compiler.types.stringLiteral(runtimeId)] : []);
body.push(exportInit ? _marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], initExpression)) : _marko_compiler.types.expressionStatement(initExpression));
} else {
for (const asset of state.bundledAssets) body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(asset)));
if (exportInit) body.push(_marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))));
}
return body;
},
visit(file, entryFile, visitChild = (id, bundled = false) => {
const state = entryFile[kState];
const resolved = resolveRelativeToEntry(entryFile, file, id);
const seenBundled = state.visited.get(resolved);
if (seenBundled === false || seenBundled && bundled) return;
state.visited.set(resolved, bundled);
const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
if (childFile) builder.visit(childFile, entryFile);
}) {
const state = entryFile[kState] ||= {
init: false,
load: false,
bundled: 0,
roots: [],
assets: /* @__PURE__ */ new Set(),
bundledAssets: /* @__PURE__ */ new Set(),
visited: /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]])
};
const programExtra = file.path.node.extra;
const { analyzedTags, assetImports } = file.metadata.marko;
const { loadImports } = programExtra;
const init = !!(programExtra.isInteractive || programExtra.needsCompat);
const load = !!programExtra.hasClientStatement;
const isRoot = !state.bundled && (init || load || !!programExtra.hasResumes);
if (init) state.init = true;
if (load) state.load = true;
if (isRoot) state.roots.push((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, file.opts.filename));
if (assetImports) {
const assets = isRoot || state.bundled ? state.bundledAssets : state.assets;
for (const request of assetImports) assets.add(resolveRelativeToEntry(entryFile, file, request));
}
if (isRoot) state.bundled++;
for (const tag of analyzedTags ? [...analyzedTags] : []) {
const lazy = loadImports?.has(tag);
if (lazy) state.bundled++;
visitChild(tag, !!state.bundled);
if (lazy) state.bundled--;
}
if (isRoot) state.bundled--;
}
};
//#endregion
//#region src/translator/util/get-style-file.ts
function getStyleFile(file) {
const { filename } = file.opts;
const fs = file.markoOpts.fileSystem;
const base = getBase(filename);
const styleMatch = new RegExp(`^(${escapeRegExp(base)}\\.${"index" === base ? "|" : ""})style\\.\\w+$`);
for (const file of fs.readdirSync(path.default.dirname(filename)).sort()) if (styleMatch.test(file)) return `./${file}`;
}
/**
* Given a filename, gets the base name, strips off the file extension
* and removes any arc flags (https://github.com/eBay/arc).
*
* @example
* getBase("/dir/foo.marko") // => "foo"
* getBase("/dir/foo.bar.marko") // => "foo.bar"
* getBase("/dir/foo[bar].marko") // => "foo"
* getBase("/dir/foo[bar].baz.marko") // => "foo.baz"
*/
function getBase(filename) {
const start = filename.lastIndexOf(path.default.sep) + 1;
const leftDot = filename.indexOf(".", start);
if (leftDot === -1) return filename.slice(start);
const rightDot = filename.lastIndexOf(".");
const closeBracket = leftDot - 1;
if (filename[closeBracket] === "]") {
const openBracket = filename.lastIndexOf("[", closeBracket);
if (openBracket > start) return filename.slice(start, openBracket) + filename.slice(leftDot, rightDot);
}
return filename.slice(start, rightDot);
}
const regexpCharsReg = /[\\^$.*+?()[\]{}|]/g;
function escapeRegExp(str) {
return str.replace(regexpCharsReg, "\\$&");
}
//#endregion
//#region src/common/errors.ts
function assertExclusiveAttrs(attrs, onError = throwErr) {
if (attrs) {
let exclusiveAttrs;
if (attrs.checkedChange) (exclusiveAttrs ||= []).push("checkedChange");
if ("checkedValue" in attrs) {
(exclusiveAttrs ||= []).push("checkedValue");
if ("checked" in attrs) exclusiveAttrs.push("checked");
} else if (attrs.checkedValueChange) {
(exclusiveAttrs ||= []).push("checkedValueChange");
if ("checked" in attrs) exclusiveAttrs.push("checked");
}
if (attrs.valueChange) {
(exclusiveAttrs ||= []).push("valueChange");
if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
}
if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
}
}
function throwErr(msg) {
throw new Error(msg);
}
function joinWithAnd(a) {
switch (a.length) {
case 0: return "";
case 1: return a[0];
case 2: return `${a[0]} and ${a[1]}`;
default: return `${a.slice(0, -1).join(", ")}, and ${a[a.length - 1]}`;
}
}
//#endregion
//#region src/html/content.ts
function _unescaped(val) {
return val ? val + "" : val === 0 ? "0" : "";
}
const unsafeXMLReg = /[<&\r]/g;
const replaceUnsafeXML = (c) => c === "&" ? "&" : c === "<" ? "<" : " ";
const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
function _escape(val) {
return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
}
const unsafeScriptReg = /<(\/?script|!--)/gi;
const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str;
function _escape_script(val) {
return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
}
const unsafeStyleReg = /<(\/style)/gi;
const escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C$1") : str;
function _escape_style(val) {
return val ? escapeStyleStr(val + "") : val === 0 ? "0" : "";
}
const unsafeCommentReg = />/g;
const escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, ">") : str;
function _escape_comment(val) {
return val ? escapeCommentStr(val + "") : val === 0 ? "0" : "";
}
globalThis.setImmediate || globalThis.setTimeout || globalThis.queueMicrotask;
//#endregion
//#region src/html/attrs.ts
function _attr_class(value) {
return stringAttr("class", toDelimitedString(value, " ", stringifyClassObject));
}
function _attr_style(value) {
return stringAttr("style", toDelimitedString(value, ";", stringifyStyleObject));
}
function _attr(name, value) {
return isVoid(value) ? "" : nonVoidAttr(name, value);
}
function stringAttr(name, value) {
return value && " " + name + attrAssignment(value);
}
function nonVoidAttr(name, value) {
switch (typeof value) {
case "string": return " " + name + attrAssignment(value);
case "boolean": return " " + name;
case "number": return " " + name + "=" + value;
}
return " " + name + attrAssignment(value + "");
}
const singleQuoteAttrReplacements = /['\r]|&(?=[#a-zA-Z])/g;
const doubleQuoteAttrReplacements = /["\r]|&(?=[#a-zA-Z])/g;
const needsQuotedAttr = /["'>\s]|&[#a-zA-Z]|\/$/g;
function attrAssignment(value) {
return value ? needsQuotedAttr.test(value) ? value[needsQuotedAttr.lastIndex - 1] === (needsQuotedAttr.lastIndex = 0, "\"") ? "='" + escapeSingleQuotedAttrValue(value) + "'" : "=\"" + escapeDoubleQuotedAttrValue(value) + "\"" : "=" + value : "";
}
function escapeSingleQuotedAttrValue(value) {
return singleQuoteAttrReplacements.test(value) ? value.replace(singleQuoteAttrReplacements, replaceUnsafeSingleQuoteAttrChar) : value;
}
function replaceUnsafeSingleQuoteAttrChar(match) {
return match === "'" ? "'" : match === "\r" ? " " : "&";
}
function escapeDoubleQuotedAttrValue(value) {
return doubleQuoteAttrReplacements.test(value) ? value.replace(doubleQuoteAttrReplacements, replaceUnsafeDoubleQuoteAttrChar) : value;
}
function replaceUnsafeDoubleQuoteAttrChar(match) {
return match === "\"" ? """ : match === "\r" ? " " : "&";
}
//#endregion
//#region src/translator/util/runtime.ts
const pureDOMFunctions = /* @__PURE__ */ new Set([
"_await_promise",
"_await_content",
"_child_setup",
"_if",
"_if_closure",
"_show",
"_try",
"_dynamic_tag",
"_dynamic_tag_content",
"_content_closures",
"_content",
"_template",
"_closure",
"_closure_get",
"_or",
"_for_closure",
"_for_selector",
"_for_in",
"_for_of",
"_for_to",
"_for_until",
"_hoist",
"_let",
"_let_change",
"_const",
"_load_signal",
"_load_setup",
"_load_template",
"_load_visible_trigger",
"_load_event_trigger",
"_load_idle_trigger",
"_load_media_trigger",
"_load_race_trigger"
]);
const [getRuntimeImports] = createProgramState(() => /* @__PURE__ */ new Map());
function importRuntime(name) {
if (!isTranslate()) throw new Error(`\`importRuntime(${JSON.stringify(name)})\` may only be called during the translate stage.`);
const { output } = getMarkoOpts();
const imports = getRuntimeImports();
let localName = imports.get(name);
if (!localName) {
localName = (0, _marko_compiler_babel_utils.importNamed)((0, _marko_compiler_babel_utils.getFile)(), getRuntimePath(output), name).name;
imports.set(name, localName);
}
return _marko_compiler.types.identifier(localName);
}
function callRuntime(name, ...args) {
const callExpression = _marko_compiler.types.callExpression(importRuntime(name), filterArguments(args));
if (isOutputDOM() && pureDOMFunctions.has(name)) return _marko_compiler.types.addComment(callExpression, "leading", "@__PURE__");
return callExpression;
}
const importedFeatures = /* @__PURE__ */ new WeakMap();
function importRuntimeFeature(feature) {
if (!isTranslate()) throw new Error(`\`importRuntimeFeature(${JSON.stringify(feature)})\` may only be called during the translate stage.`);
const program = (0, _marko_compiler_babel_utils.getProgram)().node;
let features = importedFeatures.get(program);
if (!features) importedFeatures.set(program, features = /* @__PURE__ */ new Set());
if (!features.has(feature)) {
features.add(feature);
program.body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(`${getRuntimePath("dom")}/${feature}.feat`)));
}
}
function getHTMLRuntime() {
return {
_escape,
_escape_comment,
_unescaped,
_attr,
_attr_class,
_attr_style,
_escape_script,
_escape_style
};
}
function getRuntimePath(output) {
const { optimize } = getMarkoOpts();
return `${runtime_info_default.name}/${optimize ? "" : "debug/"}${output === "html" ? "html" : "dom"}`;
}
function filterArguments(args) {
const filteredArgs = [];
for (let i = args.length; i--;) {
const arg = args[i];
if (arg || filteredArgs.length) filteredArgs[i] = arg || _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
}
return filteredArgs;
}
function getCompatRuntimeFile() {
const markoOpts = getMarkoOpts();
return `marko/${markoOpts.optimize ? "dist" : "src"}/runtime/helpers/tags-compat/${isOutputHTML() ? "html" : "dom"}${markoOpts.optimize ? "" : "-debug"}.${markoOpts.modules === "esm" ? "mjs" : "js"}`;
}
//#endregion
//#region src/translator/util/setup-statements.ts
/**
* Tracks during analyze whether translate will add setup-signal statements, so a
* template can prove its setup export is a noop and parents can skip calling it.
*/
const [getSetupInfo] = createSectionState("setupStatements", () => ({
forced: false,
exprs: /* @__PURE__ */ new Set()
}));
function addSetupStatement(section) {
getSetupInfo(section).forced = true;
}
function addSetupExpr(section, node) {
if (node) getSetupInfo(section).exprs.add(node.extra ??= {});
else getSetupInfo(section).forced = true;
}
function sectionHasSetupStatements(section) {
const info = getSetupInfo(section);
if (info.forced) return true;
for (let extra of info.exprs) {
while (extra.merged) extra = extra.merged;
if (!extra.pruned && !extra.referencedBindings) return true;
}
return false;
}
//#endregion
//#region src/translator/util/module-registrations.ts
/**
* Writes the registrations for module scoped functions: the ones this template
* exports and registers itself, and the ones it imports from a template that
* reserved a register id without registering it.
*/
function writeModuleRegistrations(program) {
const file = (0, _marko_compiler_babel_utils.getFile)();
const statements = [];
const seen = /* @__PURE__ */ new Set();
for (const child of program.node.body) {
const registeredImportedFns = child.extra?.registeredImportedFns;
if (registeredImportedFns) for (const importedFn of registeredImportedFns) {
if (seen.has(importedFn.registerId)) continue;
seen.add(importedFn.registerId);
if (isOutputHTML()) statements.push(buildRegistration(importedFn.local, importedFn.registerId));
else (0, _marko_compiler_babel_utils.importDefault)(file, resolveRegisterModule(file, importedFn));
}
else if (child.type === "ExportNamedDeclaration") addExportRegistrations(child, seen, statements);
}
program.node.body.push(...statements);
}
function addExportRegistrations(node, seen, statements) {
const { declaration } = node;
if (!declaration) return;
const add = (local, registerId) => {
if (seen.has(registerId)) return;
seen.add(registerId);
statements.push(buildRegistration(local, registerId));
};
if (declaration.type === "FunctionDeclaration") {
if (isRegisteredFnExtra(declaration.extra)) add(declaration.id.name, declaration.extra.registerId);
return;
}
if (isOutputHTML() || declaration.type !== "VariableDeclaration") return;
for (const declarator of declaration.declarations) {
const extra = declarator.init?.extra;
if (isRegisteredFnExtra(extra) && _marko_compiler.types.isIdentifier(declarator.id)) add(declarator.id.name, extra.registerId);
}
}
function buildRegistration(local, registerId) {
return _marko_compiler.types.expressionStatement(isOutputHTML() ? callRuntime("_resume", _marko_compiler.types.identifier(local), _marko_compiler.types.stringLiteral(registerId)) : callRuntime("_resume", _marko_compiler.types.stringLiteral(registerId), _marko_compiler.types.identifier(local)));
}
function resolveRegisterModule(file, { filename, exportName, registerId }) {
const importer = file.opts.filename;
return getMarkoOpts().resolveVirtualDependency(importer, {
virtualPath: `${relativePath(importer, filename)}.register-${exportName}.js`,
code: `import { ${exportName} } from "./${path.default.basename(filename)}";\nimport { _resume } from "${getRuntimePath("dom")}";\n_resume(${JSON.stringify(registerId)}, ${exportName});\n`
});
}
function relativePath(from, to) {
const relative = path.default.relative(path.default.dirname(from), to).split(path.default.sep).join("/");
return relative.startsWith(".") ? relative : `./${relative}`;
}
//#endregion
//#region src/translator/util/get-known-attr-values.ts
function getKnownAttrValues(tag) {
const attrs = {};
for (const attr of tag.attributes) if (attr.type === "MarkoAttribute") attrs[attr.name] = attr.value;
return attrs;
}
//#endregion
//#region src/translator/util/get-parent-tag.ts
function getParentTag(tag) {
const parent = tag.parent.type === "MarkoTagBody" ? tag.parentPath.parentPath : tag.parentPath;
if (parent.type === "MarkoTag") return parent;
}
function getAttributeTagParent(tag) {
let cur = tag;
while ((0, _marko_compiler_babel_utils.isAttributeTag)(cur) || (0, _marko_compiler_babel_utils.isTransparentTag)(cur)) cur = getParentTag(cur);
return cur;
}
//#endregion
//#region src/translator/util/plugin-hooks.ts
function enter$1(modulePlugin, path) {
if (!modulePlugin) return false;
const { node } = path;
const plugin = isModulePlugin(modulePlugin) ? modulePlugin.default : modulePlugin;
if (isFunctionPlugin(plugin)) plugin(path, _marko_compiler.types);
else if (plugin.enter) plugin.enter(path, _marko_compiler.types);
return node !== path.node;
}
function exit$1(modulePlugin, path) {
if (!modulePlugin) return false;
const { node } = path;
const plugin = isModulePlugin(modulePlugin) ? modulePlugin.default : modulePlugin;
if (!isFunctionPlugin(plugin) && plugin.exit) plugin.exit(path, _marko_compiler.types);
return node !== path.node;
}
function isModulePlugin(plugin) {
return Boolean(plugin.default);
}
function isFunctionPlugin(plugin) {
return typeof plugin === "function";
}
//#endregion
//#region src/translator/util/visitors.ts
function extractVisitors(visitors) {
const result = {
migrate: {},
transform: {},
analyze: {},
translate: {}
};
for (const _name in visitors) {
const name = _name;
const value = visitors[name];
if (value.migrate) result.migrate[name] = value.migrate;
if (value.transform) result.transform[name] = value.transform;
if (value.analyze) result.analyze[name] = value.analyze;
if (value.translate) result.translate[name] = value.translate;
}
return result;
}
function translateByTarget({ html, dom }) {
return {
enter(path) {
enter$1(isOutputHTML() ? html : dom, path);
},
exit(path) {
exit$1(isOutputHTML() ? html : dom, path);
}
};
}
//#endregion
//#region src/translator/util/normalize-string-expression.ts
function normalizeStringExpression(parts, useIife) {
const strs = [];
const exprs = [];
let curStr = "";
for (let i = 0; i < parts.length; i++) {
let content = parts[i];
if (typeof content === "object") if (_marko_compiler.types.isStringLiteral(content)) content = content.value;
else if (_marko_compiler.types.isTemplateLiteral(content)) {
let nextIndex = i + 1;
const exprLen = content.expressions.length;
shiftItems(parts, nextIndex, content.quasis.length + exprLen);
for (let j = 0; j < exprLen; j++) {
parts[nextIndex++] = content.quasis[j].value.cooked ?? "";
parts[nextIndex++] = content.expressions[j];
}
parts[nextIndex] = content.quasis[exprLen].value.cooked ?? "";
continue;
} else {
exprs.push(content);
strs.push(curStr);
curStr = "";
continue;
}
curStr += content;
}
if (exprs.length) {
if (exprs.length === 1 && !curStr && !strs[0]) return exprs[0];
strs.push(curStr);
if (useIife) {
const params = exprs.map((_, i) => _marko_compiler.types.identifier(`_w${i}`));
const iife = _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.templateLiteral(strs.map((raw) => _marko_compiler.types.templateElement({ raw: escapeTemplateRaw(raw) })), params)), exprs);
_marko_compiler.types.addComment(iife, "leading", "@__PURE__");
return iife;
}
return _marko_compiler.types.templateLiteral(strs.map((raw) => _marko_compiler.types.templateElement({ raw: escapeTemplateRaw(raw) })), exprs);
} else if (curStr) return _marko_compiler.types.stringLiteral(curStr);
}
function appendLiteral(arr, str) {
arr[arr.length - 1] += str;
}
function escapeTemplateRaw(raw) {
return raw.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$(?=\{)/g, "\\$");
}
function shiftItems(list, start, offset) {
for (let i = list.length - 1; i >= start; i--) list[i + offset] = list[i];
}
//#endregion
//#region src/translator/util/with-comment.ts
function withLeadingComment(node, value) {
if (value) {
const comment = {
type: "CommentBlock",
value: ` ${value} `
};
node.leadingComments = node.leadingComments ? [...node.leadingComments, comment] : [comment];
}
return node;
}
//#endregion
//#region src/translator/util/serialize-guard.ts
const [getSectionReasonState] = createSectionState("serializeReasonState", (section) => ({
if: createTypeState(),
guard: createTypeState(),
declarators: [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(getSharedUid(`scope${section.id}_reason`, section)), callRuntime("_scope_reason"))]
}));
function getScopeReasonDeclaration(section) {
return _marko_compiler.types.variableDeclaration("const", getSectionReasonState(section).declarators);
}
function getSerializeGuard(section, reason, optional) {
if (!isReasonDynamic(reason) || isCrossSection(section, reason)) {
if (!reason) return _marko_compiler.types.numericLiteral(0);
return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason === true ? void 0 : reason.state));
}
return getOrHoist(reason, true);
}
function getSerializeGuardForAny(section, reasons, optional) {
if (!Array.isArray(reasons)) return getSerializeGuard(section, reasons, optional);
let expr;
for (const reason of reasons) {
if (!isReasonDynamic(reason)) return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason.state));
const guard = getSerializeGuard(section, reason, false);
expr = expr ? _marko_compiler.types.logicalExpression("||", expr, guard) : guard;
}
return expr;
}
function getExprIfSerialized(section, reason, expr) {
if (!isReasonDynamic(reason) || isCrossSection(section, reason)) return reason && expr;
const guard = getOrHoist(reason, false);
return guard ? _marko_compiler.types.logicalExpression("&&", guard, expr) : expr;
}
function getOrHoist(reason, isGuard) {
const onlySection = getOnlySection(reason.param);
if (onlySection) {
const state = getSectionReasonState(onlySection);
const tracking = isGuard ? state.guard : state.if;
const existingFound = sourcesUtil.find(tracking.hoistedReasons, reason);
if (existingFound) return _marko_compiler.types.identifier(tracking.names.get(existingFound));
const guard = buildGuardExpr(onlySection, reason.param, isGuard);
const seenFound = sourcesUtil.find(tracking.seenReasons, reason);
if (!seenFound) {
const expr = _marko_compiler.types.parenthesizedExpression(guard);
tracking.pending.set(reason, expr);
tracking.seenReasons = sourcesUtil.add(tracking.seenReasons, reason);
return expr;
}
const name = generateUid(`${isGuard ? "sg" : "si"}__${getDebugNamesAsIdentifier(reason.param)}`);
tracking.hoistedReasons = sourcesUtil.add(tracking.hoistedReasons, reason);
tracking.names.set(reason, name);
state.declarators.push(_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(name), guard));
const pendingParen = tracking.pending.get(seenFound);
if (pendingParen) {
pendingParen.expression = _marko_compiler.types.identifier(name);
tracking.pending.delete(seenFound);
}
return _marko_compiler.types.parenthesizedExpression(_marko_compiler.types.identifier(name));
}
let orExpr;
for (const [paramsSection, params] of groupParamsBySection(reason.param)) {
const expr = buildGuardExpr(paramsSection, params, isGuard);
orExpr = orExpr ? _marko_compiler.types.logicalExpression("||", orExpr, expr) : expr;
}
return orExpr;
}
function buildGuardExpr(paramsSection, params, isGuard) {
const serializeIdentifier = _marko_compiler.types.identifier(getSharedUid(`scope${paramsSection.id}_reason`, paramsSection));
return paramsSection.paramReasonGroups ? callRuntime(isGuard ? "_serialize_guard" : "_serialize_if", serializeIdentifier, withLeadingComment(_marko_compiler.types.numericLiteral(getParamReasonGroupIndex(paramsSection, params)), getDebugNames(params))) : serializeIdentifier;
}
function getOnlySection(params) {
if (params === void 0) return void 0;
if (!Array.isArray(params)) return params.section;
const { section } = params[0];
return section === params[params.length - 1].section ? section : void 0;
}
function isCrossSection(section, reason) {
return some(reason.param, (param) => !isSameOrChildSection(param.section, section));
}
function createTypeState() {
return {
names: /* @__PURE__ */ new Map(),
pending: /* @__PURE__ */ new Map(),
seenReasons: void 0,
hoistedReasons: void 0
};
}
//#endregion
//#region src/translator/util/writer.ts
const [getWrites] = createSectionState("writes", () => [""]);
const [getTrailerWrites] = createSectionState("trailerWrites", () => [""]);
function writeTo$1(path, trailer) {
const section = getSection(path);
const get = trailer ? getTrailerWrites : getWrites;
return (strs, ...exprs) => {
const exprsLen = exprs.length;
const writes = get(section);
appendLiteral(writes, strs[0]);
for (let i = 0; i < exprsLen; i++) writes.push(exprs[i], strs[i + 1]);
};
}
function consumeHTML(path) {
const section = getSection(path);
const writes = getWrites(section);
const trailers = getTrailerWrites(section);
const writeResult = normalizeStringExpression(writes.map(unwrapWrite));
const trailerResult = normalizeStringExpression(trailers);
writes.length = 0;
writes[0] = "";
trailers.length = 0;
trailers[0] = "";
if (writeResult && trailerResult) return _marko_compiler.types.expressionStatement(_marko_compiler.types.sequenceExpression([callRuntime("_html", writeResult), callRuntime("_trailers", trailerResult)]));
else if (writeResult) return _marko_compiler.types.expressionStatement(callRuntime("_html", writeResult));
else if (trailerResult) return _marko_compiler.types.expressionStatement(callRuntime("_trailers", trailerResult));
}
function flushBefore(path) {
const expr = consumeHTML(path);
if (expr) path.insertBefore(expr)[0].skip();
}
function flushInto(path) {
const target = path.isProgram() ? path : path.get("body");
const expr = consumeHTML(target);
if (expr) target.node.body.push(expr);
}
function markNode(path, nodeBinding, reason, deferred) {
if (nodeBinding.type !== 0) throw path.buildCodeFrameError("POTENTIAL MARKO BUG: Tried to mark a node that was not determined to need a mark during analyze.");
if (isOutputHTML()) {
if (reason) {
const section = getSection(path);
writeTo$1(path, deferred)`${callRuntime("_el_resume", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeBinding), getSerializeGuard(section, reason, true))}`;
}
}
}
function unwrapWrite(write) {
return typeof write === "function" ? write() || "" : write;
}
//#endregion
//#region src/translator/core/return.ts
const [getSectionReturnValueIdentifier, setReturnValueIdentifier] = createSectionState("returnValue");
var return_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
(0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, ["value", "valueChange"]);
let valueAttr;
let valueChangeAttr;
for (const attr of tag.node.attributes) if (_marko_compiler.types.isMarkoAttribute(attr)) {
if (attr.name === "value") {
if (valueAttr) throw tag.hub.buildError(attr, "Invalid duplicate value attribute.");
valueAttr = attr;
} else if (attr.name === "valueChange") {
if (valueChangeAttr) throw tag.hub.buildError(attr, "Invalid duplicate valueChange attribute.");
valueChangeAttr = attr;
}
}
const parentTag = getParentTag(tag);
if (parentTag) {
if ((0, _marko_compiler_babel_utils.isNativeTag)(parentTag)) throw tag.get("name").buildCodeFrameError("The [`<return>` tag](https://markojs.com/docs/reference/core-tag#return) can not be used in a [native tag](https://markojs.com/docs/reference/native-tag).");
else if (isControlFlowTag(parentTag)) throw tag.get("name").buildCodeFrameError(`The [\`<return>\` tag](https://markojs.com/docs/reference/core-tag#return) can not be used under the \`<${parentTag.get("name").toString()}>\` tag.`);
}
const section = getOrCreateSection(tag);
if (section.returnValueExpr) throw tag.get("name").buildCodeFrameError(`Cannot have multiple [\`<return>\` tags](https://markojs.com/docs/reference/core-tag#return) ${tag.parent.type === "Program" ? "for the template" : "within a tag's body content"}.`);
const attrs = getKnownAttrValues(tag.node);
if (!attrs.value) throw tag.get("name").buildCodeFrameError("The [`<return>` tag](https://markojs.com/docs/reference/core-tag#return) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
if (attrs.valueChange) {
(attrs.valueChange.extra ??= {}).isEffect = true;
addSetupExpr(section, attrs.valueChange);
addSerializeReason(section, true, getAccessorProp().TagVariableChange);
}
addSetupExpr(section, attrs.value);
section.returnValueExpr = attrs.value.extra ??= {};
},
translate: translateByTarget({
html: { exit(tag) {
const section = getSection(tag);
const attrs = getKnownAttrValues(tag.node);
flushBefore(tag);
if (attrs.valueChange) setSectionSerializedValue(section, getAccessorProp().TagVariableChange, _marko_compiler.types.logicalExpression("||", attrs.valueChange, _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0))));
if (attrs.value) {
const returnId = generateUidIdentifier("return");
setReturnValueIdentifier(section, returnId);
tag.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(returnId, attrs.value)]))[0].skip();
}
} },
dom: { exit(tag) {
const section = getSection(tag);
const attrs = getKnownAttrValues(tag.node);
if (attrs.value) addStatement("render", section, attrs.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_return", scopeIdentifier, attrs.value)));
if (attrs.valueChange) addStatement("render", section, attrs.valueChange.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_return_change", scopeIdentifier, attrs.valueChange)));
tag.remove();
} }
}),
parseOptions: { openTagOnly: true },
autocomplete: [{
displayText: "return=<value>",
description: "Provides a value for use in a parent template.",
snippet: "return=${1:value}",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#return"
}]
};
//#endregion
//#region src/translator/util/for-each-identifier.ts
function forEachIdentifier(node, cb) {
switch (node.type) {
case "ObjectPattern":
for (const prop of node.properties) switch (prop.type) {
case "ObjectProperty":
if (prop.value.type === "AssignmentPattern") forEachIdentifier(prop.value.left, cb);
else forEachIdentifier(prop.value, cb);
break;
case "RestElement":
forEachIdentifier(prop.argument, cb);
break;
}
break;
case "ArrayPattern":
for (const el of node.elements) if (el != null) switch (el.type) {
case "RestElement":
forEachIdentifier(el.argument, cb);
break;
case "AssignmentPattern":
forEachIdentifier(el.left, cb);
break;
default:
forEachIdentifier(el, cb);
break;
}
break;
case "Identifier":
cb(node);
break;
}
}
function forEachIdentifierPath(nodePath, cb) {
if (nodePath.isIdentifier()) cb(nodePath);
else if (nodePath.isObjectPattern()) {
for (const prop of nodePath.get("properties")) if (prop.isObjectProperty()) {
const value = prop.get("value");
if (value.isAssignmentPattern()) forEachIdentifierPath(value.get("left"), cb);
else forEachIdentifierPath(value, cb);
} else if (prop.isRestElement()) forEachIdentifierPath(prop.get("argument"), cb);
} else if (nodePath.isArrayPattern()) {
for (const el of nodePath.get("elements")) if (el) if (el.isRestElement()) forEachIdentifierPath(el.get("argument"), cb);
else if (el.isAssignmentPattern()) forEachIdentifierPath(el.get("left"), cb);
else forEachIdentifierPath(el, cb);
}
}
//#endregion
//#region src/translator/util/for-selector.ts
const forSelectorsBySection = /* @__PURE__ */ new WeakMap();
const forSelectorValues = /* @__PURE__ */ new WeakSet();
function getForSelectorKey(bodySection, closure) {
const selectors = forSelectorsBySection.get(bodySection);
if (selectors?.closures.has(getCanonicalBinding(closure))) return selectors.keyBinding;
}
function isForSelectorValue(binding) {
return forSelectorValues.has(binding);
}
function detectForSelector(bodySection, keyBinding) {
let closures;
for (const expr of keyBinding.reads) {
if (expr.section !== bodySection) continue;
forEach(expr.referencedBindings, (closure) => {
const canonical = getCanonicalBinding(closure);
if (closure.type !== 6 && isDirectClosure(bodySection, closure) && !closures?.has(canonical) && onlyComparesKey(closure, canonical, bodySection, keyBinding)) {
(closures ||= /* @__PURE__ */ new Set()).add(canonical);
forSelectorValues.add(closure);
}
});
}
if (closures) forSelectorsBySection.set(bodySection, {
keyBinding,
closures
});
}
function onlyComparesKey(closure, canonical, bodySection, keyBinding) {
let found = false;
const keyReads = /* @__PURE__ */ new Map();
for (let chain = closure; chain; chain = chain.upstreamAlias) for (const expr of chain.reads) {
if (expr.section !== bodySection) continue;
let other = false;
forEach(getExpressionReads(expr), (read) => {
const resolved = read.extra.read;
const at = resolved && resolvesTo(resolved, canonical);
if (!at) return;
const keyRead = read.comparedTo?.extra?.read;
if (at === 2 || resolved.getter || !readsKey(keyRead, keyBinding)) other = true;
else {
found = true;
if (keyRead && !keyRead.props && getCanonicalBinding(keyRead.binding) === getCanonicalBinding(keyBinding)) keyReads.set(expr, bindingUtil.add(keyReads.get(expr), keyRead.binding));
}
});
if (other) return false;
}
if (found) for (const [expr, dropped] of keyReads) dropKeyReferences(expr, dropped);
return found;
}
function dropKeyReferences(expr, dropped) {
if (dropReferencedBindings(expr, dropped)) forEach(dropped, (binding) => {
binding.forcePersist = true;
});
}
function resolvesTo(read, canonical) {
let binding = read.binding;
let through = 0;
forEach(read.props, (prop) => {
if (binding) {
if (getCanonicalBinding(binding) === canonical) through = 2;
binding = binding.propertyAliases.get(prop);
}
});
return binding && getCanonicalBinding(binding) === canonical ? 1 : through;
}
function readsKey(read, keyBinding) {
if (!read || read.getter) return false;
let binding = read.binding;
forEach(read.props, (prop) => {
binding = binding?.propertyAliases.get(prop);
});
return !!binding && getCanonicalBinding(binding) === getCanonicalBinding(keyBinding);
}
//#endregion
//#region src/translator/util/to-property-name.ts
function getMemberExpressionPropString(expr) {
switch (expr.property.type) {
case "StringLiteral": return expr.property.value;
case "NumericLiteral": return "" + expr.property.value;
case "Identifier":
if (expr.computed) return;
return expr.property.name;
}
}
function isValidPropertyIdentifier(name) {
return /^[a-z_$][a-z0-9_$]*$/i.test(name);
}
function toPropertyName(name) {
if (isValidPropertyIdentifier(name)) return _marko_compiler.types.identifier(name);
else if (/^(?:0|[1-9][0-9]*)$/.test(name)) return _marko_compiler.types.numericLiteral(parseInt(name, 10));
return _marko_compiler.types.stringLiteral(name);
}
function toObjectProperty(name, value) {
return _marko_compiler.types.objectProperty(toPropertyName(name), value);
}
function toMemberExpression(object, key, optional) {
const prop = toPropertyName(key);
const computed = prop.type !== "Identifier";
return optional ? _marko_compiler.types.optionalMemberExpression(object, prop, computed, true) : _marko_compiler.types.memberExpression(object, prop, computed);
}
//#endregion
//#region src/translator/util/get-declared-binding-expression.ts
function getDeclaredBindingExpression(binding) {
const canonicalBinding = getCanonicalBinding(binding);
if (canonicalBinding.declared || !canonicalBinding.upstreamAlias || canonicalBinding.excludeProperties !== void 0) return _marko_compiler.types.identifier(canonicalBinding.name);
else if (canonicalBinding.property !== void 0) return toMemberExpression(getDeclaredBindingExpression(canonicalBinding.upstreamAlias), canonicalBinding.property, canonicalBinding.upstreamAlias.nullable);
else return getDeclaredBindingExpression(canonicalBinding.upstreamAlias);
}
//#endregion
//#region src/translator/util/scope-read.ts
function getScopeExpression(section, targetSection) {
let scope = scopeIdentifier ?? _marko_compiler.types.identifier("undefined");
const diff = section.depth - targetSection.depth;
for (let i = 0; i < diff; i++) scope = _marko_compiler.types.memberExpression(scope, _marko_compiler.types.identifier(getAccessorProp().Owner));
if (diff < 0) throw new Error("Unable to find scope for reference.");
return scope;
}
function createScopeReadExpression(reference, section = reference.section) {
const propName = toPropertyName(getScopeAccessor(reference));
const expr = _marko_compiler.types.memberExpression(reference.type === 4 ? scopeIdentifier : getScopeExpression(section, reference.section), propName, propName.type !== "Identifier");
if (section === reference.section && reference.type !== 0) {
const exprExtra = expr.extra ??= {};
exprExtra.read = createRead(reference, void 0);
exprExtra.section = section;
}
return expr;
}
//#endregion
//#region src/translator/util/simplify-fn.ts
/**
* Given any arbitrary function type will normalize method like functions into expressions.
*/
function simplifyFunction(fn) {
switch (fn.type) {
case "FunctionDeclaration":
case "FunctionExpression":
case "ArrowFunctionExpression": return fn;
default: return _marko_compiler.types.functionExpression(null, fn.params, fn.body, fn.generator, fn.async);
}
}
//#endregion
//#region src/translator/util/to-first-expression-or-block.ts
function toFirstExpressionOrBlock(stmts) {
if (stmts.length === 1 && _marko_compiler.types.isExpressionStatement(stmts[0])) return stmts[0].expression;
return _marko_compiler.types.blockStatement(stmts);
}
//#endregion
//#region src/translator/util/signals.ts
const [getSignals] = createSectionState("signals", () => /* @__PURE__ */ new Map());
const [getClosureSignalBuilder, _setClosureSignalBuilder] = createSectionState("queue");
function setClosureSignalBuilder(tag, builder) {
_setClosureSignalBuilder(getSectionForBody(tag.get("body")), builder);
}
const [getTryHasPlaceholder, setTryHasPlaceholder] = createSectionState("tryWithPlaceholder");
const [getOwnerResumedByMarker, setOwnerResumedByMarker] = createSectionState("ownerResumedByMarker");
function setSectionOwnerResumedByMarker(section) {
setOwnerResumedByMarker(section, true);
}
const [getSerializedAccessors] = createSectionState("serializedScopeProperties", () => /* @__PURE__ */ new Map());
function setSectionSerializedValue(section, prop, expression) {
const reason = getSerializeReason(section, prop);
if (reason) getSerializedAccessors(section).set(prop, {
expression,
reason
});
}
function setBindingSerializedValue(section, binding, expression, prefix) {
const reason = getSerializeReason(section, binding, prefix);
if (reason) if (prefix === void 0) getSerializedAccessors(section).set(getScopeAccessor(binding), {
expression,
reason
});
else {
const accessor = getPrefixedScopeAccessor(binding, prefix);
getSerializedAccessors(section).set(accessor, {
expression,
reason
});
if (!isOptimize() && prefix === getAccessorPrefix().TagVariableChange) {
const { root, access } = getDebugScopeAccess(binding);
setSectionDebugVar(section, accessor, `${root.name + access}Change`, root.loc);
}
}
}
const [getSectionDebugVars] = createSectionState("sectionDebugVars", () => /* @__PURE__ */ new Map());
function setSectionDebugVar(section, accessor, name, loc) {
if (!isOptimize()) getSectionDebugVars(section).set(accessor, loc ? [name, `${loc.start.line}:${loc.start.column + 1}`] : [name]);
}
const nonAnalyzedForceSerializedSection = /* @__PURE__ */ new WeakSet();
function setSerializedValue(section, key, expression) {
nonAnalyzedForceSerializedSection.add(section);
getSerializedAccessors(section).set(key, {
expression,
reason: true
});
}
const [getSectionWriteScopeBuilder, setSectionWriteScopeBuilder] = createSectionState("sectionWriteScopeBuilder");
function addWriteScopeBuilder(section, builder) {
const prev = getSectionWriteScopeBuilder(section);
setSectionWriteScopeBuilder(section, prev ? (expr) => builder(prev(expr)) : builder);
}
const htmlDynamicClosureInstancesIdentifier = /* @__PURE__ */ new WeakMap();
const [getHTMLSectionStatements] = createSectionState("htmlScopeStatements", () => []);
const [getBindingGetterIdMap] = createSectionState("bindingGetterIdMap", () => /* @__PURE__ */ new Map());
function getBindingGetterIdentifier(binding, getterSection) {
const section = getterSection || binding.section;
const idsMap = getBindingGetterIdMap(section);
let identifier = idsMap.get(binding);
if (!identifier) idsMap.set(binding, identifier = generateUidIdentifier(`${section.name ? `${section.name}__` : ""}${binding.originalName ?? binding.name}_getter`));
return identifier;
}
function getSignal(section, referencedBindings, name) {
if (referencedBindings && !Array.isArray(referencedBindings)) {
if (referencedBindings.type === 6) return getSignal(section, void 0);
if (referencedBindings.type !== 4 && referencedBindings.section !== section) {
const canonicalReference = getCanonicalBinding(referencedBindings);
if (canonicalReference !== referencedBindings) return getSignal(section, canonicalReference);
}
}
const signals = getSignals(section);
let signal = signals.get(referencedBindings);
if (!signal) {
const signalName = name ?? (referencedBindings ? getDebugNamesAsIdentifier(referencedBindings) : "setup");
const exportName = referencedBindings ? !Array.isArray(referencedBindings) && referencedBindings.section === section && referencedBindings.export : !section.parent && (0, _marko_compiler_babel_utils.getProgram)().node.extra.domExports?.setup;
signals.set(referencedBindings, signal = {
identifier: exportName ? _marko_compiler.types.identifier(exportName) : generateUidIdentifier(section.name ? `${section.name}__${signalName}` : signalName),
referencedBindings,
section,
values: [],
intersection: void 0,
forwards: void 0,
prepare: [],
render: [],
effect: [],
hasHTMLEffect: false,
build: void 0,
export: !!exportName,
hasSideEffect: !!(referencedBindings && (Array.isArray(referencedBindings) || referencedBindings.type === 0 || referencedBindings.type === 1 || referencedBindings.section !== section || referencedBindings.closureSections || referencedBindings.hoists)),
forcePersist: false,
inline: void 0,
extraArgs: void 0,
prependStatements: void 0,
buildAssignment: void 0
});
if (isOutputHTML()) return signal;
else if (!referencedBindings) signal.build = () => getSignalFn(signal);
else if (Array.isArray(referencedBindings)) {
const collapseSource = collapsedIntersectionSource.get(referencedBindings);
subscribe(collapseSource || referencedBindings, signal);
if (collapseSource) {
const sourceSignal = getSignal(section, collapseSource);
forEach(referencedBindings, (member) => {
const memberSignal = getSignal(section, member);
const inline = member.type === 5 && !member.upstreamAlias && member.reads.size === 1 && sourceSignal.values.find((v) => v.signal === memberSignal);
if (inline) memberSignal.inline = inline;
else memberSignal.hasSideEffect = memberSignal.forcePersist = true;
});
signal.build = () => getSignalFn(signal);
} else signal.build = () => {
const { id, scopeOffset } = intersectionMeta.get(referencedBindings);
return callRuntime("_or", _marko_compiler.types.numericLiteral(id), getSignalFn(signal), scopeOffset || referencedBindings.length > 2 ? _marko_compiler.types.numericLiteral(referencedBindings.length - 1) : void 0, scopeOffset && getScopeAccessorLiteral(scopeOffset, true));
};
} else if (referencedBindings.section !== section && sectionUtil.has(referencedBindings.closureSections, section)) signal.build = () => {
const closure = referencedBindings;
const render = getSignalFn(signal);
const closureSignalBuilder = getClosureSignalBuilder(section);
if (closureSignalBuilder && !isDynamicClosure(section, closure)) return closureSignalBuilder(closure, render);
return callRuntime("_closure_get", isOptimize() ? _marko_compiler.types.numericLiteral(getClosureAccessorId(closure)) : getScopeAccessorLiteral(closure, true), render, isImmediateOwner(section, closure) ? void 0 : _marko_compiler.types.arrowFunctionExpression([scopeIdentifier], getScopeExpression(section, closure.section)), underTryPlaceholder(section) ? _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "pending")) : void 0);
};
}
return signal;
}
function underTryPlaceholder(section) {
let curSection = section.parent;
while (curSection) {
if (getTryHasPlaceholder(curSection)) return true;
curSection = curSection.parent;
}
return false;
}
function initValue(binding, isLet = false) {
const section = binding.section;
const signal = getSignal(section, binding);
if (binding.forcePersist) signal.forcePersist = true;
signal.build = () => {
if (isPureMemberForwarder(binding)) return;
const fn = getSignalFn(signal);
const isDirectAlias = binding.upstreamAlias && binding.property === void 0 && binding.excludeProperties === void 0;
if (!signal.forcePersist && (isDirectAlias || !signal.hasSideEffect || !signalHasStatements(signal))) return fn;
return callRuntime(isLet ? signal.extraArgs ? "_let_change" : "_let" : "_const", getScopeAccessorLiteral(binding, true, isLet), fn);
};
for (const alias of binding.aliases) if (alias.type !== 6) initValue(alias);
for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) initValue(alias);
return signal;
}
function signalHasStatements(signal) {
if (signal.extraArgs || signal.forcePersist || signal.prepare.length || signal.render.length || signal.effect.length || signal.hasHTMLEffect || signal.values.length || signal.intersection) return true;
const binding = signal.referencedBindings;
if (binding) {
if (!Array.isArray(binding) && (binding.closureSections || binding.type === 0 || binding.section === signal.section && (binding.hoists || binding.aliases.size || hasNonConstantPropertyAlias(binding)))) return true;
} else if (signal.section.referencedClosures) return true;
return false;
}
function isPureMemberForwarder(binding) {
if (binding.property === void 0 || binding.reads.size || binding.exposed || binding.aliases.size || binding.assignmentSections || isForSelectorValue(binding) || getSerializeReason(binding.section, binding) || getSignal(binding.section, binding).hasSideEffect) return false;
for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
return false;
}
function pushMemberForwards(signal, value, alias) {
if (isPureMemberForwarder(alias)) {
for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(signal, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
} else {
const aliasSignal = getSignal(alias.section, alias);
signal.forwards = push(signal.forwards, aliasSignal);
signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
scopeIdentifier,
value,
...getTranslatedExtraArgs(aliasSignal)
])));
}
}
function getSignalFn(signal) {
const section = signal.section;
const binding = signal.referencedBindings;
const isValue = binding && !Array.isArray(binding) && binding.section === section;
const assertsHoists = isValue && binding.hoists && !isOptimize();
if (isValue) {
for (const alias of binding.aliases) {
const aliasSignal = getSignal(alias.section, alias);
if (signalHasStatements(aliasSignal)) {
signal.forwards = push(signal.forwards, aliasSignal);
if (alias.excludeProperties !== void 0) {
const aliasId = _marko_compiler.types.identifier(alias.name);
let pattern;
if (alias.restOffset) pattern = _marko_compiler.types.arrayPattern(new Array(alias.restOffset).fill(null).concat(_marko_compiler.types.restElement(aliasId)));
else {
const props = [];
forEach(alias.excludeProperties, (name) => {
const propId = toPropertyName(name);
const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
});
props.push(_marko_compiler.types.restElement(aliasId));
pattern = _marko_compiler.types.objectPattern(props);
}
signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([pattern], _marko_compiler.types.callExpression(aliasSignal.identifier, [
scopeIdentifier,
aliasId,
...getTranslatedExtraArgs(aliasSignal)
])), [binding.nullable ? _marko_compiler.types.logicalExpression("||", createScopeReadExpression(binding), alias.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : createScopeReadExpression(binding)])));
} else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
scopeIdentifier,
createScopeReadExpression(binding),
...getTranslatedExtraArgs(aliasSignal)
])));
}
}
for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
if (assertsHoists) signal.render.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", createScopeReadExpression(binding))));
}
for (const value of signal.values) {
if (value.signal.inline) continue;
if (signalHasStatements(value.signal)) {
const invocation = _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value.signal.identifier, [
scopeIdentifier,
value.value,
...getTranslatedExtraArgs(value.signal)
]));
signal.render.push(invocation);
} else signal.render.push(_marko_compiler.types.expressionStatement(withLeadingComment(value.value, getDebugNames(value.signal.referencedBindings))));
}
forEach(signal.intersection, (intersection) => {
signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(intersection.identifier, [scopeIdentifier])));
});
if (isValue && binding.sources) {
let dynamicClosureArgs;
let dynamicClosureSignalIdentifier;
forEach(binding.closureSections, (closureSection) => {
if (isDynamicClosure(closureSection, binding)) {
if (!dynamicClosureArgs) {
dynamicClosureArgs = [];
dynamicClosureSignalIdentifier = generateUidIdentifier(signal.identifier.name + "__closure");
signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(dynamicClosureSignalIdentifier, [scopeIdentifier])));
}
dynamicClosureArgs.push(getSignal(closureSection, binding).identifier);
} else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(getSignal(closureSection, binding).identifier, [scopeIdentifier])));
});
if (dynamicClosureSignalIdentifier) (signal.prependStatements ||= []).push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(dynamicClosureSignalIdentifier, callRuntime("_closure", ...dynamicClosureArgs))]));
}
if (signal.effect.length) {
const effectIdentifier = _marko_compiler.types.identifier(`${signal.identifier.name}__script`);
signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(effectIdentifier, [scopeIdentifier])));
}
if (isValue && getSerializeReason(section, binding)) signal.hasSideEffect = true;
const render = signal.prepare.length ? signal.prepare.concat(signal.render) : signal.render;
if (!signal.hasSideEffect) {
if (isValue && render.length === 1) {
const first = render[0];
if (first.type === "ExpressionStatement") {
const { expression } = first;
if (expression.type === "CallExpression" && expression.callee.type === "Identifier" && expression.arguments.length === 2 && expression.arguments[0] === scopeIdentifier && isOwnValueRead(expression.arguments[1], binding)) return expression.callee;
}
}
return _marko_compiler.types.arrowFunctionExpression(isValue ? [scopeIdentifier, getSignalValueIdentifier(signal)] : [scopeIdentifier], toFirstExpressionOrBlock(render));
}
if (render.length === 1) {
const first = render[0];
if (first.type === "ExpressionStatement") {
const { expression } = first;
if (expression.type === "CallExpression") {
const args = expression.arguments;
if (args.length === 1 && args[0] === scopeIdentifier) {
if (expression.callee.type === "MemberExpression" && expression.callee.property.type === "Identifier" && expression.callee.property.name === getAccessorProp().Owner) return expression.callee.object;
return expression.callee;
}
}
}
}
return _marko_compiler.types.arrowFunctionExpression([scopeIdentifier], _marko_compiler.types.blockStatement(render));
}
const hasTranslatedExtraArgs = /* @__PURE__ */ new WeakSet();
const emptyExtraArgs = [];
function getTranslatedExtraArgs(signal) {
if (signal.extraArgs) {
if (!hasTranslatedExtraArgs.has(signal)) {
hasTranslatedExtraArgs.add(signal);
traverseReplace(signal, "extraArgs", replaceRenderNode);
}
return signal.extraArgs;
}
return emptyExtraArgs;
}
function getSignalValueIdentifier(signal) {
const canonicalBinding = getCanonicalBinding(signal.referencedBindings);
return _marko_compiler.types.identifier(canonicalBinding.name);
}
function isOwnValueRead(node, binding) {
const extra = node.extra;
const read = extra?.read;
return !!read && !extra.assignment && read.binding === binding && read.props === void 0 && !read.getter?.invoked;
}
function subscribe(references, subscriber) {
if (references) forEach(references, (binding) => {
if (binding.type !== 6) {
const source = binding.property === void 0 && binding.excludeProperties === void 0 && binding.upstreamAlias || binding;
const providerSignal = getSignal(subscriber.section, source);
providerSignal.hasSideEffect = true;
providerSignal.intersection = push(providerSignal.intersection, subscriber);
}
});
}
function replaceNullishAndEmptyFunctionsWith0(args) {
const len = args.length;
let finalLen = void 0;
for (let i = len; i--;) {
const arg = args[i];
if (!arg) {
args[i] = _marko_compiler.types.numericLiteral(0);
continue;
}
if (_marko_compiler.types.isNullLiteral(arg) || _marko_compiler.types.isUnaryExpression(arg) && arg.operator === "void") {
args[i] = _marko_compiler.types.numericLiteral(0);
continue;
}
if (_marko_compiler.types.isArrowFunctionExpression(arg) && _marko_compiler.types.isBlockStatement(arg.body)) {
const body = arg.body.body;
if (body.length === 0) {
args[i] = _marko_compiler.types.numericLiteral(0);
continue;
}
if (body.length === 1 && _marko_compiler.types.isExpressionStatement(body[0])) arg.body = body[0].expression;
}
if (finalLen === void 0) finalLen = i + 1;
}
args.length = finalLen || 0;
return args;
}
function addStatement(type, targetSection, referencedBindings, statement, isPure) {
const signal = getSignal(targetSection, referencedBindings);
const statements = signal[type] ??= [];
if (Array.isArray(statement)) statements.push(...statement);
else statements.push(statement);
if (!isPure || type === "effect") signal.hasSideEffect = true;
}
function addValue(targetSection, referencedBindings, signal, value) {
const parentSignal = getSignal(targetSection, referencedBindings);
parentSignal.values.push({
signal,
value
});
if (value.extra?.referencedBindingsInFunction) parentSignal.hasSideEffect = true;
}
function buildResumeRegisterKey(section, referencedBindings, type) {
let name = "";
if (referencedBindings) if (typeof referencedBindings === "string") name += `*${referencedBindings}`;
else if (Array.isArray(referencedBindings)) for (const ref of referencedBindings) name += `_${ref.name}#${ref.id}`;
else name += `_${referencedBindings.name}#${referencedBindings.id}`;
return `${section.id}${name}${type ? "/" + type : ""}`;
}
function getResumeRegisterId(section, referencedBindings, type) {
const { markoOpts, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
return (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename, buildResumeRegisterKey(section, referencedBindings, type));
}
function writeSignals(section) {
const seen = /* @__PURE__ */ new Set();
const written = /* @__PURE__ */ new Set();
writeGetters(section);
for (const signal of getSignals(section).values()) writeSignal(signal);
function writeSignal(signal) {
if (seen.has(signal)) return;
seen.add(signal);
for (const value of signal.values) {
writeSignal(value.signal);
traverseReplace(value, "value", replaceRenderNode);
}
forEach(signal.intersection, writeSignal);
let effectDeclarator;
if (signal.effect.length) {
traverseReplace(signal, "effect", replaceEffectNode);
const effectIdentifier = _marko_compiler.types.identifier(`${signal.identifier.name}__script`);
const effectFn = _marko_compiler.types.arrowFunctionExpression([scopeIdentifier], toFirstExpressionOrBlock(signal.effect));
effectDeclarator = _marko_compiler.types.variableDeclarator(effectIdentifier, callRuntime("_script", _marko_compiler.types.stringLiteral(getResumeRegisterId(section, signal.referencedBindings)), effectFn));
}
let signalDeclaration;
if (signal.build) {
let value = signal.build();
const buildsEagerForward = _marko_compiler.types.isIdentifier(value);
if (!value || !signal.register && !signal.referenced && _marko_compiler.types.isFunction(value) && _marko_compiler.types.isBlockStatement(value.body) && !value.body.body.length) return;
if (_marko_compiler.types.isCallExpression(value)) replaceNullishAndEmptyFunctionsWith0(value.arguments);
if (signal.register) value = callRuntime("_var_resume", _marko_compiler.types.stringLiteral(getResumeRegisterId(section, signal.referencedBindings, "var")), value);
if (buildsEagerForward) forEach(signal.forwards, writeSignal);
const signalDeclarator = _marko_compiler.types.variableDeclarator(signal.identifier, value);
signalDeclaration = !section.parent && !signal.referencedBindings && (_marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value)) ? _marko_compiler.types.functionDeclaration(signal.identifier, value.params, _marko_compiler.types.isExpression(value.body) ? _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(value.body)]) : value.body) : _marko_compiler.types.variableDeclaration("const", [signalDeclarator]);
if (signal.export) signalDeclaration = _marko_compiler.types.exportNamedDeclaration(signalDeclaration);
}
traverseReplace(signal, "render", replaceRenderNode, signal);
const signalStatements = signal.prependStatements || [];
if (effectDeclarator) signalStatements.push(_marko_compiler.types.variableDeclaration("const", [effectDeclarator]));
if (signalDeclaration) signalStatements.push(signalDeclaration);
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(...signalStatements);
written.add(signal);
}
return written;
}
function writeGetters(section) {
forEach(section.bindings, (binding) => {
for (const [hoistSection, hasReference] of binding.getters) {
const getterIdentifier = getBindingGetterIdentifier(binding, hoistSection);
const accessors = [getScopeAccessorLiteral(binding, true)];
if (hoistSection) {
let currentSection = binding.section;
while (currentSection && currentSection !== hoistSection) {
const parentSection = currentSection.parent;
if (parentSection) accessors.push(getSectionInstancesAccessorLiteral(currentSection));
currentSection = parentSection;
}
}
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(getterIdentifier, hoistSection ? hasReference ? callRuntime("_hoist_resume", _marko_compiler.types.stringLiteral(getResumeRegisterId(hoistSection, binding, "hoist")), ...accessors) : callRuntime("_hoist", ...accessors) : callRuntime("_el", _marko_compiler.types.stringLiteral(getResumeRegisterId(section, binding)), ...accessors))]));
}
});
}
function writeRegisteredFns() {
const registeredFns = registeredFnsForProgram.get((0, _marko_compiler_babel_utils.getProgram)().node);
const statements = [];
if (registeredFns) {
for (const registeredFn of registeredFns) {
let fn;
if (registeredFn.referencedBindings || registeredFn.referencesScope || registeredFn.referencedLocals) {
let params;
let prologue;
if (registeredFn.referencedLocals) {
params = [localsIdentifier];
if (registeredFn.referencedBindings || registeredFn.referencesScope) prologue = [_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(scopeIdentifier, _marko_compiler.types.memberExpression(localsIdentifier, _marko_compiler.types.identifier(getAccessorProp().Owner)))])];
} else params = [scopeIdentifier];
const body = toReturnedFunction(registeredFn.node, prologue);
fn = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(registeredFn.id), _marko_compiler.types.arrowFunctionExpression(params, body.length === 1 && body[0].type === "ReturnStatement" ? body[0].argument : _marko_compiler.types.blockStatement(body)))]);
} else if (registeredFn.node.type === "FunctionDeclaration" && registeredFn.node.id?.name === registeredFn.id) fn = registeredFn.node;
else fn = _marko_compiler.types.functionDeclaration(_marko_compiler.types.identifier(registeredFn.id), registeredFn.node.params, registeredFn.node.body.type === "BlockStatement" ? registeredFn.node.body : _marko_compiler.types.blockStatement([_marko_compiler.types.returnStatement(registeredFn.node.body)]), registeredFn.node.generator, registeredFn.node.async);
statements.push(fn);
}
for (const registeredFn of registeredFns) statements.push(_marko_compiler.types.expressionStatement(callRuntime("_resume", _marko_compiler.types.stringLiteral(registeredFn.registerId), _marko_compiler.types.identifier(registeredFn.id))));
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(...statements);
}
}
function toReturnedFunction(rawFn, prologue) {
const fn = simplifyFunction(rawFn);
if (prologue) {
if (fn.body.type !== "BlockStatement") fn.body = _marko_compiler.types.blockStatement([_marko_compiler.types.returnStatement(fn.body)]);
fn.body.body.unshift(...prologue);
}
return fn.type === "FunctionDeclaration" ? [fn, _marko_compiler.types.returnStatement(fn.id)] : [_marko_compiler.types.returnStatement(fn)];
}
function addHTMLEffectCall(section, referencedBindings) {
const signal = getSignal(section, referencedBindings);
signal.hasHTMLEffect = signal.hasSideEffect = true;
}
function writeHTMLResumeStatements(path) {
const section = getSectionForBody(path);
if (!section) return;
const body = path.node.body;
const allSignals = Array.from(getSignals(section).values());
const scopeIdIdentifier = getScopeIdIdentifier(section);
const markerSerializeArg = getSerializeGuardForAny(section, section.domSerializeReasons, true);
const sectionSerializeReason = nonAnalyzedForceSerializedSection.has(section) ? true : section.serializeReason;
forEach(section.referencedClosures, (closure) => {
if (closure.sources) {
if (isDynamicClosure(section, closure)) {
const closureSignal = getSignal(closure.section, closure);
let identifier = htmlDynamicClosureInstancesIdentifier.get(closureSignal);
if (!identifier) {
htmlDynamicClosureInstancesIdentifier.set(closureSignal, identifier = generateUidIdentifier(closureSignal.identifier.name + "__closures"));
getHTMLSectionStatements(closure.section).push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(identifier, _marko_compiler.types.newExpression(_marko_compiler.types.identifier("Set"), []))]));
setBindingSerializedValue(closure.section, closure, identifier, getAccessorPrefix().ClosureScopes);
}
const closureIndex = getDynamicClosureIndex(closure, section);
if (closureIndex) setBindingSerializedValue(section, closure, _marko_compiler.types.numericLiteral(closureIndex), getAccessorPrefix().ClosureSignalIndex);
const closureScopesReason = getSerializeReason(closure.section, closure, getAccessorPrefix().ClosureScopes);
if (underTryPlaceholder(section)) {
const reason = getSerializeReason(section);
if (reason) {
const script = getExprIfSerialized(section, reason, callRuntime("_script", getScopeIdIdentifier(section), _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "pending")), markerSerializeArg));
getHTMLSectionStatements(section).push(_marko_compiler.types.expressionStatement(isReasonDynamic(closureScopesReason) && !isSameReason(closureScopesReason, reason) ? getExprIfSerialized(closure.section, closureScopesReason, script) : script));
}
} else {
const subscribeArg = isReasonDynamic(closureScopesReason) && !isSameReason(closureScopesReason, sectionSerializeReason) ? getExprIfSerialized(closure.section, closureScopesReason, identifier) : identifier;
addWriteScopeBuilder(section, (expr) => callRuntime("_subscribe", subscribeArg, expr));
}
}
}
});
for (let i = allSignals.length; i--;) if (allSignals[i].hasHTMLEffect) {
const signalRefs = allSignals[i].referencedBindings;
body.push(_marko_compiler.types.expressionStatement(callRuntime("_script", scopeIdIdentifier, _marko_compiler.types.stringLiteral(getResumeRegisterId(section, signalRefs)), markerSerializeArg)));
}
const debug = !isOptimize();
const writeScopeBuilder = getSectionWriteScopeBuilder(section);
const serializedLookup = getSerializedAccessors(section);
const serializedProperties = [];
const ifSerialized = (reason, expr) => {
if (isSameReason(sectionSerializeReason, reason)) return expr;
return getExprIfSerialized(section, reason, expr);
};
let debugVars;
const writeSerializedBinding = (binding) => {
const reason = getSerializeReason(section, binding);
if (!reason) return;
if (binding.noSerialize) {
serializedLookup.delete(getScopeAccessor(binding));
return;
}
const accessor = getScopeAccessor(binding);
serializedLookup.delete(accessor);
let expr = getDeclaredBindingExpression(binding);
if (binding.noSerializeProperties) {
const props = [_marko_compiler.types.spreadElement(expr)];
forEach(binding.noSerializeProperties, (prop) => {
props.push(toObjectProperty(prop, _marko_compiler.types.identifier("undefined")));
});
expr = _marko_compiler.types.objectExpression(props);
}
serializedProperties.push(toObjectProperty(accessor, ifSerialized(reason, expr)));
if (debug) {
const { root, access } = getDebugScopeAccess(binding);
const locExpr = root.loc && _marko_compiler.types.stringLiteral(`${root.loc.start.line}:${root.loc.start.column + 1}`);
(debugVars ||= []).push(toObjectProperty(getScopeAccessor(binding), root !== binding ? _marko_compiler.types.arrayExpression(locExpr ? [_marko_compiler.types.stringLiteral(root.name + access), locExpr] : [_marko_compiler.types.stringLiteral(root.name + access)]) : locExpr || _marko_compiler.types.numericLiteral(0)));
}
};
forEach(section.bindings, (binding) => {
if (binding.type !== 0 && binding.type !== 4) writeSerializedBinding(binding);
});
forEach(section.referencedLocalClosures, writeSerializedBinding);
if (section.parent) {
const ownerAccessor = getAccessorProp().Owner;
const ownerReason = getSerializeReason(section, ownerAccessor);
if (ownerReason) {
serializedLookup.delete(ownerAccessor);
if (!getOwnerResumedByMarker(section)) serializedProperties.push(toObjectProperty(ownerAccessor, ifSerialized(ownerReason, callRuntime("_scope_with_id", getScopeIdIdentifier(section.parent)))));
}
}
for (const [key, { expression, reason }] of serializedLookup) serializedProperties.push(toObjectProperty(key, ifSerialized(reason, expression)));
if (sectionSerializeReason) {
for (const prop of serializedProperties) if (prop.key.type === "Identifier" && prop.value.type === "Identifier" && prop.key.name === prop.value.name) prop.shorthand = true;
const writeScopeArgs = [scopeIdIdentifier, _marko_compiler.types.objectExpression(serializedProperties)];
if (debug) {
writeScopeArgs.push(_marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.getFile)().opts.filenameRelative), section.loc && section.loc.start.line != null ? _marko_compiler.types.stringLiteral(`${section.loc.start.line}:${section.loc.start.column + 1}`) : _marko_compiler.types.numericLiteral(0));
for (const [accessor, varLoc] of getSectionDebugVars(section)) (debugVars ||= []).push(toObjectProperty(accessor, _marko_compiler.types.valueToNode(varLoc)));
if (debugVars) writeScopeArgs.push(_marko_compiler.types.objectExpression(debugVars));
}
body.push(_marko_compiler.types.expressionStatement(getExprIfSerialized(section, sectionSerializeReason, writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs))));
}
if (!section.isBranch && (section.hasAbortSignal || !!section.referencedClosures || sectionSerializeReason && !!find(section.bindings, (binding) => binding.type === 1)) && markerSerializeArg) {
const call = callRuntime("_resume_branch", scopeIdIdentifier);
const link = section.hasAbortSignal ? call : getExprIfSerialized(section, sectionSerializeReason, call);
if (link) body.push(_marko_compiler.types.expressionStatement(markerSerializeArg.type === "NumericLiteral" ? link : _marko_compiler.types.logicalExpression("||", markerSerializeArg, link)));
}
const additionalStatements = getHTMLSectionStatements(section);
if (body.length || additionalStatements.length) body.unshift(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(scopeIdIdentifier, callRuntime("_scope_id"))]), ...additionalStatements);
if (debug) forEach(section.bindings, (binding) => {
if (binding.hoists && binding.type !== 0) body.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", _marko_compiler.types.identifier(binding.name))));
});
const returnIdentifier = getSectionReturnValueIdentifier(section);
if (returnIdentifier !== void 0) body.push(_marko_compiler.types.returnStatement(returnIdentifier));
}
function getSetup(section) {
return section.hoistedTo ? getSignal(section, void 0) : getSignals(section).get(void 0);
}
function replaceRenderNode(node, signal) {
return replaceAssignedNode(node) || replaceBindingReadNode$1(node, signal) || replaceRegisteredFunctionNode$1(node);
}
function replaceEffectNode(node) {
return replaceAssignedNode(node) || replaceBindingReadNode$1(node);
}
function replaceBindingReadNode$1(node, signal) {
switch (node.type) {
case "Identifier":
case "MemberExpression":
case "OptionalMemberExpression": return getReadReplacement(node, signal);
case "CallExpression": {
const { extra } = node.callee;
if (extra?.read) {
const { binding, getter } = extra.read;
if (binding.type === 0 && !getter) {
const replacement = createScopeReadExpression(binding, extra.section);
return isOptimize() ? replacement : callRuntime("_el_read", replacement);
} else if (getter?.hoisted) node.callee = _marko_compiler.types.callExpression(getBindingGetterIdentifier(binding, getter.hoisted), [getScopeExpression(extra.section, getter.hoisted)]);
}
break;
}
}
}
const updateExpressions = /* @__PURE__ */ new WeakSet();
function replaceAssignedNode(node) {
switch (node.type) {
case "ExpressionStatement":
if (node.expression.type === "BinaryExpression" && updateExpressions.delete(node.expression)) node.expression = node.expression.left;
if (node.expression.type === "CallExpression" && updateExpressions.delete(node.expression)) {
node.expression.callee = node.expression.arguments[0];
node.expression.arguments = [node.expression.arguments[1]];
}
break;
case "UpdateExpression": {
const { extra } = node.argument;
if (isAssignedBindingExtra(extra)) {
let builtAssignment = getBuildAssignment(extra)?.(extra.section, _marko_compiler.types.binaryExpression(node.operator === "++" ? "+" : "-", _marko_compiler.types.unaryExpression("+", createScopeReadExpression(extra.assignment, extra.section)), _marko_compiler.types.numericLiteral(1)));
if (builtAssignment) {
if (!node.prefix) {
builtAssignment = _marko_compiler.types.binaryExpression(node.operator === "++" ? "-" : "+", builtAssignment, _marko_compiler.types.numericLiteral(1));
updateExpressions.add(builtAssignment);
}
return builtAssignment;
}
}
break;
}
case "AssignmentExpression":
switch (node.left.type) {
case "Identifier": {
const { extra } = node.left;
if (isAssignedBindingExtra(extra)) {
const { operator } = node;
const shortCircuits = operator === "||=" || operator === "&&=" || operator === "??=";
const readAssigned = () => createScopeReadExpression(extra.assignment, extra.section);
const builtAssignment = getBuildAssignment(extra)?.(extra.section, operator === "=" || shortCircuits ? node.right : _marko_compiler.types.binaryExpression(operator.slice(0, -1), readAssigned(), node.right));
if (builtAssignment) return shortCircuits ? _marko_compiler.types.logicalExpression(operator.slice(0, -1), readAssigned(), builtAssignment) : builtAssignment;
}
return extra?.assignment && withLeadingComment(node.right, getDebugName(extra.assignment));
}
case "ArrayPattern":
case "ObjectPattern": {
let params;
let assignments;
forEachIdentifier(node.left, (id) => {
const { extra } = id;
if (isAssignedBindingExtra(extra)) {
const buildAssignment = getBuildAssignment(extra);
if (buildAssignment) {
const uid = generateUid(id.name);
const builtAssignment = buildAssignment(extra.section, _marko_compiler.types.identifier(uid));
if (builtAssignment) {
id.name = uid;
(params ||= []).push(_marko_compiler.types.identifier(uid));
(assignments ||= []).push(builtAssignment);
return;
}
}
}
if (extra?.assignment) (params ||= []).push(_marko_compiler.types.identifier(id.name));
});
if (assignments || params) {
const resultId = generateUid("result");
return _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier(resultId), ...params || []], _marko_compiler.types.sequenceExpression([
_marko_compiler.types.assignmentExpression("=", node.left, _marko_compiler.types.identifier(resultId)),
...assignments || [],
_marko_compiler.types.identifier(resultId)
])), [node.right]);
}
break;
}
}
break;
}
}
function getBuildAssignment(extra) {
const { assignmentTo, assignment } = extra;
if (assignmentTo) return (section, value) => {
let scopeRead;
if (assignmentTo.pruned) {
let cur = assignmentTo;
const props = [];
while (cur.pruned && cur.property !== void 0 && cur.upstreamAlias) {
props.push(cur.property);
cur = cur.upstreamAlias;
}
scopeRead = createScopeReadExpression(cur, section);
for (let i = props.length; i--;) scopeRead = toMemberExpression(scopeRead, props[i], false);
} else scopeRead = createScopeReadExpression(assignmentTo, section);
const replacement = callRuntime("_call", scopeRead, value);
updateExpressions.add(replacement);
return replacement;
};
return getSignal(assignment.section, assignment).buildAssignment;
}
const registeredFnsForProgram = /* @__PURE__ */ new WeakMap();
function replaceRegisteredFunctionNode$1(node) {
switch (node.type) {
case "ClassMethod": {
const replacement = getRegisteredFnExpression$1(node);
return replacement && _marko_compiler.types.classProperty(node.key, replacement, void 0, void 0, node.computed, node.static);
}
case "ClassPrivateMethod": {
const replacement = getRegisteredFnExpression$1(node);
return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement, void 0, node.static);
}
case "ObjectMethod": {
const replacement = getRegisteredFnExpression$1(node);
return replacement && _marko_compiler.types.objectProperty(node.key, replacement, node.computed);
}
case "ArrowFunctionExpression":
case "FunctionExpression": return getRegisteredFnExpression$1(node);
case "FunctionDeclaration": {
const replacement = getRegisteredFnExpression$1(node);
if (replacement) return _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.id, replacement)]);
break;
}
}
}
function getRegisteredFnExpression$1(node) {
const { extra } = node;
if (isRegisteredFnExtra(extra)) {
const id = extra.name;
const referencesScope = extra.referencesScope;
const referencedBindings = extra.referencedBindingsInFunction;
const referencedLocals = extra.referencedLocalBindingsInFunction;
let registeredFns = registeredFnsForProgram.get((0, _marko_compiler_babel_utils.getProgram)().node);
if (!registeredFns) registeredFnsForProgram.set((0, _marko_compiler_babel_utils.getProgram)().node, registeredFns = []);
registeredFns.push({
id,
node,
registerId: extra.registerId,
section: extra.section,
referencesScope,
referencedBindings,
referencedLocals
});
if (referencedLocals) {
const properties = [];
if (referencesScope || referencedBindings) properties.push(_marko_compiler.types.objectProperty(_marko_compiler.types.identifier(getAccessorProp().Owner), scopeIdentifier));
forEach(referencedLocals, (binding) => {
properties.push(toObjectProperty(getLocalsScopeAccessor(binding), getDeclaredBindingExpression(binding)));
});
return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(id), [_marko_compiler.types.objectExpression(properties)]);
} else if (referencesScope || referencedBindings) return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(id), [scopeIdentifier]);
else return _marko_compiler.types.identifier(id);
}
}
//#endregion
//#region src/translator/util/import-reference.ts
function importOrSelfReferenceName(file, request, name, nameHint) {
if (isCircularRequest(file, request)) return _marko_compiler.types.identifier(name);
return (0, _marko_compiler_babel_utils.importNamed)(file, request, name, nameHint);
}
function isCircularRequest(file, request) {
const { filename } = file.opts;
return request === filename || request[0] === "." && path.default.resolve(filename, "..", request) === filename;
}
//#endregion
//#region src/translator/util/structure.ts
const walkCodeToName = {
[32]: "get",
[37]: "replace",
[38]: "endChild",
[47]: "beginChild",
[48]: "beginChildWithVar",
[49]: "dynamicTagWithVar",
[67]: "next",
[97]: "over",
[107]: "out",
[117]: "multiplier",
[91]: "nextEnd",
[106]: "overEnd",
[116]: "outEnd",
[126]: "multiplierEnd"
};
function enter(path) {
getSection(path).structure?.push(0);
}
function exit(path) {
getSection(path).structure?.push(1);
}
function enterShallow(path) {
getSection(path).structure?.push(0, 1);
}
function child(tag, name, renderer) {
getSection(tag).structure?.push({
kind: Child,
name,
hasVar: !!tag.node.var,
renderer
});
}
function writeTo(path) {
const { structure } = getSection(path);
return (strs, ...exprs) => {
if (!structure) return;
const exprsLen = exprs.length;
pushMarkup(structure, strs[0]);
for (let i = 0; i < exprsLen; i++) {
pushMarkup(structure, exprs[i]);
pushMarkup(structure, strs[i + 1]);
}
};
}
function writeTextTo(path, value) {
if (value) getSection(path).structure?.push({
kind: Text,
value
});
}
function pushMarkup(structure, str) {
if (!str) return;
const last = structure.length - 1;
if (typeof structure[last] === "string") structure[last] += str;
else structure.push(str);
}
function visit(path, code, claimed = true) {
const { structure } = getSection(path);
if (!structure) return;
const op = {
kind: Visit,
code,
claimed
};
structure.push(op);
return op;
}
function resolveStructure(section) {
const startDynamic = section.content?.startType === 1;
const resolved = {
writes: [startDynamic ? "<!>" : ""],
walks: [""],
walkComment: [],
steps: startDynamic ? [0, 1] : []
};
let textEdge;
for (const op of section.structure) if (typeof op === "string") {
appendLiteral(resolved.writes, op);
textEdge = void 0;
} else if (typeof op === "number") resolved.steps.push(op);
else switch (op.kind) {
case Text:
if (textEdge === "child") separate(resolved);
appendLiteral(resolved.writes, op.value);
textEdge = "own";
break;
case Visit:
if (!op.claimed) continue;
flushSteps(resolved);
resolved.walkComment.push(walkCodeToName[op.code]);
appendLiteral(resolved.walks, String.fromCharCode(op.code));
if (op.code !== 32) {
appendLiteral(resolved.writes, "<!>");
textEdge = void 0;
}
break;
case Child: {
const content = refContent(op.renderer);
if (textEdge && content?.startType === 4) separate(resolved);
textEdge = content?.endType === 4 ? "child" : void 0;
flushSteps(resolved);
const template = op.renderer && resolveRef(op.renderer, "template");
if (template) resolved.writes.push(template, "");
resolved.walkComment.push(`<${op.name}${op.hasVar ? "/var" : ""}>`);
appendLiteral(resolved.walks, String.fromCharCode(op.hasVar ? 48 : 47));
const walks = op.renderer && resolveRef(op.renderer, "walks");
if (walks) resolved.walks.push(walks, "");
appendLiteral(resolved.walks, String.fromCharCode(38));
break;
}
}
if (section.content?.endType === 1) {
appendLiteral(resolved.writes, "<!>");
resolved.steps.push(0, 1);
}
flushSteps(resolved);
return resolved;
}
function separate(resolved) {
appendLiteral(resolved.writes, "<!>");
resolved.steps.push(0, 1);
}
function refContent(ref) {
return (ref && (ref.kind === "sectionRef" ? ref.section : ref.program.section))?.content;
}
function resolveRef(ref, part) {
if (ref.kind === "sectionRef") return getSectionMetaIdentifiers(ref.section)[part === "template" ? "writes" : "walks"];
const name = ref.program.domExports[part];
return ref.program.section === (0, _marko_compiler_babel_utils.getProgram)().node.extra.section ? _marko_compiler.types.identifier(name) : importOrSelfReferenceName((0, _marko_compiler_babel_utils.getFile)(), ref.path, name, `${ref.hint}_${part}`);
}
const [getSectionMeta] = createSectionState("SectionMeta", (section) => {
if (!section.structure) return {
walks: void 0,
writes: void 0,
decls: void 0
};
const { writes, walks, walkComment } = resolveStructure(section);
const walkLiteral = normalizeStringExpression(walks, true);
if (walkLiteral && walkLiteral.value !== "") withLeadingComment(walkLiteral, walkComment.join(", "));
return {
walks: walkLiteral,
writes: normalizeStringExpression(writes, true),
decls: void 0
};
});
const sectionMetaIsIds = /* @__PURE__ */ new WeakSet();
function getSectionMetaIdentifiers(section) {
const meta = getSectionMeta(section);
if (!sectionMetaIsIds.has(meta)) {
sectionMetaIsIds.add(meta);
const { walks, writes } = meta;
const decls = [];
if (walks) {
meta.walks = generateUidIdentifier(`${section.name}__walks`);
decls.push(_marko_compiler.types.variableDeclarator(meta.walks, walks));
}
if (writes) {
meta.writes = generateUidIdentifier(`${section.name}__template`);
decls.push(_marko_compiler.types.variableDeclarator(meta.writes, writes));
}
if (decls.length) meta.decls = decls;
}
return meta;
}
function flushSteps({ walks, walkComment, steps }) {
if (!steps.length) return;
const walkCodes = [];
let walkString = "";
let depth = 0;
for (const step of steps) if (step === 0) {
depth++;
walkCodes.push(67);
} else {
depth--;
if (depth >= 0) {
walkCodes.length = walkCodes.lastIndexOf(67);
walkCodes.push(97);
} else {
walkCodes.length = walkCodes.lastIndexOf(107) + 1;
walkCodes.push(107);
depth = 0;
}
}
let current = walkCodes[0];
let count = 0;
for (const walk of walkCodes) if (walk !== current) {
walkComment.push(`${walkCodeToName[current]}(${count})`);
walkString += nCodeString(current, count);
current = walk;
count = 1;
} else count++;
walkComment.push(`${walkCodeToName[current]}(${count})`);
walkString += nCodeString(current, count);
steps.length = 0;
appendLiteral(walks, walkString);
}
function nCodeString(code, number) {
switch (code) {
case 67: return toCharString(number, code, 25);
case 97: return toCharString(number, code, 10);
case 107: return toCharString(number, code, 10);
default: throw new Error(`Unexpected walk code: ${code}`);
}
}
function toCharString(number, startCode, rangeSize) {
let result = "";
if (number >= rangeSize) {
const multiplier = Math.floor(number / rangeSize);
result += toCharString(multiplier, 117, 10);
number -= multiplier * rangeSize;
}
result += String.fromCharCode(startCode + number);
return result;
}
/** `_content` strips trailing exit codes before it walks, so a renderer that
* reaches the runtime through it never needs them on the wire. */
function trimTrailingExits(walks) {
if (!_marko_compiler.types.isStringLiteral(walks)) return walks;
const value = walks.value.replace(/[^\0-1]+$/, "");
return value === walks.value ? walks : value ? withLeadingComment(_marko_compiler.types.stringLiteral(value), getComment(walks)) : void 0;
}
function getComment(node) {
return node.leadingComments?.[0]?.value.trim() || "";
}
//#endregion
//#region src/translator/visitors/program/dom.ts
var dom_default = { translate: {
enter(program) {
const section = getSectionForBody(program);
forEachSectionReverse((childSection) => {
if (childSection !== section) forEach(childSection.referencedClosures, (closure) => {
if (closure.type !== 6) {
const closureSignal = getSignal(childSection, closure);
if (signalHasStatements(closureSignal)) addStatement("render", childSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(isDynamicClosure(childSection, closure) ? closureSignal.identifier : _marko_compiler.types.memberExpression(closureSignal.identifier, _marko_compiler.types.identifier("_")), [scopeIdentifier])));
}
});
});
},
exit(program) {
forEachSectionReverse(getSectionMeta);
const section = getSectionForBody(program);
const { walks, writes, decls } = getSectionMeta(section);
const domExports = program.node.extra.domExports;
const templateIdentifier = _marko_compiler.types.identifier(domExports.template);
const walksIdentifier = _marko_compiler.types.identifier(domExports.walks);
const setupIdentifier = _marko_compiler.types.identifier(domExports.setup);
const inputBinding = program.node.params[0].extra?.binding;
const programInputSignal = inputBinding && !inputBinding.pruned ? initValue(inputBinding) : void 0;
let extraDecls = decls;
const styleFile = program.node.extra.styleFile;
if (styleFile) (0, _marko_compiler_babel_utils.importDefault)((0, _marko_compiler_babel_utils.getFile)(), styleFile);
forEachSectionReverse((childSection) => {
if (childSection !== section) {
const tagParamsSignal = childSection.params && initValue(childSection.params);
const tagParamsIdentifier = tagParamsSignal && signalHasStatements(tagParamsSignal) ? tagParamsSignal.identifier : void 0;
const { writes, decls } = getSectionMeta(childSection);
const walks = trimTrailingExits(getSectionMeta(childSection).walks);
const setup = getSetup(childSection);
const written = writeSignals(childSection);
const setupIdentifier = setup && written.has(setup) ? setup.identifier : void 0;
if (!isSectionRendererElided(childSection)) if (getSectionParentIsOwner(childSection)) setBranchRendererArgs(childSection, [
writes,
walks,
setupIdentifier,
tagParamsIdentifier
]);
else {
let renderer = callRuntime(getSectionRegisterReasons(childSection) ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(childSection, "content")), ...replaceNullishAndEmptyFunctionsWith0([
writes,
walks,
setupIdentifier,
tagParamsIdentifier,
childSection.hoisted || childSection.isHoistThrough ? getSectionInstancesAccessorLiteral(childSection) : void 0
]));
if (childSection.referencedLocalClosures) {
const objProps = [];
forEach(childSection.referencedLocalClosures, (closure) => {
const closureSignal = getSignal(childSection, closure);
const key = toPropertyName(getScopeAccessor(closure, true));
if (signalHasStatements(closureSignal)) {
const expr = getSignalFn(closureSignal);
if (_marko_compiler.types.isFunction(expr) && _marko_compiler.types.isBlockStatement(expr.body)) objProps.push(_marko_compiler.types.objectMethod("method", key, expr.params, expr.body));
else objProps.push(_marko_compiler.types.objectProperty(key, expr));
}
});
if (objProps.length) renderer = callRuntime("_content_closures", renderer, _marko_compiler.types.objectExpression(objProps));
}
program.node.body.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(childSection.name), renderer)]));
}
if (decls) extraDecls = extraDecls ? [...decls, ...extraDecls] : decls;
}
});
const written = writeSignals(section);
writeRegisteredFns();
const setup = getSetup(section);
if (domExports.setupEmpty && setup && written.has(setup)) throw program.buildCodeFrameError("Marko internal error: analysis marked this template's setup export as empty but translation produced statements for it. Please open an issue with a reproduction.");
if (!setup) program.node.body.unshift(_marko_compiler.types.exportNamedDeclaration(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(setupIdentifier, _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([])))])));
program.node.body.unshift(_marko_compiler.types.exportNamedDeclaration(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(templateIdentifier, writes || _marko_compiler.types.stringLiteral(""))])), _marko_compiler.types.exportNamedDeclaration(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(walksIdentifier, walks || _marko_compiler.types.stringLiteral(""))])));
if (extraDecls) program.node.body.unshift(_marko_compiler.types.variableDeclaration("const", extraDecls));
writeModuleRegistrations(program);
program.node.body.push(_marko_compiler.types.exportDefaultDeclaration(callRuntime("_template", _marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.getFile)().metadata.marko.id), ...replaceNullishAndEmptyFunctionsWith0([
templateIdentifier,
walksIdentifier,
domExports.setupEmpty ? void 0 : setupIdentifier,
programInputSignal?.identifier
]))));
}
} };
//#endregion
//#region src/translator/util/is-static.ts
function isStatic(path) {
return path.isImportDeclaration() || path.isExportDeclaration() || path.isMarkoScriptlet({ static: true });
}
//#endregion
//#region src/translator/visitors/program/html.ts
function getTemplateContentName() {
return getSharedUid("content");
}
var html_default = { translate: {
enter() {
forEachSection((section) => {
forEach(section.bindings, (binding) => {
for (const [hoistSection, hasReference] of binding.getters) if (hasReference) getHTMLSectionStatements(hoistSection || section).push(_marko_compiler.types.variableDeclaration("const", [hoistSection ? _marko_compiler.types.variableDeclarator(getBindingGetterIdentifier(binding, hoistSection), callRuntime("_hoist", getScopeIdIdentifier(hoistSection), _marko_compiler.types.stringLiteral(getResumeRegisterId(hoistSection, binding, "hoist")))) : _marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(binding.originalName), callRuntime("_el", getScopeIdIdentifier(section), _marko_compiler.types.stringLiteral(getResumeRegisterId(section, binding))))]));
});
const sectionDynamicSubscribers = /* @__PURE__ */ new Set();
forEach(section.hoisted, (binding) => {
let highestHoistSection;
forEach(binding.hoists, (hoistSection) => {
if (!highestHoistSection || hoistSection.depth < highestHoistSection.depth) highestHoistSection = hoistSection;
});
let currentSection = section;
while (currentSection && currentSection !== highestHoistSection) {
const parentSection = currentSection.parent;
if (!currentSection.sectionAccessor && !sectionDynamicSubscribers.has(currentSection)) {
const subscribersIdentifier = generateUidIdentifier(`${currentSection.name}__subscribers`);
sectionDynamicSubscribers.add(currentSection);
getHTMLSectionStatements(parentSection).push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(subscribersIdentifier, _marko_compiler.types.newExpression(_marko_compiler.types.identifier("Set"), []))]));
addWriteScopeBuilder(currentSection, (expr) => callRuntime("_subscribe", subscribersIdentifier, expr));
setSerializedValue(parentSection, getSectionInstancesAccessor(currentSection), subscribersIdentifier);
}
currentSection = parentSection;
}
});
});
},
exit(program) {
if (program.node.extra.hasGlobalRead) getHTMLSectionStatements(getSection(program)).push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier("$global"), callRuntime("$global"))]));
flushInto(program);
writeHTMLResumeStatements(program);
traverseReplace(program.node, "body", replaceNode);
const renderContent = [];
const section = getSection(program);
let dynamicSerializeReason = !!section.paramReasonGroups || isReasonDynamic(section.serializeReason);
if (!dynamicSerializeReason) {
for (const reason of section.serializeReasons.values()) if (isReasonDynamic(reason)) {
dynamicSerializeReason = true;
break;
}
}
if (dynamicSerializeReason) renderContent.push(getScopeReasonDeclaration(section));
else renderContent.push(_marko_compiler.types.expressionStatement(callRuntime("_scope_reason")));
for (const child of program.get("body")) if (!isStatic(child)) {
renderContent.push(child.node);
child.remove();
} else if (child.isMarkoScriptlet()) if (child.node.target && child.node.target !== "server") child.remove();
else child.replaceWithMultiple(child.node.body);
writeModuleRegistrations(program);
const contentId = usedSharedUid("content") && getTemplateContentName();
const contentFn = _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier("input")], _marko_compiler.types.blockStatement(renderContent));
const exportDefault = _marko_compiler.types.exportDefaultDeclaration(callRuntime("_template", _marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.getFile)().metadata.marko.id), contentId ? _marko_compiler.types.identifier(contentId) : contentFn, program.node.extra.page || !getMarkoOpts().linkAssets ? _marko_compiler.types.numericLiteral(1) : void 0));
if (contentId) program.node.body.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(contentId), contentFn)]), exportDefault);
else program.node.body.push(exportDefault);
}
} };
function replaceNode(node) {
return replaceBindingReadNode(node) || replaceRegisteredFunctionNode(node);
}
function replaceBindingReadNode(node) {
switch (node.type) {
case "Identifier":
case "MemberExpression":
case "OptionalMemberExpression": {
const { extra } = node;
if (extra && !(extra.read && !extra.read.binding.declared || extra.binding && !extra.binding.declared)) return getReadReplacement(node);
break;
}
case "CallExpression": {
const read = node.callee.extra?.read;
if (read && (read.getter !== void 0 || read.binding.type === 0)) return _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.cloneNode(node.callee)], node), [importRuntime(read.binding.type === 0 ? "_el_read_error" : "_hoist_read_error")]);
break;
}
}
}
function replaceRegisteredFunctionNode(node) {
switch (node.type) {
case "ClassMethod": {
const replacement = getRegisteredFnExpression(node);
return replacement && _marko_compiler.types.classProperty(node.key, replacement, void 0, void 0, node.computed, node.static);
}
case "ClassPrivateMethod": {
const replacement = getRegisteredFnExpression(node);
return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement, void 0, node.static);
}
case "ObjectMethod": {
const replacement = getRegisteredFnExpression(node);
return replacement && _marko_compiler.types.objectProperty(node.key, replacement, node.computed);
}
case "ArrowFunctionExpression":
case "FunctionExpression": return getRegisteredFnExpression(node);
case "BlockStatement":
case "MarkoScriptlet":
addRegisteredDeclarations(node.body);
break;
}
}
function addRegisteredDeclarations(body) {
const len = body.length;
for (let i = 0; i < len; i++) {
const child = body[i];
if (child.type === "FunctionDeclaration" && isRegisteredFnExtra(child.extra)) body.push(_marko_compiler.types.expressionStatement(callRuntime("_resume", _marko_compiler.types.identifier(child.id.name), _marko_compiler.types.stringLiteral(child.extra.registerId))));
}
}
function getRegisteredFnExpression(node) {
const { extra } = node;
if (isRegisteredFnExtra(extra)) {
const referencedLocals = extra.referencedLocalBindingsInFunction;
if (referencedLocals) {
const localProperties = [];
forEach(referencedLocals, (binding) => {
localProperties.push(toObjectProperty(getLocalsScopeAccessor(binding), getDeclaredBindingExpression(binding)));
});
return callRuntime("_resume_locals", simplifyFunction(node), _marko_compiler.types.stringLiteral(extra.registerId), _marko_compiler.types.objectExpression(localProperties), (extra.referencedBindingsInFunction || extra.referencesScope) && getScopeIdIdentifier(extra.section));
}
return callRuntime("_resume", simplifyFunction(node), _marko_compiler.types.stringLiteral(extra.registerId), (extra.referencedBindingsInFunction || extra.referencesScope) && getScopeIdIdentifier(extra.section));
}
}
//#endregion
//#region src/translator/util/body-to-text-literal.ts
const kRawText = Symbol("raw text placeholder");
function bodyToTextLiteral(body, decodeEntities = false) {
return buildTextLiteral(body, toText, true, decodeEntities);
}
function bodyToRawTextLiteral(body) {
return buildTextLiteral(body, (value) => value, true);
}
function injectTextCoercion(expr) {
switch (expr.type) {
case "ConditionalExpression":
injectTextCoercion(expr.consequent);
injectTextCoercion(expr.alternate);
break;
case "TemplateLiteral":
expr.expressions = expr.expressions.map((child) => toText(child));
break;
}
}
function toText(value) {
return callRuntime("_to_text", value);
}
function buildTextLiteral(body, coerce, bareSingle, decodeEntities = false) {
const templateQuasis = [];
const templateExpressions = [];
let currentQuasi = "";
let placeholderExtra;
let singleValue;
for (const child of body.body) if (_marko_compiler.types.isMarkoText(child)) currentQuasi += decodeEntities ? (0, _marko_compiler_babel_utils.decodeHTML)(child.value) : child.value;
else if (_marko_compiler.types.isMarkoPlaceholder(child)) {
placeholderExtra ||= child.value.extra;
templateQuasis.push(templateElement(currentQuasi, false));
templateExpressions.push(coerce(child.value));
singleValue = child.value;
currentQuasi = "";
}
if (templateExpressions.length) {
if (bareSingle && templateExpressions.length === 1 && !currentQuasi && !templateQuasis[0].value.cooked && !_marko_compiler.types.isStringLiteral(singleValue)) return singleValue;
templateQuasis.push(templateElement(currentQuasi, true));
const literal = _marko_compiler.types.templateLiteral(templateQuasis, templateExpressions);
literal.extra = placeholderExtra;
return literal;
}
return _marko_compiler.types.stringLiteral(currentQuasi);
}
function templateElement(value, tail) {
return _marko_compiler.types.templateElement({
raw: escapeTemplateRaw(value),
cooked: value
}, tail);
}
//#endregion
//#region src/translator/util/branch-tag.ts
function getBranchSectionAccessor(nodeBinding) {
return {
binding: nodeBinding,
prefix: getAccessorPrefix().BranchScopes
};
}
function initBranchSection(bodySection, upstreamExpression, sectionAccessor) {
bodySection.isBranch = true;
bodySection.upstreamExpression = upstreamExpression;
bodySection.sectionAccessor = sectionAccessor;
}
function resumeOwnerByMarkerWhenStatic(tagSection, bodySection, nodeBinding, statefulReasonKey) {
if (isStateSerializeReason(getSerializeReason(tagSection, statefulReasonKey)) && isStaticSerializeReason(getSerializeReason(bodySection, kBranchSerializeReason)) && isStaticSerializeReason(getSerializeReason(tagSection, nodeBinding))) setSectionOwnerResumedByMarker(bodySection);
}
//#endregion
//#region src/translator/util/is-event-or-change-handler.ts
function isEventOrChangeHandler(prop) {
return /^on[-A-Z]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
}
//#endregion
//#region src/translator/util/is-non-html-text.ts
function isNonHTMLText(placeholder) {
const parentTag = placeholder.parentPath.isMarkoTagBody() && placeholder.parentPath.parentPath;
if (parentTag) {
if (isCoreTag(parentTag)) switch (parentTag.node.name.value) {
case "html-comment":
case "html-script":
case "html-style":
case "style": return true;
}
else if (isTextOnlyNativeTag(parentTag)) return true;
}
return false;
}
function isTextOnlyNativeTag(tag) {
if (analyzeTagNameType(tag) !== 0) return false;
const def = (0, _marko_compiler_babel_utils.getTagDef)(tag);
return !!(def && def.html && (def.name === "title" || def.parseOptions?.text));
}
//#endregion
//#region src/translator/core/for.ts
const kStatefulReason$2 = Symbol("<for> stateful reason");
var for_default = {
analyze(tag) {
const tagSection = getOrCreateSection(tag);
const isAttrTag = tag.node.body.attributeTags;
const tagBody = tag.get("body");
const paramsBinding = trackParamsReferences(tagBody, isAttrTag ? 4 : 5);
let allowAttrs;
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
assertNoSpreadAttrs(tag);
const forType = getForType(tag.node);
switch (forType) {
case "of":
allowAttrs = ["of"];
break;
case "in":
allowAttrs = ["in"];
break;
case "to":
allowAttrs = [
"to",
"from",
"step"
];
break;
case "until":
allowAttrs = [
"until",
"from",
"step"
];
break;
default: throw tag.buildCodeFrameError("The [`<for>` tag](https://markojs.com/docs/reference/core-tag#for) requires an `of=`, `in=`, `to=`, or `until=` attribute.");
}
if (!isAttrTag) allowAttrs.push("by");
const keyAttr = tag.node.attributes.find((attr) => attr.type === "MarkoAttribute" && attr.name === "key");
if (keyAttr) throw tag.hub.buildError(keyAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) keys items with the \`by=\` attribute, not \`key=\`. ${forType === "of" ? "Use `by=\"propName\"` or `by=(item, index) => key`" : forType === "in" ? "Use `by=(key, value) => key`" : "Use `by=(num) => key`"}.`);
(0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, allowAttrs);
if (isAttrTag) return;
const byAttr = getKnownAttrValues(tag.node).by;
if (forType !== "of" && byAttr?.type === "StringLiteral") throw tag.hub.buildError(byAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only supports a string \`by\` key with \`of\`; use a \`by=(${forType === "in" ? "key, value" : "index"}) => ...\` function for \`<for ${forType}>\`.`);
if (byAttr) {
const paramNames = /* @__PURE__ */ new Set();
for (const param of tag.node.body.params) for (const name in _marko_compiler.types.getBindingIdentifiers(param)) paramNames.add(name);
const paramRead = paramNames.size ? findLoopParamRead(byAttr, paramNames) : void 0;
if (paramRead) throw tag.hub.buildError(paramRead, `The \`by=\` attribute is evaluated before the loop runs, so \`${paramRead.name}\` is not in scope. Key with a property name string (\`by="id"\`) or a function (\`by=(${paramRead.name}) => key\`).`);
}
const bodySection = startSection(tagBody);
if (!bodySection) {
dropNodes(getAllTagReferenceNodes(tag.node));
return;
}
const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
const tagExtra = mergeReferences(tagSection, tag.node, getAllTagReferenceNodes(tag.node));
addSerializeExpr(tagSection, tagExtra, kStatefulReason$2);
if (paramsBinding) {
setBindingDownstream(paramsBinding, tagExtra);
const keyBinding = getLoopKeyBinding(byAttr, paramsBinding, forType);
if (keyBinding) {
if (!byAttr) {
keyBinding.type = 6;
keyBinding.scopeAccessor = getAccessorProp().LoopKey;
}
onFinalizeReferences(() => detectForSelector(bodySection, keyBinding));
}
}
initBranchSection(bodySection, tagExtra, getBranchSectionAccessor(nodeBinding));
if (!isAttrTag && !getOnlyChildParentTagName(tag)) {
visit(tag, 37);
enterShallow(tag);
}
},
translate: translateByTarget({
html: {
enter(tag) {
if (tag.node.body.attributeTags) return;
const bodySection = getSectionForBody(tag.get("body"));
if (!bodySection) {
tag.remove();
return;
}
setSectionParentIsOwner(bodySection, true);
flushBefore(tag);
},
exit(tag) {
if (tag.node.body.attributeTags) return;
const tagBody = tag.get("body");
const tagSection = getSection(tag);
const bodySection = getSectionForBody(tagBody);
const { node } = tag;
const onlyChildParentTagName = getOnlyChildParentTagName(tag);
const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
const forAttrs = getKnownAttrValues(node);
const forType = getForType(node);
const params = node.body.params;
const statements = [];
const bodyStatements = node.body.body;
const singleChild = bodySection.content?.singleChild && bodySection.content.startType !== 4;
const branchSerializeReason = getSerializeReason(bodySection, kBranchSerializeReason);
const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
resumeOwnerByMarkerWhenStatic(tagSection, bodySection, nodeBinding, kStatefulReason$2);
flushInto(tag);
writeHTMLResumeStatements(tagBody);
const forTagArgs = getBaseArgsInForTag(forType, forAttrs);
const forTagHTMLRuntime = branchSerializeReason ? forTypeToBranchRuntime(forType) : forTypeToRuntime(forType);
forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
if (branchSerializeReason) {
const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
const statefulSerializeArg = getSerializeGuard(tagSection, getSerializeReason(tagSection, kStatefulReason$2), !(skipParentEnd || singleChild));
const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
forTagArgs.push(forAttrs.by || _marko_compiler.types.numericLiteral(0), getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuard(tagSection, branchSerializeReason, !markerSerializeArg), markerSerializeArg, statefulSerializeArg);
if (skipParentEnd) {
getParentTag(tag).node.extra[kSkipEndTag] = true;
forTagArgs.push(_marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`));
}
if (singleChild) {
if (!skipParentEnd) forTagArgs.push(_marko_compiler.types.numericLiteral(0));
forTagArgs.push(_marko_compiler.types.numericLiteral(1));
}
}
statements.push(_marko_compiler.types.expressionStatement(callRuntime(forTagHTMLRuntime, ...forTagArgs)));
for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
}
},
dom: {
enter(tag) {
if (tag.node.body.attributeTags) return;
const bodySection = getSectionForBody(tag.get("body"));
if (!bodySection) {
tag.remove();
return;
}
setSectionParentIsOwner(bodySection, true);
},
exit(tag) {
if (tag.node.body.attributeTags) return;
const tagBody = tag.get("body");
const tagSection = getSection(tag);
const bodySection = getSectionForBody(tagBody);
const { node } = tag;
const { referencedBindings } = node.extra;
const nodeRef = getOptimizedOnlyChildNodeBinding(tag, tagSection);
setClosureSignalBuilder(tag, (closure, render) => {
const selectorKeyBinding = getForSelectorKey(bodySection, closure);
if (selectorKeyBinding) return callRuntime("_for_selector", getScopeAccessorLiteral(nodeRef, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
return callRuntime("_for_closure", getScopeAccessorLiteral(nodeRef, true), render);
});
const forType = getForType(node);
const signal = getSignal(tagSection, nodeRef, "for");
signal.build = () => {
return callRuntime(forTypeToBranchRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
};
const forAttrs = getKnownAttrValues(node);
const loopArgs = getBaseArgsInForTag(forType, forAttrs);
if (forAttrs.by) loopArgs.push(forAttrs.by);
addValue(tagSection, referencedBindings, signal, _marko_compiler.types.arrayExpression(loopArgs));
tag.remove();
}
}
}),
parseOptions: { controlFlow: true },
attributes: {
of: {
type: "expression",
autocomplete: [{ description: "Iterates over a list of items." }]
},
in: {
type: "expression",
autocomplete: [{ description: "Iterates over the keys and values of an object." }]
},
to: {
type: "number",
autocomplete: [{ description: "Iterates up to the provided number (inclusive)" }]
},
until: {
type: "number",
autocomplete: [{ description: "Iterates up to the provided number (exclusive)" }]
},
from: {
type: "number",
autocomplete: [{ description: "Iterates starting from the provided number (inclusive)" }]
},
step: {
type: "number",
autocomplete: [{ description: "The amount to increment during each iteration (with from/to/until)" }]
}
},
autocomplete: [
{
snippet: "for|${1:value, index}| of=${3:array}",
description: "Use to iterate over lists, object properties, or between ranges.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
},
{
snippet: "for|${1:name, value}| in=${3:object}",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
},
{
snippet: "for|${1:index}| to=${2:number}",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
},
{
snippet: "for|${1:index}| until=${2:number}",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
}
]
};
function buildForRuntimeCall(type, attrs, params, statements) {
return _marko_compiler.types.expressionStatement(callRuntime(forTypeToRuntime(type), ...getBaseArgsInForTag(type, attrs), _marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(statements))));
}
function getForType(tag) {
for (const attr of tag.attributes) if (attr.type === "MarkoAttribute") switch (attr.name) {
case "of":
case "in":
case "to":
case "until": return attr.name;
}
}
function findLoopParamRead(node, names) {
switch (node.type) {
case "Identifier": return names.has(node.name) ? node : void 0;
case "MemberExpression":
case "OptionalMemberExpression": return findLoopParamRead(node.object, names) || (node.computed ? findLoopParamRead(node.property, names) : void 0);
}
if (_marko_compiler.types.isFunction(node) || _marko_compiler.types.isClass(node)) return;
for (const key of _marko_compiler.types.VISITOR_KEYS[node.type] || []) {
if (key === "typeAnnotation" || key === "typeParameters") continue;
if (key === "key" && !node.computed) continue;
const value = node[key];
if (Array.isArray(value)) for (const child of value) {
const found = child?.type && findLoopParamRead(child, names);
if (found) return found;
}
else if (value?.type) {
const found = findLoopParamRead(value, names);
if (found) return found;
}
}
}
function getLoopKeyBinding(byAttr, paramsBinding, forType) {
if (!paramsBinding) return;
if (byAttr) {
const keyChain = getByKeyChain(byAttr);
if (!keyChain) return;
let keyBinding = paramsBinding.propertyAliases.get("0");
for (const property of keyChain) keyBinding = keyBinding?.propertyAliases.get(property);
return keyBinding;
}
return paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
}
function getByKeyChain(byAttr) {
if (byAttr.type === "StringLiteral") return [byAttr.value];
if (byAttr.type === "ArrowFunctionExpression" || byAttr.type === "FunctionExpression") {
const itemParam = byAttr.params[0];
let body = byAttr.body;
if (body.type === "BlockStatement") {
const [statement] = body.body;
body = body.body.length === 1 && statement.type === "ReturnStatement" ? statement.argument : void 0;
}
if (itemParam?.type === "Identifier" && body) return getStaticMemberChain(body, itemParam.name);
}
}
function getStaticMemberChain(node, rootName) {
const chain = [];
let cur = node;
while (cur.type === "MemberExpression" || cur.type === "OptionalMemberExpression") {
const property = getMemberExpressionPropString(cur);
if (property === void 0) return;
chain.push(property);
cur = cur.object;
}
if (cur.type === "Identifier" && cur.name === rootName) return chain.reverse();
}
function forTypeToRuntime(type) {
switch (type) {
case "of": return "forOf";
case "in": return "forIn";
case "to": return "forTo";
case "until": return "forUntil";
}
}
function forTypeToBranchRuntime(type) {
switch (type) {
case "of": return "_for_of";
case "in": return "_for_in";
case "to": return "_for_to";
case "until": return "_for_until";
}
}
function getBaseArgsInForTag(type, attrs) {
switch (type) {
case "in": return [attrs.in];
case "of": return [attrs.of];
case "to": return [
attrs.to,
attrs.from || _marko_compiler.types.numericLiteral(0),
attrs.step || _marko_compiler.types.numericLiteral(1)
];
case "until": return [
attrs.until,
attrs.from || _marko_compiler.types.numericLiteral(0),
attrs.step || _marko_compiler.types.numericLiteral(1)
];
}
}
//#endregion
//#region src/translator/util/nested-attribute-tags.ts
const [getAttrTagIdentifiers] = createProgramState(() => /* @__PURE__ */ new WeakMap());
function getAttrTagIdentifier(meta) {
const identifiers = getAttrTagIdentifiers();
let name = identifiers.get(meta);
if (!name) identifiers.set(meta, name = generateUid(meta.name));
return _marko_compiler.types.identifier(name);
}
function getAttrTagPaths(tag) {
return tag.node.body.attributeTags ? tag.get("body").get("body") : tag.get("attributeTags");
}
function analyzeAttributeTags(tag) {
if (tag.node.extra?.attributeTags) return tag.node.extra.attributeTags;
const attrTags = getAttrTagPaths(tag);
if (!attrTags.length) return;
const tagExtra = tag.node.extra ??= {};
const lookup = tagExtra.attributeTags = {};
const attrTagNodesByName = {};
const sampleAttrTagsForControlFlow = /* @__PURE__ */ new Map();
for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const name = getTagName(child);
lookup[name] ||= createAttrTagMeta(name, [name]);
(attrTagNodesByName[name] ||= []).push(child);
analyzeAttributeTags(child);
} else {
const isRepeated = (0, _marko_compiler_babel_utils.isLoopTag)(child);
let curGroup;
for (const name of crawlAttrTags(child, attrTagNodesByName)) {
const oldMeta = lookup[name];
if (oldMeta) {
if (!curGroup) curGroup = oldMeta.group;
else if (curGroup !== oldMeta.group) for (const name of oldMeta.group) {
lookup[name].group = curGroup;
curGroup.push(name);
}
}
let attrTagMeta = lookup[name];
if (!attrTagMeta) {
attrTagMeta = lookup[name] = createAttrTagMeta(name, curGroup ||= []);
curGroup.push(name);
}
attrTagMeta.dynamic = true;
if (isRepeated) attrTagMeta.repeated = true;
sampleAttrTagsForControlFlow.set(child, name);
}
}
for (const [controlFlowTag, sampleAttrName] of sampleAttrTagsForControlFlow) (controlFlowTag.node.extra ??= {}).attributeTagGroup = lookup[sampleAttrName].group;
for (const name in attrTagNodesByName) {
const attrTagMeta = lookup[name];
if (!attrTagMeta.repeated) {
const attrTagNodes = attrTagNodesByName[name];
if (attrTagNodes.length > 1) attrTagMeta.repeated = !attrTagMeta.dynamic || hasRepeatedDynamicAttrTags(attrTagNodes);
}
}
return lookup;
}
function createAttrTagMeta(name, group) {
return {
name: name.slice(1),
dynamic: false,
repeated: false,
group
};
}
function crawlAttrTags(tag, attrTagNodesByName, attrTagNames = /* @__PURE__ */ new Set()) {
const attrTags = getAttrTagPaths(tag);
for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const tagName = getTagName(child);
attrTagNames.add(tagName);
(attrTagNodesByName[tagName] ||= []).push(child);
analyzeAttributeTags(child);
} else crawlAttrTags(child, attrTagNodesByName, attrTagNames);
return attrTagNames;
}
function hasRepeatedDynamicAttrTags(attrTags) {
let conditionRoot;
const seenBranches = /* @__PURE__ */ new Set();
for (const attrTag of attrTags) {
const parentTag = getParentTag(attrTag);
if (seenBranches.has(parentTag) || !isConditionTag(parentTag)) return true;
const curConditionRoot = getConditionRoot(parentTag);
if (curConditionRoot && curConditionRoot !== (conditionRoot ||= curConditionRoot)) return true;
seenBranches.add(parentTag);
}
return false;
}
function getConditionRoot(tag) {
if (getTagName(tag) === "if") return tag;
let prev = tag.getPrevSibling();
while (prev.node) {
if (prev.isMarkoTag() && getTagName(prev) === "if") return prev;
prev = prev.getPrevSibling();
}
}
//#endregion
//#region src/translator/util/translate-attrs.ts
const contentProps = /* @__PURE__ */ new WeakSet();
function translateAttrs(tag, propTree = true, skip, statements = [], contentKey = "content") {
const contentProperties = [];
const attrTagLookup = tag.node.extra?.attributeTags;
const seen = new Set(skip);
if (attrTagLookup) {
for (const name in attrTagLookup) {
const attrTagMeta = attrTagLookup[name];
if (!seen.has(attrTagMeta.name) && getKnownFromPropTree(propTree, attrTagMeta.name)) {
seen.add(attrTagMeta.name);
if (attrTagMeta.dynamic) {
statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(getAttrTagIdentifier(attrTagMeta))]));
contentProperties.push(toObjectProperty(attrTagMeta.name, getAttrTagIdentifier(attrTagMeta)));
}
}
}
const attrTags = getAttrTagPaths(tag);
for (let i = 0; i < attrTags.length; i++) {
const child = attrTags[i];
if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const attrTagMeta = attrTagLookup[getTagName(child)];
if (skip?.has(attrTagMeta.name)) continue;
if (attrTagMeta.dynamic) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
else {
const translatedAttrTag = translateAttrs(child, getKnownFromPropTree(propTree, attrTagMeta.name), void 0, statements, contentKey);
const prevProp = attrTagMeta.repeated ? findObjectProperty(attrTagMeta.name, contentProperties) : void 0;
if (prevProp) prevProp.value = callRuntime("attrTags", prevProp.value, _marko_compiler.types.objectExpression(translatedAttrTag.properties));
else contentProperties.push(toObjectProperty(attrTagMeta.name, callRuntime("attrTag", _marko_compiler.types.objectExpression(translatedAttrTag.properties))));
}
} else i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
}
}
if (!seen.has(contentKey) && getKnownFromPropTree(propTree, contentKey)) {
const contentExpression = buildContent(tag.get("body"));
if (contentExpression) {
const contentProp = _marko_compiler.types.objectProperty(_marko_compiler.types.identifier(contentKey), contentExpression);
seen.add(contentKey);
contentProps.add(contentProp);
contentProperties.push(contentProp);
}
}
const { attributes } = tag.node;
const attrProperties = [];
for (let i = attributes.length; i--;) {
const attr = attributes[i];
const { value } = attr;
if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) attrProperties.push(_marko_compiler.types.spreadElement(value));
else if (!seen.has(attr.name) && getKnownFromPropTree(propTree, attr.name)) {
seen.add(attr.name);
attrProperties.push(toObjectProperty(attr.name, value));
}
}
return {
properties: attrProperties.reverse().concat(contentProperties),
statements
};
}
function getTranslatedBodyContentProperty(props) {
for (const prop of props) if (contentProps.has(prop)) return prop;
}
function addDynamicAttrTagStatements(attrTags, index, attrTagLookup, statements, propTree, contentKey = "content") {
const tag = attrTags[index];
if (tag.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
const attrTagMeta = attrTagLookup[getTagName(tag)];
const attrTagExport = getKnownFromPropTree(propTree, attrTagMeta.name);
if (attrTagExport && attrTagMeta.dynamic) {
const translatedAttrTag = translateAttrs(tag, attrTagExport, void 0, statements, contentKey);
if (attrTagMeta.repeated) statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTags", getAttrTagIdentifier(attrTagMeta), _marko_compiler.types.objectExpression(translatedAttrTag.properties)))));
else statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTag", _marko_compiler.types.objectExpression(translatedAttrTag.properties)))));
}
} else switch (getTagName(tag)) {
case "if": return translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
case "for": return translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
}
return index;
}
/** Unwraps a lone spread to the spread argument itself, so the result may alias
* a caller binding; anything the runtime writes to needs its own object. */
function propsToExpression(props) {
return props.length === 1 && _marko_compiler.types.isSpreadElement(props[0]) ? props[0].argument : _marko_compiler.types.objectExpression(props);
}
function translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
const forTag = attrTags[index];
const bodyStatements = [];
addAllAttrTagsAsDynamic(forTag, attrTagLookup, bodyStatements, propTree, contentKey);
statements.push(buildForRuntimeCall(getForType(forTag.node), getKnownAttrValues(forTag.node), forTag.node.body.params, bodyStatements));
return index;
}
function translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
const ifTag = attrTags[index];
const consequentStatements = [];
let ifStatement = _marko_compiler.types.ifStatement(getConditionTestValue(ifTag), _marko_compiler.types.blockStatement(consequentStatements));
statements.push(ifStatement);
addAllAttrTagsAsDynamic(ifTag, attrTagLookup, consequentStatements, propTree, contentKey);
let nextIndex = index + 1;
while (nextIndex < attrTags.length) {
const nextTag = attrTags[nextIndex];
if (nextTag.isMarkoTag()) switch (getTagName(nextTag)) {
case "else-if":
case "else": {
const testValue = getConditionTestValue(nextTag);
const alternateStatements = [];
addAllAttrTagsAsDynamic(nextTag, attrTagLookup, alternateStatements, propTree, contentKey);
if (testValue) {
ifStatement.alternate = ifStatement = _marko_compiler.types.ifStatement(testValue, _marko_compiler.types.blockStatement(alternateStatements));
nextIndex++;
continue;
} else {
ifStatement.alternate = _marko_compiler.types.blockStatement(alternateStatements);
break;
}
}
}
break;
}
return nextIndex - 1;
}
function addAllAttrTagsAsDynamic(tag, attrTagLookup, statements, propTree, contentKey) {
const attrTags = getAttrTagPaths(tag);
for (let i = 0; i < attrTags.length; i++) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
}
function findObjectProperty(name, props) {
for (const prop of props) if (prop.type === "ObjectProperty") switch (prop.key.type) {
case "StringLiteral":
if (prop.key.value === name) return prop;
break;
case "Identifier":
if (prop.key.name === name) return prop;
break;
}
return false;
}
function getConditionTestValue({ node: { attributes } }) {
return attributes.length === 1 ? attributes[0].value : void 0;
}
function buildContent(body) {
const bodySection = body.node.extra?.section;
if (bodySection) if (isOutputHTML()) {
const serialized = getSectionRegisterReasons(bodySection);
let dynamicSerializeReason = !!bodySection.paramReasonGroups || isReasonDynamic(bodySection.serializeReason);
if (!dynamicSerializeReason) {
for (const reason of bodySection.serializeReasons.values()) if (isReasonDynamic(reason)) {
dynamicSerializeReason = true;
break;
}
}
if (dynamicSerializeReason) body.node.body.unshift(getScopeReasonDeclaration(bodySection));
else body.node.body.unshift(_marko_compiler.types.expressionStatement(callRuntime("_scope_reason")));
return callRuntime(serialized ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(bodySection, "content")), _marko_compiler.types.arrowFunctionExpression(body.node.params, _marko_compiler.types.blockStatement(body.node.body)), getScopeIdIdentifier(getSection(getAttributeTagParent(body.parentPath))));
} else {
if (isSectionRendererElided(bodySection)) return;
return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), bodySection.referencedLocalClosures ? [scopeIdentifier, _marko_compiler.types.objectExpression(toArray(bodySection.referencedLocalClosures, (ref) => {
return toObjectProperty(getScopeAccessor(ref, true), getDeclaredBindingExpression(ref));
}))] : [scopeIdentifier]);
}
}
//#endregion
//#region src/translator/visitors/tag/native-tag.ts
const kNativeTagBinding = Symbol("native tag binding");
const kSkipEndTag = Symbol("skip native tag mark");
const kTagContentAttr = Symbol("tag could have dynamic content attribute");
const kVisitOp = Symbol("native tag structure visit");
const htmlSelectArgs = /* @__PURE__ */ new WeakMap();
var native_tag_default = {
analyze: {
enter(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
const { node } = tag;
if (node.var && !_marko_compiler.types.isIdentifier(node.var)) throw tag.get("var").buildCodeFrameError("Tag variables on [native tags](https://markojs.com/docs/reference/native-tag) cannot be destructured.");
const tagName = getCanonicalTagName(tag);
switch (tagName) {
case "html":
case "body":
case "head":
(0, _marko_compiler_babel_utils.getProgram)().node.extra.page ??= true;
break;
}
if (tagName === "option") assertOptionInSelectWithValue(tag);
const isTextOnly = isTextOnlyNativeTag(tag);
const seen = Object.create(null);
const { attributes } = tag.node;
let injectNonce = isInjectNonceTag(tagName);
let hasDynamicAttributes = false;
let hasEventHandlers = false;
let relatedControllable;
let spreadReferenceNodes;
let exprExtras;
for (let i = attributes.length; i--;) {
const attr = attributes[i];
if (_marko_compiler.types.isMarkoAttribute(attr) && attr.name === "content" && tag.node.body.body.length) {
dropNodes(attr.value);
continue;
}
const valueExtra = attr.value.extra ??= {};
if (_marko_compiler.types.isMarkoAttribute(attr)) {
if (seen[attr.name]) {
(0, _marko_compiler_babel_utils.diagnosticWarn)(tag, {
label: `The \`${attr.name}\` attribute is set more than once on \`<${tagName}>\`; only the last value is used.`,
loc: attr.loc ?? void 0
});
dropNodes(attr.value);
continue;
}
seen[attr.name] = attr;
assertValidNativeAttrName(tag, attr);
assertNativeAttrValueType(tag, attr);
if (attr.name === "style") warnCamelCaseStyleKeys(tag, attr);
if (injectNonce && attr.name === "nonce") injectNonce = false;
if (isEventOrChangeHandler(attr.name)) assertNativeHandlerAttr(tag, attr);
if (isEventHandler(attr.name)) {
valueExtra.isEffect = true;
valueExtra.invokeOnly = true;
hasEventHandlers = true;
} else {
assertValidNativeEventHandlerAttr(tag, attr);
if (!evaluate(attr.value).confident) hasDynamicAttributes = true;
}
} else if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) {
valueExtra.isEffect = true;
hasEventHandlers = true;
hasDynamicAttributes = true;
}
if (spreadReferenceNodes) spreadReferenceNodes.push(attr.value);
else if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) {
spreadReferenceNodes = [attr.value];
relatedControllable = getRelatedControllable(tagName, seen);
} else exprExtras = push(exprExtras, valueExtra);
}
assertExclusiveAttrs(seen, (msg) => {
throw tag.get("name").buildCodeFrameError(msg);
});
if (seen.content) {
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
if (tagDef?.parseOptions?.openTagOnly && !tagDef.attributes?.content) throw tag.hub.buildError(seen.content, `The \`<${tagName}>\` tag cannot have content, so it does not support the \`content\` attribute.`);
if (isTextOnly) throw tag.hub.buildError(seen.content, `The \`<${tagName}>\` tag takes its content from its body as text, so it does not support the \`content\` attribute.`);
}
let textPlaceholders;
if (isTextOnly) {
for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) (textPlaceholders ||= []).push(child.value);
else if (!_marko_compiler.types.isMarkoText(child)) throw tag.hub.buildError(child, `Only text is allowed inside a \`<${tagName}>\`.`);
}
relatedControllable ||= getRelatedControllable(tagName, seen);
const valueChangeEval = tagName === "input" && seen.valueChange ? evaluate(seen.valueChange.value) : void 0;
if (valueChangeEval && !(valueChangeEval.confident && valueChangeEval.computed == null) && getInputValueMode(seen.type) === "attribute") {
const type = evaluate(seen.type.value).computed;
throw tag.hub.buildError(seen.valueChange, `\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
}
if (relatedControllable && relatedControllable.attrs[1]) hasEventHandlers = true;
if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || seen.content && tagName !== "meta" && !node.body.body.length || isDynamicControllable(relatedControllable)) {
const tagExtra = node.extra ??= {};
const tagSection = getOrCreateSection(tag);
const nodeBinding = tagExtra[kNativeTagBinding] = createBinding("#" + tagName.toLowerCase(), 0, tagSection, void 0, void 0, void 0, void 0, !!node.var);
if (hasEventHandlers) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
if (spreadReferenceNodes) {
const isMergedSpread = !!relatedControllable;
if (relatedControllable && !relatedControllable.attrs.every(Boolean)) {
for (const attr of relatedControllable.attrs) if (attr) spreadReferenceNodes.push(attr.value);
relatedControllable = void 0;
}
const spreadExtra = mergeReferences(tagSection, tag.node, spreadReferenceNodes);
spreadExtra.nativeTagSpread = true;
spreadExtra.invokeOnly = true;
if (isMergedSpread) spreadExtra.nativeTagSpreadMerged = true;
let carveProperties = getSpreadControllableValueProps(tagName);
if (!tag.node.body.body.length && !isTextOnly && !(0, _marko_compiler_babel_utils.getTagDef)(tag)?.parseOptions?.openTagOnly && !seen.content) if (carveProperties) carveProperties.push("content");
else carveProperties = ["content"];
for (const node of spreadReferenceNodes) {
const spreadBinding = node.extra?.spreadFrom;
if (spreadBinding) {
spreadBinding.noSerialize = true;
if (carveProperties) {
for (const property of carveProperties) if (!includes(spreadBinding.noSerializeProperties, property)) spreadBinding.noSerializeProperties = push(spreadBinding.noSerializeProperties, property);
}
}
}
}
if (relatedControllable) mergeReferences(tagSection, relatedControllable.attrs.find(Boolean).value, relatedControllable.attrs.map((it) => it?.value));
if (textPlaceholders) {
exprExtras = push(exprExtras, textPlaceholders.length === 1 ? textPlaceholders[0].extra ??= {} : mergeReferences(tagSection, textPlaceholders[0], textPlaceholders.slice(1)));
addSetupExpr(tagSection, textPlaceholders[0]);
}
if (injectNonce) addSetupStatement(tagSection);
if (relatedControllable?.attrs[1]) addSetupStatement(tagSection);
for (const name in seen) {
const attr = seen[name];
if (isEventHandler(name) || name === "content" || !evaluate(attr.value).confident) addSetupExpr(tagSection, attr.value);
}
addSerializeExpr(tagSection, !!(node.var || hasEventHandlers), nodeBinding);
trackDomVarReferences(tag, nodeBinding);
addSerializeExpr(tagSection, push(exprExtras, tagExtra), nodeBinding);
}
const write = writeTo(tag);
(node.extra ??= {})[kVisitOp] = visit(tag, 32, false);
write`<${tagName}`;
for (const attr of getUsedAttrs(tagName, tag.node, true).staticAttrs) {
const { name, value } = attr;
const { confident, computed } = value.extra || {};
switch (name) {
case "class":
case "style": {
const helper = `_attr_${name}`;
if (confident) write`${getHTMLRuntime()[helper](computed)}`;
else {
const meta = {
staticItems: void 0,
dynamicItems: void 0,
dynamicValues: void 0
};
trackDelimitedAttrValue(value, meta);
if (!meta.dynamicItems && meta.staticItems) write`${getHTMLRuntime()[helper](meta.staticItems)}`;
}
break;
}
default:
if (confident) write`${getHTMLRuntime()._attr(name, computed)}`;
break;
}
}
write`>`;
enter(tag);
},
exit(tag) {
const tagName = getCanonicalTagName(tag);
const tagExtra = tag.node.extra;
const visitOp = tagExtra[kVisitOp];
if (visitOp) visitOp.claimed = !!tagExtra[kNativeTagBinding];
if (!(0, _marko_compiler_babel_utils.getTagDef)(tag)?.parseOptions?.openTagOnly) {
const write = writeTo(tag);
if (tagName !== "textarea" && isTextOnlyNativeTag(tag)) {
const textLiteral = bodyToRawTextLiteral(tag.node.body);
if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${textLiteral.value}`;
}
write`</${tagName}>`;
}
exit(tag);
}
},
translate: translateByTarget({
html: {
enter(tag) {
const tagName = getCanonicalTagName(tag);
const tagExtra = tag.node.extra;
const nodeBinding = tagExtra[kNativeTagBinding];
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
const write = writeTo$1(tag);
const tagSection = getSection(tag);
const visitAccessor = nodeBinding && getScopeAccessorLiteral(nodeBinding);
const usedAttrs = getUsedAttrs(tagName, tag.node);
const { staticAttrs, staticControllable, staticContentAttr, skipExpression, injectNonce } = usedAttrs;
let { spreadExpression } = usedAttrs;
if (!isOptimize() && nodeBinding) {
const changeAttr = staticControllable?.attrs[1];
if (changeAttr) {
const handler = evaluate(changeAttr.value);
if (!(handler.confident && handler.computed == null)) setSectionDebugVar(tagSection, getPrefixedScopeAccessor(nodeBinding, getAccessorPrefix().ControlledHandler), changeAttr.name, changeAttr.loc);
} else if (spreadExpression) {
const spreads = tag.node.attributes.filter((attr) => _marko_compiler.types.isMarkoSpreadAttribute(attr));
const spreadLoc = spreads.length === 1 && spreads[0].value.loc;
if (spreadLoc && spreadLoc.start.index != null) {
const name = "..." + (0, _marko_compiler_babel_utils.getFile)().code.slice(spreadLoc.start.index, spreadLoc.end.index);
for (const prefix of [getAccessorPrefix().ControlledHandler, getAccessorPrefix().EventAttributes]) if (prefix !== getAccessorPrefix().ControlledHandler || getSpreadControllableValueProps(tagName)) setSectionDebugVar(tagSection, getPrefixedScopeAccessor(nodeBinding, prefix), name, spreadLoc);
}
}
}
if (tagName === "select" && (staticControllable || spreadExpression)) flushBefore(tag);
write`<${tagName}`;
if (injectNonce) write`${callRuntime("_attr_nonce")}`;
if (staticControllable) {
const hasChangeHandler = !!staticControllable.attrs[1];
if (tagName !== "select" && tagName !== "textarea") write`${callRuntime(staticControllable.helper, getScopeIdIdentifier(tagSection), visitAccessor, ...staticControllable.attrs.map((attr) => attr?.value))}`;
if (hasChangeHandler) addHTMLEffectCall(tagSection, void 0);
}
let writeAtStartOfBody;
if (tagName === "html" && getMarkoOpts().linkAssets && !tag.node.body.body.some((child) => child.type === "MarkoTag" && child.name.type === "StringLiteral" && child.name.value === "head")) writeAtStartOfBody = callRuntime("_flush_head");
if (tagName === "select") {
if (staticControllable) htmlSelectArgs.set(tag.node, {
value: staticControllable.attrs[0]?.value || buildUndefined$1(),
valueChange: staticControllable.attrs[1]?.value || buildUndefined$1()
});
else if (spreadExpression) {
const spreadIdentifier = generateUidIdentifier("select_input");
tag.insertBefore(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(spreadIdentifier, spreadExpression)]));
htmlSelectArgs.set(tag.node, {
value: _marko_compiler.types.memberExpression(spreadIdentifier, _marko_compiler.types.identifier("value")),
valueChange: _marko_compiler.types.memberExpression(spreadIdentifier, _marko_compiler.types.identifier("valueChange")),
serializeType: _marko_compiler.types.numericLiteral(1)
});
spreadExpression = spreadIdentifier;
}
} else if (tagName === "textarea") {
let value;
let valueChange;
if (staticControllable) {
value = staticControllable.attrs[0]?.value;
valueChange = staticControllable.attrs[1]?.value;
} else if (spreadExpression) {
const spreadIdentifier = generateUidIdentifier("textarea_input");
tag.insertBefore(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(spreadIdentifier, spreadExpression)]));
value = _marko_compiler.types.memberExpression(spreadIdentifier, _marko_compiler.types.identifier("value"));
valueChange = _marko_compiler.types.memberExpression(spreadIdentifier, _marko_compiler.types.identifier("valueChange"));
spreadExpression = spreadIdentifier;
}
if (valueChange) writeAtStartOfBody = callRuntime("_attr_textarea_value", getScopeIdIdentifier(tagSection), visitAccessor, value, valueChange, staticControllable ? void 0 : _marko_compiler.types.numericLiteral(1));
else if (value) writeAtStartOfBody = callRuntime("_textarea_value", value);
}
for (const attr of staticAttrs) {
const { name, value } = attr;
const { confident, computed } = value.extra || {};
const valueReferences = value.extra?.referencedBindings;
if (tagName === "option" && name === "value") {
write`${callRuntime("_attr_option_value", value)}`;
continue;
}
switch (name) {
case "class":
case "style": {
const helper = `_attr_${name}`;
if (confident) write`${getHTMLRuntime()[helper](computed)}`;
else write`${factorAttrConditional(buildAttrExpression(value, (branch) => {
const { confident, computed } = evaluate(branch);
return confident ? getHTMLRuntime()[helper](computed) : void 0;
}, (branch) => buildStringAttrAnd(helper, branch) || name === "class" && buildClassAttrExpression(branch) || callRuntime(helper, branch)))}`;
break;
}
default:
if (confident) write`${getHTMLRuntime()._attr(name, computed)}`;
else if (isEventHandler(name)) addHTMLEffectCall(tagSection, valueReferences);
else write`${factorAttrConditional(buildAttrExpression(value, (branch) => {
const { confident, computed } = evaluate(branch);
return confident ? getHTMLRuntime()._attr(name, computed) : void 0;
}, (branch) => buildLogicalAttr(name, branch) || callRuntime("_attr", _marko_compiler.types.stringLiteral(name), branch)))}`;
break;
}
}
const isOpenOnly = !!(tagDef && tagDef.parseOptions?.openTagOnly);
const isTextOnly = isTextOnlyNativeTag(tag);
const hasChildren = !!tag.node.body.body.length;
if (spreadExpression) {
addHTMLEffectCall(tagSection, tagExtra.referencedBindings);
if (isTextOnly || isOpenOnly || hasChildren || staticContentAttr) if (skipExpression) write`${callRuntime("_attrs_partial", spreadExpression, skipExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName))}`;
else write`${callRuntime("_attrs", spreadExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName))}`;
}
if (isOpenOnly || isTextOnly) write`>`;
else if (staticContentAttr) {
write`>`;
tagExtra[kTagContentAttr] = true;
tag.node.body.body = [_marko_compiler.types.expressionStatement(callRuntime("_attr_content", visitAccessor, getScopeIdIdentifier(tagSection), staticContentAttr.value, getSerializeGuard(tagSection, nodeBinding && getSerializeReason(tagSection, nodeBinding), true)))];
} else if (spreadExpression && !hasChildren) {
const serializeReason = getSerializeGuard(tagSection, nodeBinding && getSerializeReason(tagSection, nodeBinding), true);
tagExtra[kTagContentAttr] = true;
tag.node.body.body = [skipExpression ? _marko_compiler.types.expressionStatement(callRuntime("_attrs_partial_content", spreadExpression, skipExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), serializeReason)) : _marko_compiler.types.expressionStatement(callRuntime("_attrs_content", spreadExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), serializeReason))];
} else write`>`;
if (writeAtStartOfBody) write`${writeAtStartOfBody}`;
},
exit(tag) {
const tagExtra = tag.node.extra;
const nodeBinding = tagExtra[kNativeTagBinding];
const isOpenOnly = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.parseOptions?.openTagOnly;
const isTextOnly = isTextOnlyNativeTag(tag);
const selectArgs = htmlSelectArgs.get(tag.node);
const tagName = getCanonicalTagName(tag);
const tagSection = getSection(tag);
const markerSerializeReason = !tagExtra[kSkipEndTag] && nodeBinding && getSerializeReason(tagSection, nodeBinding);
const write = writeTo$1(tag, tagName === "html" || !markerSerializeReason && tagName === "body");
if (tagExtra[kTagContentAttr]) flushBefore(tag);
if (selectArgs) {
if (!tagExtra[kSkipEndTag]) write`</${tagName}>`;
flushInto(tag);
tag.insertBefore(_marko_compiler.types.expressionStatement(callRuntime("_attr_select_value", getScopeIdIdentifier(tagSection), nodeBinding && getScopeAccessorLiteral(nodeBinding), selectArgs.value, selectArgs.valueChange, _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement(tag.node.body.body)), selectArgs.serializeType)));
} else if (isTextOnly) {
const rawTextHelper = getRawTextEscapeHelper(tagName);
if (rawTextHelper) {
const body = bodyToTextLiteral(tag.node.body);
write`${_marko_compiler.types.isStringLiteral(body) ? getHTMLRuntime()[rawTextHelper](body.value) : callRuntime(rawTextHelper, body)}`;
} else for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoText(child)) write`${child.value}`;
else if (_marko_compiler.types.isMarkoPlaceholder(child)) write`${callRuntime("_escape", child.value)}`;
} else tag.insertBefore(tag.node.body.body).forEach((child) => child.skip());
if (!tagExtra[kSkipEndTag] && !isOpenOnly && !selectArgs) {
if (tagName === "head" && getMarkoOpts().linkAssets) write`${callRuntime("_flush_head")}`;
write`</${tagName}>`;
}
if (markerSerializeReason) markNode(tag, nodeBinding, markerSerializeReason, tagName === "html");
tag.remove();
}
},
dom: {
enter(tag) {
const tagName = getCanonicalTagName(tag);
const tagExtra = tag.node.extra;
const nodeBinding = tagExtra[kNativeTagBinding];
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
const tagSection = getSection(tag);
const visitAccessor = nodeBinding && getScopeAccessorLiteral(nodeBinding);
const { staticAttrs, staticControllable, staticContentAttr, skipExpression, spreadExpression, injectNonce } = getUsedAttrs(tagName, tag.node);
const isOpenOnly = !!(tagDef && tagDef.parseOptions?.openTagOnly);
const isTextOnly = isTextOnlyNativeTag(tag);
const hasChildren = !!tag.node.body.body.length;
if (injectNonce) addStatement("render", tagSection, void 0, _marko_compiler.types.expressionStatement(callRuntime("_attr_nonce", scopeIdentifier, getScopeAccessorLiteral(nodeBinding))), true);
if (staticControllable) {
const hasChangeHandler = !!staticControllable.attrs[1];
const defaultHelper = getDOMControllableDefaultHelper(staticControllable);
const referencedBindings = staticControllable.attrs.find(Boolean).value.extra?.referencedBindings;
const values = (hasChangeHandler ? staticControllable.attrs : staticControllable.attrs.toSpliced(1, 1)).map((attr) => attr?.value);
if (hasChangeHandler && defaultHelper !== `${staticControllable.helper}_default`) values.push(importRuntime(defaultHelper));
addStatement("render", tagSection, referencedBindings, _marko_compiler.types.expressionStatement(callRuntime(hasChangeHandler ? staticControllable.helper : defaultHelper, scopeIdentifier, visitAccessor, ...values)));
if (hasChangeHandler) addStatement("effect", tagSection, void 0, _marko_compiler.types.expressionStatement(callRuntime(`${staticControllable.helper}_script`, scopeIdentifier, visitAccessor)));
}
for (const attr of staticAttrs) {
const { name, value } = attr;
const { confident } = value.extra || {};
const valueReferences = value.extra?.referencedBindings;
switch (name) {
case "class":
case "style": {
const helper = `_attr_${name}`;
if (!confident) {
const nodeExpr = createScopeReadExpression(nodeBinding);
const meta = {
staticItems: void 0,
dynamicItems: void 0,
dynamicValues: void 0
};
let stmt;
trackDelimitedAttrValue(value, meta);
if (meta.dynamicItems) stmt = _marko_compiler.types.expressionStatement(callRuntime(helper, nodeExpr, value));
else if (meta.dynamicValues) {
const keys = Object.keys(meta.dynamicValues);
if (keys.length === 1) {
const [key] = keys;
const value = meta.dynamicValues[key];
stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_item`, nodeExpr, _marko_compiler.types.stringLiteral(key), value));
} else {
const props = [];
for (const key of keys) {
const value = meta.dynamicValues[key];
props.push(_marko_compiler.types.objectProperty(toPropertyName(key), value));
}
stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_items`, nodeExpr, _marko_compiler.types.objectExpression(props)));
}
}
if (stmt) addStatement("render", tagSection, valueReferences, stmt, true);
}
break;
}
default:
if (confident) break;
else if (isEventHandler(name)) addStatement("effect", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_on", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(getEventHandlerName(name)), value)));
else addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_attr", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(name), value)), true);
break;
}
}
if (spreadExpression) {
const canHaveAttrContent = !(isTextOnly || isOpenOnly || hasChildren || staticContentAttr);
const name = tag.get("name");
const staticName = name.isStringLiteral() ? name.node.value : void 0;
const controllable = !staticControllable && controllableClaimFor(staticName);
if (skipExpression) addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime(canHaveAttrContent ? "_attrs_partial_content" : "_attrs_partial", scopeIdentifier, visitAccessor, spreadExpression, skipExpression, controllable && importRuntime(controllable))));
else addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime(canHaveAttrContent ? "_attrs_content" : "_attrs", scopeIdentifier, visitAccessor, spreadExpression, controllable && importRuntime(controllable))));
enableControllable(controllableFeatureFor(staticName));
addStatement("effect", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attrs_script", scopeIdentifier, visitAccessor)));
}
if (staticContentAttr) addStatement("render", tagSection, staticContentAttr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attr_content", scopeIdentifier, visitAccessor, staticContentAttr.value)), true);
},
exit(tag) {
const nodeBinding = tag.node.extra[kNativeTagBinding];
const openTagOnly = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.parseOptions?.openTagOnly;
const tagName = getCanonicalTagName(tag);
if (!openTagOnly) if (tagName !== "textarea" && isTextOnlyNativeTag(tag)) {
const textLiteral = bodyToTextLiteral(tag.node.body, tagName === "title");
if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", getSection(tag), textLiteral.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text_content", createScopeReadExpression(nodeBinding), textLiteral)), true);
} else tag.insertBefore(tag.node.body.body).forEach((child) => child.skip());
tag.remove();
}
}
})
};
function getSpreadControllableValueProps(tagName) {
switch (tagName) {
case "input": return [
"value",
"checked",
"checkedValue"
];
case "select":
case "textarea": return ["value"];
case "details":
case "dialog": return ["open"];
}
}
function getRelatedControllable(tagName, attrs) {
switch (tagName) {
case "input":
if (attrs.checked || attrs.checkedChange) return {
special: false,
helper: "_attr_input_checked",
attrs: [attrs.checked, attrs.checkedChange]
};
if (attrs.checkedValue || attrs.checkedValueChange) return {
special: true,
helper: "_attr_input_checkedValue",
attrs: [
attrs.checkedValue,
attrs.checkedValueChange,
attrs.value
]
};
if (attrs.value || attrs.valueChange) {
const valueMode = getInputValueMode(attrs.type);
if (valueMode === "attribute" && !attrs.valueChange) break;
return {
special: false,
helper: "_attr_input_value",
attrs: [attrs.value, attrs.valueChange],
valueMode
};
}
break;
case "select":
if (attrs.value || attrs.valueChange) return {
special: true,
helper: "_attr_select_value",
attrs: [attrs.value, attrs.valueChange]
};
break;
case "textarea":
if (attrs.value || attrs.valueChange) return {
special: true,
helper: "_attr_textarea_value",
attrs: [attrs.value, attrs.valueChange]
};
break;
case "details":
case "dialog":
if (attrs.open || attrs.openChange) return {
special: false,
helper: `_attr_${tagName}_open`,
attrs: [attrs.open, attrs.openChange]
};
break;
}
}
function getInputValueMode(typeAttr) {
if (!typeAttr) return;
const type = evaluate(typeAttr.value);
if (!type.confident) return "dynamic";
if (typeof type.computed === "string") switch (type.computed.toLowerCase()) {
case "button":
case "checkbox":
case "hidden":
case "image":
case "radio":
case "reset":
case "submit": return "attribute";
}
}
function getDOMControllableDefaultHelper(controllable) {
return controllable.helper === "_attr_input_value" && controllable.valueMode ? `_attr_input_value_${controllable.valueMode}_default` : `${controllable.helper}_default`;
}
function getUsedAttrs(tagName, tag, staticOnly) {
const seen = Object.create(null);
const { attributes } = tag;
const maybeStaticAttrs = /* @__PURE__ */ new Set();
const skipProps = /* @__PURE__ */ new Set();
let spreadExpression;
let skipExpression;
let spreadProps;
let staticControllable;
let staticContentAttr;
let injectNonce = isInjectNonceTag(tagName);
for (let i = attributes.length; i--;) {
const attr = attributes[i];
const { value } = attr;
if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) {
if (!spreadProps) {
spreadProps = [];
staticControllable = getRelatedControllable(tagName, seen);
if (staticControllable && !staticControllable.attrs.every(Boolean)) {
for (const attr of staticControllable.attrs) if (attr) {
spreadProps.push(toObjectProperty(attr.name, attr.value));
maybeStaticAttrs.delete(attr);
}
staticControllable = void 0;
}
}
spreadProps.push(_marko_compiler.types.spreadElement(value));
} else if (!(seen[attr.name] || attr.name === "content" && tag.body.body.length)) {
seen[attr.name] = attr;
if (injectNonce && attr.name === "nonce") injectNonce = false;
if (spreadProps) spreadProps.push(toObjectProperty(attr.name, attr.value));
else if (attr.name === "content" && tagName !== "meta") staticContentAttr = attr;
else maybeStaticAttrs.add(attr);
}
}
if (!spreadProps) {
staticControllable = getRelatedControllable(tagName, seen);
if (!isDynamicControllable(staticControllable)) staticControllable = void 0;
}
if (staticControllable) {
for (const attr of staticControllable.attrs) if (attr) maybeStaticAttrs.delete(attr);
}
const staticAttrs = [...maybeStaticAttrs].reverse();
if (staticOnly) return {
injectNonce,
staticAttrs,
staticContentAttr,
staticControllable,
spreadExpression,
skipExpression
};
if (spreadProps) {
if (staticControllable) {
for (const attr of staticControllable.attrs) if (attr) skipProps.add(attr.name);
}
for (const { name } of staticAttrs) if (isEventHandler(name)) skipProps.add(`on-${getEventHandlerName(name)}`);
else skipProps.add(name);
if (injectNonce) {
injectNonce = false;
spreadProps.push(_marko_compiler.types.objectProperty(_marko_compiler.types.identifier("nonce"), _marko_compiler.types.memberExpression(isOutputHTML() ? callRuntime("$global") : toMemberExpression(scopeIdentifier, getAccessorProp().Global), _marko_compiler.types.identifier("cspNonce"))));
}
spreadExpression = propsToExpression(spreadProps.reverse());
}
if (skipProps.size) skipExpression = _marko_compiler.types.objectExpression(Array.from(skipProps, (name) => toObjectProperty(name, _marko_compiler.types.numericLiteral(1))));
return {
injectNonce,
staticAttrs,
staticContentAttr,
staticControllable,
spreadExpression,
skipExpression
};
}
function isInjectNonceTag(tagName) {
switch (tagName) {
case "script":
case "style": return true;
default: return false;
}
}
function assertValidNativeAttrName(tag, attr) {
const suggestion = getWrongAttrSuggestion(attr.name);
if (suggestion) throw tag.hub.buildError(attr.loc?.end && { loc: {
start: attr.loc.start,
end: {
line: attr.loc.start.line,
column: attr.loc.start.column + attr.name.length
}
} }, `\`${attr.name}\` is not a valid attribute, did you mean \`${suggestion}\`?`, Error);
}
function assertNativeAttrValueType(tag, attr) {
const { name } = attr;
if (name === "class" || name === "style" || name === "content" || isEventOrChangeHandler(name) || lowercaseEventHandlerReg.test(name)) return;
if (_marko_compiler.types.isFunction(attr.value)) throw tag.hub.buildError(attr, `The \`${name}\` attribute cannot be a function.`, Error);
if (_marko_compiler.types.isObjectExpression(attr.value)) throw tag.hub.buildError(attr, `The \`${name}\` attribute cannot be a plain object (it would render as \`[object Object]\`).`, Error);
}
function warnCamelCaseStyleKeys(tag, attr) {
const { value } = attr;
const objects = value.type === "ObjectExpression" ? [value] : value.type === "ArrayExpression" ? value.elements.filter((el) => el?.type === "ObjectExpression") : [];
for (const object of objects) for (const prop of object.properties) {
if (prop.type !== "ObjectProperty" || prop.computed) continue;
const { key } = prop;
const name = key.type === "Identifier" ? key.name : key.type === "StringLiteral" ? key.value : void 0;
if (name && !name.startsWith("--") && !name.includes("-") && /[A-Z]/.test(name)) (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, {
label: `\`${name}\` is not a CSS property name; the [\`style=\` object](https://markojs.com/docs/reference/native-tag#style) writes keys out verbatim (unlike the camelCased DOM style API), so this renders as invalid CSS the browser ignores. Use the kebab-case name \`${name.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()).replace(/^ms-/, "-ms-")}\`.`,
loc: key.loc ?? void 0
});
}
}
function assertNativeHandlerAttr(tag, attr) {
if (_marko_compiler.types.isObjectExpression(attr.value)) throw tag.hub.buildError(attr.value, `The \`${attr.name}\` ${isEventHandler(attr.name) ? "event handler" : "change handler"} on a [native tag](https://markojs.com/docs/reference/native-tag) must be a function. Attribute values in Marko are plain JavaScript expressions, not JSX; remove the wrapping \`{ }\` (e.g. \`${attr.name}=myHandler\` or \`${attr.name}() { ... }\`).`, Error);
if ((0, _marko_compiler_babel_utils.computeNode)(attr.value)?.value) throw tag.hub.buildError(attr.value, `The \`${attr.name}\` ${isEventHandler(attr.name) ? "event handler" : "change handler"} on a [native tag](https://markojs.com/docs/reference/native-tag) must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …).`, Error);
}
const lowercaseEventHandlerReg = /^on[a-z]/;
function assertValidNativeEventHandlerAttr(tag, attr) {
if (!lowercaseEventHandlerReg.test(attr.name)) return;
const { value } = attr;
let invalid = _marko_compiler.types.isFunction(value);
if (!invalid) {
const { confident, computed } = evaluate(value);
invalid = confident && !!computed && typeof computed !== "string";
}
if (invalid) {
const suggestion = "on" + attr.name[2].toUpperCase() + attr.name.slice(3);
throw tag.hub.buildError(value, `The \`${attr.name}\` attribute on a [native tag](https://markojs.com/docs/reference/native-tag) must be a string or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …). To attach an event listener, use the \`${suggestion}\` [event handler attribute](https://markojs.com/docs/reference/event-handling) instead.`, Error);
}
}
function getCanonicalTagName(tag) {
const tagName = getTagName(tag);
switch (tagName) {
case "html-script": return "script";
case "html-style": return "style";
default: return tagName;
}
}
function assertOptionInSelectWithValue(tag) {
let parent = tag.parentPath;
while (parent) {
if (parent.isMarkoTag()) {
if (analyzeTagNameType(parent) === 0) {
const parentName = getCanonicalTagName(parent);
if (parentName === "select") {
if (parent.node.attributes.some((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.name === "value" || attr.name === "valueChange"))) {
let hasValue = false;
const attributes = tag.get("attributes");
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i].node;
if (!_marko_compiler.types.isMarkoAttribute(attr) || attr.name === "value") hasValue = true;
else if (attr.name === "selected") throw attributes[i].buildCodeFrameError("The `selected` attribute is not supported on an `<option>` within a `<select>` that has a `value` attribute; include the option's `value` in the select's `value` instead.");
}
if (!hasValue) throw tag.buildCodeFrameError("An `<option>` within a `<select>` that has a `value` attribute must also have a `value` attribute.");
}
return;
}
if (parentName !== "optgroup") return;
} else if (!isControlFlowTag(parent)) return;
} else if (parent.isProgram()) return;
parent = parent.parentPath;
}
}
function getRawTextEscapeHelper(tagName) {
switch (tagName) {
case "script": return "_escape_script";
case "style": return "_escape_style";
}
}
function buildAttrExpression(value, serialize, dynamic) {
if (value.type === "ConditionalExpression") return _marko_compiler.types.conditionalExpression(value.test, buildAttrExpression(value.consequent, serialize, dynamic), buildAttrExpression(value.alternate, serialize, dynamic));
const serialized = serialize(value);
return serialized === void 0 ? dynamic(value) : _marko_compiler.types.stringLiteral(serialized);
}
function factorAttrConditional(value) {
if (value.type !== "ConditionalExpression") return value;
const consequent = factorAttrConditional(value.consequent);
const alternate = factorAttrConditional(value.alternate);
if (consequent.type === "StringLiteral" && alternate.type === "StringLiteral") {
const a = consequent.value;
const b = alternate.value;
const end = commonAttrPrefixEnd([a, b]);
if (end) return normalizeStringExpression([a.slice(0, end), _marko_compiler.types.conditionalExpression(value.test, _marko_compiler.types.stringLiteral(a.slice(end)), _marko_compiler.types.stringLiteral(b.slice(end)))]);
}
return _marko_compiler.types.conditionalExpression(value.test, consequent, alternate);
}
function commonAttrPrefixEnd(strings) {
let prefix = strings[0];
for (let i = 1; i < strings.length && prefix; i++) {
const s = strings[i];
const len = Math.min(prefix.length, s.length);
let j = 0;
while (j < len && prefix[j] === s[j]) j++;
prefix = prefix.slice(0, j);
}
return prefix.lastIndexOf("=") + 1;
}
function buildLogicalAttr(name, value) {
if (value.type !== "LogicalExpression") return;
const { confident, computed } = evaluate(value.right);
if (!confident) return;
const attr = getHTMLRuntime()._attr(name, computed);
return callRuntime(value.operator === "&&" ? "_attr_and" : value.operator === "||" ? "_attr_or" : "_attr_nullish", _marko_compiler.types.stringLiteral(name), value.left, _marko_compiler.types.stringLiteral(attr));
}
function buildStringAttrAnd(helper, value) {
if (value.type === "LogicalExpression" && value.operator === "&&") {
const { confident, computed } = evaluate(value.right);
if (confident) return _marko_compiler.types.conditionalExpression(value.left, _marko_compiler.types.stringLiteral(getHTMLRuntime()[helper](computed)), _marko_compiler.types.stringLiteral(""));
}
}
const MAX_PRECOMPUTED_CLASS_TOGGLES = 4;
function buildClassAttrExpression(value) {
if (value.type !== "ObjectExpression" && value.type !== "ArrayExpression") return;
const meta = {
staticItems: void 0,
dynamicItems: void 0,
dynamicValues: void 0
};
trackDelimitedAttrValue(value, meta);
if (meta.dynamicItems || !meta.staticItems || !meta.dynamicValues) return;
const base = toDelimitedString(meta.staticItems, " ", stringifyClassObject);
if (!base) return;
const { _attr_class } = getHTMLRuntime();
const keys = Object.keys(meta.dynamicValues);
if (keys.length === 1) {
const [key] = keys;
return _marko_compiler.types.conditionalExpression(meta.dynamicValues[key], _marko_compiler.types.stringLiteral(_attr_class(base + " " + key)), _marko_compiler.types.stringLiteral(_attr_class(base)));
}
if (keys.length <= MAX_PRECOMPUTED_CLASS_TOGGLES) {
const combos = [];
for (let mask = 0; mask < 1 << keys.length; mask++) {
let classes = base;
for (let i = 0; i < keys.length; i++) if (mask & 1 << i) classes += " " + keys[i];
combos.push(_attr_class(classes));
}
const end = commonAttrPrefixEnd(combos);
const table = generateUidIdentifier("class");
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(table, _marko_compiler.types.arrayExpression(combos.map((combo) => _marko_compiler.types.stringLiteral(combo.slice(end)))))])], true));
let index = _marko_compiler.types.conditionalExpression(meta.dynamicValues[keys[0]], _marko_compiler.types.numericLiteral(1), _marko_compiler.types.numericLiteral(0));
for (let i = 1; i < keys.length; i++) index = _marko_compiler.types.binaryExpression("+", index, _marko_compiler.types.conditionalExpression(meta.dynamicValues[keys[i]], _marko_compiler.types.numericLiteral(1 << i), _marko_compiler.types.numericLiteral(0)));
const lookup = _marko_compiler.types.memberExpression(_marko_compiler.types.cloneNode(table), index, true);
return normalizeStringExpression([combos[0].slice(0, end), lookup]);
}
let classes = _marko_compiler.types.stringLiteral(base);
for (const key of keys) classes = _marko_compiler.types.binaryExpression("+", classes, _marko_compiler.types.conditionalExpression(meta.dynamicValues[key], _marko_compiler.types.stringLiteral(" " + key), _marko_compiler.types.stringLiteral("")));
return callRuntime("_attr_class", classes);
}
function trackDelimitedAttrValue(expr, meta) {
switch (expr.type) {
case "ObjectExpression":
trackDelimitedAttrObjectProperties(expr, meta);
break;
case "ArrayExpression":
trackDelimitedAttrArrayItems(expr, meta);
break;
default:
(meta.dynamicItems ||= []).push(expr);
break;
}
}
function trackDelimitedAttrArrayItems(arr, meta) {
for (const item of arr.elements) if (item) switch (item.type) {
case "ArrayExpression":
trackDelimitedAttrArrayItems(item, meta);
break;
case "ObjectExpression":
trackDelimitedAttrObjectProperties(item, meta);
break;
case "SpreadElement":
if (item.argument.type === "ArrayExpression") trackDelimitedAttrArrayItems(item.argument, meta);
else (meta.dynamicItems ||= []).push(item);
break;
default: {
const evalItem = evaluate(item);
if (evalItem.confident) (meta.staticItems ||= []).push(evalItem.computed);
else (meta.dynamicItems ||= []).push(item);
break;
}
}
}
function trackDelimitedAttrObjectProperties(obj, meta) {
let staticProps;
let dynamicProps;
for (const prop of obj.properties) {
if (prop.type !== "ObjectProperty" || prop.computed) {
(dynamicProps ||= []).push(prop);
continue;
}
let key;
if (prop.key.type === "Identifier") key = prop.key.name;
else {
const keyEval = evaluate(prop.key);
if (keyEval.confident && typeof keyEval.computed === "string" && !/^$|\s/.test(keyEval.computed)) key = keyEval.computed + "";
else {
(dynamicProps ||= []).push(prop);
continue;
}
}
const value = prop.value;
const propEval = evaluate(value);
if (propEval.confident) (staticProps ||= {})[key] = propEval.computed;
else (meta.dynamicValues ||= {})[key] = value;
}
if (staticProps) (meta.staticItems ||= []).push(staticProps);
if (dynamicProps) (meta.dynamicItems ||= []).push(_marko_compiler.types.objectExpression(dynamicProps));
}
function isDynamicControllable(controllable) {
if (controllable) return controllable.special || !!(controllable.attrs[1] || controllable.attrs.find(Boolean).value.extra?.referencedBindings);
return false;
}
function buildUndefined$1() {
return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
}
/** How a spread claims its controlled attrs during render; nothing for the many
* tags that control nothing, and nothing when a static attr owns the
* controllable, since then the spread must leave the slots it wrote alone. */
function controllableClaimFor(tagName) {
switch (tagName) {
case "input": return "_controllable_input";
case "textarea": return "_controllable_textarea";
case "select": return "_controllable_select";
case "details":
case "dialog": return "_controllable_open";
}
}
/** The resume-pass feature for a tag: `_attrs_script` resolves the control
* kind at run time, and a run-time tag name can be any of them. */
function controllableFeatureFor(tagName) {
switch (tagName) {
case "input": return "controllable-input";
case "textarea": return "controllable-textarea";
case "select": return "controllable-select";
case "details":
case "dialog": return "controllable-open";
case void 0: return "controllable";
}
}
function enableControllable(feature) {
if (feature) importRuntimeFeature(feature);
}
//#endregion
//#region src/translator/util/is-only-child-in-parent.ts
const kOnlyChildInParent = Symbol("only child in parent");
const kNodeRef = Symbol("potential only child node ref");
function getOnlyChildParentTagName(tag, branchSize = 1) {
const extra = tag.node.extra;
if (extra[kOnlyChildInParent] !== void 0) return extra[kOnlyChildInParent];
const parentTag = getParentTag(tag);
return extra[kOnlyChildInParent] = parentTag && analyzeTagNameType(parentTag) === 0 && parentTag.node.name.type === "StringLiteral" && tag.parent.body.filter((node) => node.type !== "MarkoComment").length === branchSize ? parentTag.node.name.value : false;
}
function getOptimizedOnlyChildNodeBinding(tag, section, branchSize = 1) {
if (getOnlyChildParentTagName(tag, branchSize)) {
const parentTag = getParentTag(tag).node;
const parentTagName = parentTag.name?.value;
return (parentTag.extra ??= {})[kNativeTagBinding] ??= createBinding("#" + parentTagName.toLowerCase(), 0, section);
} else return (tag.node.extra ??= {})[kNodeRef] ??= createBinding("#text", 0, section);
}
//#endregion
//#region src/translator/util/to-first-statement-or-block.ts
function toFirstStatementOrBlock(body) {
if (Array.isArray(body)) {
if (body.length === 1) return body[0];
return _marko_compiler.types.blockStatement(body);
}
return body;
}
//#endregion
//#region src/translator/core/if.ts
const kStatefulReason$1 = Symbol("<if> stateful reason");
const BRANCHES_LOOKUP = /* @__PURE__ */ new WeakMap();
const IfTag = {
analyze(tag) {
assertValidCondition(tag);
if (tag.node.body.attributeTags) return;
if (isLastBranch(tag)) {
const branches = getBranches(tag);
const [ifTag] = branches[0];
const ifTagSection = getOrCreateSection(ifTag);
const ifTagExtra = ifTag.node.extra ??= {};
const mergeReferenceNodes = [];
if (!getOnlyChildParentTagName(ifTag, branches.length)) {
visit(ifTag, 37);
enterShallow(ifTag);
}
const sectionAccessor = getBranchSectionAccessor(getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length));
for (const [branchTag, branchBodySection] of branches) {
if (branchBodySection) initBranchSection(branchBodySection, ifTagExtra, sectionAccessor);
if (branchTag.node.attributes.length) mergeReferenceNodes.push(branchTag.node.attributes[0].value);
}
mergeReferences(ifTagSection, ifTag.node, mergeReferenceNodes);
addSerializeExpr(ifTagSection, ifTagExtra, kStatefulReason$1);
}
},
translate: translateByTarget({
html: {
enter(tag) {
if (tag.node.body.attributeTags) return;
const bodySection = getSectionForBody(tag.get("body"));
flushBefore(tag);
if (bodySection) setSectionParentIsOwner(bodySection, true);
},
exit(tag) {
if (tag.node.body.attributeTags) return;
const tagBody = tag.get("body");
const bodySection = getSectionForBody(tagBody);
if (bodySection) {
const branches = getBranches(tag);
const [ifTag] = branches[0];
const ifTagSection = getSection(ifTag);
resumeOwnerByMarkerWhenStatic(ifTagSection, bodySection, getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length), kStatefulReason$1);
flushInto(tag);
writeHTMLResumeStatements(tagBody);
}
if (isLastBranch(tag)) {
const branches = getBranches(tag);
const [ifTag] = branches[0];
const ifTagSection = getSection(ifTag);
const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
const onlyChildParentTagName = getOnlyChildParentTagName(ifTag, branches.length);
const markerSerializeReason = getSerializeReason(ifTagSection, nodeBinding);
const nextTag = tag.getNextSibling();
let branchSerializeReasons;
let statement;
let singleChild = true;
for (const [, branchBodySection] of branches) if (!(branchBodySection?.content?.singleChild && branchBodySection.content.startType !== 4)) {
singleChild = false;
break;
}
for (let i = branches.length; i--;) {
const [branchTag, branchBodySection] = branches[i];
const bodyStatements = branchTag.node.body.body;
if (branchBodySection) {
const branchSerializeReason = getSerializeReason(branchBodySection, kBranchSerializeReason);
if (branchSerializeReason) {
if (branchSerializeReasons !== true) branchSerializeReasons = branchSerializeReason === true || branchSerializeReason.state ? true : sourcesUtil.add(branchSerializeReasons, branchSerializeReason);
bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
}
}
const [testAttr] = branchTag.node.attributes;
const curStatement = toFirstStatementOrBlock(bodyStatements);
if (testAttr) statement = _marko_compiler.types.ifStatement(testAttr.value, curStatement, statement);
else statement = curStatement;
branchTag.remove();
}
if (branchSerializeReasons) {
const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
if (skipParentEnd) getParentTag(ifTag).node.extra[kSkipEndTag] = true;
const statefulSerializeArg = getSerializeGuard(ifTagSection, getSerializeReason(ifTagSection, kStatefulReason$1), !(skipParentEnd || singleChild));
const markerSerializeArg = getSerializeGuard(ifTagSection, markerSerializeReason, !statefulSerializeArg);
const cbNode = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([statement]));
statement = _marko_compiler.types.expressionStatement(callRuntime("_if", cbNode, getScopeIdIdentifier(ifTagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuardForAny(ifTagSection, branchSerializeReasons, !markerSerializeArg), markerSerializeArg, statefulSerializeArg, skipParentEnd ? _marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`) : singleChild ? _marko_compiler.types.numericLiteral(0) : void 0, singleChild ? _marko_compiler.types.numericLiteral(1) : void 0));
}
nextTag.insertBefore(statement);
}
}
},
dom: {
enter(tag) {
if (tag.node.body.attributeTags) return;
const bodySection = getSectionForBody(tag.get("body"));
if (bodySection) setSectionParentIsOwner(bodySection, true);
},
exit(tag) {
if (tag.node.body.attributeTags) return;
if (isLastBranch(tag)) {
const branches = getBranches(tag);
const [ifTag] = branches[0];
const ifTagSection = getSection(ifTag);
const ifTagExtra = branches[0][0].node.extra;
const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
let expr = _marko_compiler.types.numericLiteral(branches.length);
for (let i = branches.length; i--;) {
const [branchTag, branchBodySection] = branches[i];
const [testAttr] = branchTag.node.attributes;
const consequent = _marko_compiler.types.numericLiteral(branchBodySection ? i : -1);
if (branchBodySection) setClosureSignalBuilder(branchTag, (_closure, render) => {
return callRuntime("_if_closure", getScopeAccessorLiteral(nodeRef, true), _marko_compiler.types.numericLiteral(i), render);
});
branchTag.remove();
expr = testAttr ? _marko_compiler.types.conditionalExpression(testAttr.value, consequent, expr) : consequent;
}
const signal = getSignal(ifTagSection, nodeRef, "if");
signal.build = () => {
const rendererArgs = [];
for (const [_, branchBodySection] of branches) if (branchBodySection) rendererArgs.push(...getBranchRendererArgs(branchBodySection).slice(0, 3));
else rendererArgs.push(void 0, void 0, void 0);
return callRuntime("_if", getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(rendererArgs));
};
addValue(ifTagSection, ifTagExtra.referencedBindings, signal, expr);
}
}
}
}),
parseOptions: { controlFlow: true },
autocomplete: [{
snippet: "if=${1:condition}",
description: "Use to display content only if the condition is met.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
}]
};
const ElseIfTag = {
...IfTag,
autocomplete: [{
snippet: "else-if=${1:condition}",
description: "Use after an <if> or <else-if> tag to display content if those conditions do not match and this one does.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
}]
};
const ElseTag = {
...IfTag,
autocomplete: [{
description: "Use after an <if> or <else-if> tag to display content if those conditions do not match.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
}]
};
function flattenTextOnlyConditional(rootTag) {
if (!isCoreTagName(rootTag, "if")) return;
const tagBody = rootTag.parentPath;
if (!tagBody.isMarkoTagBody()) return;
const parentTag = tagBody.parentPath;
if (!parentTag.isMarkoTag() || analyzeTagNameType(parentTag) !== 0) return;
const { _escape } = getHTMLRuntime();
const branches = [];
let cur = rootTag;
do {
const tag = cur;
const { node } = tag;
const body = node.body.body;
if (node.body.attributeTags || !body.length) return;
const [attr] = node.attributes;
if (isCoreTagName(tag, "else")) {
if (node.attributes.length > 1 || attr && (!_marko_compiler.types.isMarkoAttribute(attr) || attr.name !== "if")) return;
} else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !(attr.default || attr.name === "value")) return;
for (const child of body) if (_marko_compiler.types.isMarkoText(child)) {
if (_escape(child.value) !== child.value) return;
} else if (!_marko_compiler.types.isMarkoPlaceholder(child) || !child.escape) return;
branches.push(tag);
let next = cur.getNextSibling();
while (next.node && next.isMarkoComment()) next = next.getNextSibling();
cur = next;
} while (cur.node && (isCoreTagName(cur, "else-if") || isCoreTagName(cur, "else")));
for (const branchTag of branches) assertValidCondition(branchTag);
let expr = _marko_compiler.types.stringLiteral("");
let rawText = false;
for (let i = branches.length; i--;) {
const branchTag = branches[i];
const text = bodyToRawTextLiteral(branchTag.node.body);
rawText ||= _marko_compiler.types.isTemplateLiteral(text);
const [conditionAttr] = branchTag.node.attributes;
expr = conditionAttr ? _marko_compiler.types.conditionalExpression(conditionAttr.value, text, expr) : text;
}
for (let i = branches.length; i-- > 1;) branches[i].remove();
const placeholder = _marko_compiler.types.markoPlaceholder(expr, true);
if (rawText) (placeholder.extra ??= {})[kRawText] = true;
rootTag.replaceWith(placeholder);
}
function assertValidCondition(tag) {
const conditionTagName = getTagName(tag);
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag, conditionTagName === "else" ? "Write the condition as an attribute instead: `<else if=condition>`." : `Write the condition as a value attribute instead: \`<${conditionTagName}=condition>\`.`);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertHasBody$1(tag);
assertNoSpreadAttrs(tag);
switch (getTagName(tag)) {
case "if":
assertHasValueAttribute$1(tag);
break;
case "else-if":
assertHasValueAttribute$1(tag);
assertHasPrecedingCondition(tag);
break;
case "else":
assertOptionalIfAttribute(tag);
assertHasPrecedingCondition(tag);
break;
}
}
function assertHasPrecedingCondition(tag) {
let prev = tag.getPrevSibling();
while (prev.node && prev.isMarkoComment()) prev = prev.getPrevSibling();
if (!isConditionTag(prev) || getTagName(prev) === "else" && !prev.node.attributes.length) throw tag.buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#if--else) must have a preceding \`<if=cond>\` or \`<else if=cond>\`.`);
}
function assertHasBody$1(tag) {
if (!(tag.node.body.body.length || tag.node.attributeTags.length)) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires [body content](https://markojs.com/docs/reference/language#tag-content).`);
}
function assertHasValueAttribute$1(tag) {
const { node } = tag;
const [valueAttr] = node.attributes;
if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !(valueAttr.default || valueAttr.name === "value")) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
if (node.attributes.length > 1) {
const start = node.attributes[1].loc?.start;
const end = node.attributes[node.attributes.length - 1].loc?.end;
const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`;
if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
else throw tag.hub.buildError({ loc: {
start,
end
} }, msg, Error);
}
}
function assertOptionalIfAttribute(tag) {
const { node } = tag;
const [ifAttr] = node.attributes;
if (node.attributes.length > 1 || ifAttr && ifAttr.name !== "if") {
const start = node.attributes[0].loc?.start;
const end = node.attributes[node.attributes.length - 1].loc?.end;
const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports an \`if=\` attribute.`;
if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
else throw tag.hub.buildError({ loc: {
start,
end
} }, msg, Error);
}
}
function getBranches(tag) {
let branches = BRANCHES_LOOKUP.get(tag);
if (!branches) {
let curTag = tag;
branches = [];
do {
BRANCHES_LOOKUP.set(curTag, branches);
branches.push([curTag, startSection(curTag.get("body"))]);
while ((curTag = curTag.getNextSibling()).isMarkoComment());
} while (isCoreTagName(curTag, "else") || isCoreTagName(curTag, "else-if"));
}
return branches;
}
function isLastBranch(tag) {
const branches = getBranches(tag);
return branches[branches.length - 1][0] === tag;
}
//#endregion
//#region src/translator/core/textarea.ts
function preAnalyze$1(tag) {
if (tag.node.body.body.length) {
const [firstChild] = tag.node.body.body;
if (firstChild.type === "MarkoText") firstChild.value = firstChild.value.replace(/^\r?\n/, "");
const parts = [];
for (const child of tag.node.body.body) if (child.type === "MarkoText") parts.push((0, _marko_compiler_babel_utils.decodeHTML)(child.value));
else if (child.type === "MarkoPlaceholder" && child.escape) parts.push(child.value);
else throw (0, _marko_compiler_babel_utils.getFile)().hub.buildError(child, "Unexpected content in textarea, only text and placeholders are supported.", SyntaxError);
const textValue = normalizeStringExpression(parts);
if (textValue) {
const valueAttr = tag.node.attributes.find((attr) => _marko_compiler.types.isMarkoAttribute(attr) && attr.name === "value");
if (valueAttr) throw (0, _marko_compiler_babel_utils.getFile)().hub.buildError(valueAttr, "A textarea cannot have both a value attribute and body content.", SyntaxError);
tag.node.attributes.push(_marko_compiler.types.markoAttribute("value", textValue));
}
tag.node.body.body = [];
}
}
//#endregion
//#region src/translator/util/with-previous-location.ts
function withPreviousLocation(newNode, originalNode) {
newNode.start = originalNode.start;
newNode.loc = originalNode.loc;
newNode.end = originalNode.end;
return newNode;
}
//#endregion
//#region src/translator/visitors/program/pre-analyze.ts
const TAG_NAME_IDENTIFIER_REG = /^[A-Z][a-zA-Z0-9_$]*$/;
const BINDING_CHANGE_HANDLER = /* @__PURE__ */ new WeakMap();
function preAnalyze(program) {
normalizeBody(program.get("body"));
}
function normalizeBody(body) {
if (body?.length) {
for (const child of body) if (child.isMarkoTag()) {
flattenTextOnlyConditional(child);
if (child.isMarkoTag()) normalizeTag(child);
} else if (child.isMarkoPlaceholder()) hoistStaticPlaceholderText(child);
}
}
function hoistStaticPlaceholderText(placeholder) {
const { node } = placeholder;
const normalized = normalizeStringExpression([node.value]);
if (!normalized || !_marko_compiler.types.isTemplateLiteral(normalized)) return;
node.value = normalized;
const { _escape } = getHTMLRuntime();
const { quasis } = normalized;
const lastIndex = quasis.length - 1;
const leading = quasis[0].value.cooked ?? "";
const trailing = quasis[lastIndex].value.cooked ?? "";
if (leading && _escape(leading) === leading) {
insertStaticText(placeholder, leading, true);
quasis[0].value = {
raw: "",
cooked: ""
};
}
if (trailing && _escape(trailing) === trailing) {
insertStaticText(placeholder, trailing, false);
quasis[lastIndex].value = {
raw: "",
cooked: ""
};
}
}
function insertStaticText(placeholder, value, before) {
const sibling = before ? placeholder.getPrevSibling() : placeholder.getNextSibling();
if (sibling.isMarkoText()) sibling.node.value = before ? sibling.node.value + value : value + sibling.node.value;
else if (before) placeholder.insertBefore(_marko_compiler.types.markoText(value));
else placeholder.insertAfter(_marko_compiler.types.markoText(value));
}
function normalizeTag(tag) {
const { node } = tag;
const { name, attributes } = node;
let attrNameReg = userAttrNameReg;
if (name.type === "StringLiteral") {
const tagName = name.value;
if (tag.scope.getBinding(tagName) && TAG_NAME_IDENTIFIER_REG.test(tagName)) node.name = withPreviousLocation(_marko_compiler.types.identifier(tagName), name);
}
normalizeBody(tag.get("body").get("body"));
normalizeBody(tag.get("attributeTags"));
if (node.var) {
const insertions = getAssignmentInsertions(node.var);
if (insertions) tag.insertAfter(insertions);
}
if (node.body.params.length) {
let insertions;
for (const param of node.body.params) insertions = getAssignmentInsertions(param, insertions);
if (insertions) node.body.body = [...insertions, ...node.body.body];
}
const nativeTagDef = getStaticNativeTagDef(tag);
if (nativeTagDef) {
if (!_marko_compiler.types.isStringLiteral(node.name)) {
node.name = withPreviousLocation(_marko_compiler.types.stringLiteral(nativeTagDef.name), node.name);
node.tagDef = nativeTagDef;
}
attrNameReg = htmlAttrNameReg;
if (nativeTagDef.parseOptions?.openTagOnly && node.body.body.length) throw tag.hub.buildError(node.body.body[0], `The \`<${nativeTagDef.name}>\` tag cannot have content, so it does not support a body.`);
if (nativeTagDef.name === "textarea") preAnalyze$1(tag);
}
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i];
if (_marko_compiler.types.isMarkoAttribute(attr)) {
if (attr.bound) {
attributes.splice(++i, 0, getChangeHandler(tag, attr));
attr.bound = false;
} else if (attr.modifier != null) attr.name += ":" + attr.modifier;
if (attrNameReg.test(attr.name)) throw tag.hub.buildError(attr.loc?.end && { loc: {
start: attr.loc.start,
end: {
line: attr.loc.start.line,
column: attr.loc.start.column + attr.name.length
}
} }, "Invalid attribute name.");
attr.modifier = null;
}
}
}
function getStaticNativeTagDef(tag) {
const { name } = tag.node;
if (_marko_compiler.types.isStringLiteral(name)) return (0, _marko_compiler_babel_utils.isNativeTag)(tag) ? (0, _marko_compiler_babel_utils.getTagDef)(tag) : void 0;
if (_marko_compiler.types.isTemplateLiteral(name) && name.quasis.length === 1) {
const tagDef = (0, _marko_compiler_babel_utils.getTagDefForTagName)((0, _marko_compiler_babel_utils.getFile)(), name.quasis[0].value.cooked);
if (tagDef?.taglibId === "marko-html" && tagDef.html && !tagDef.template && !tagDef.renderer) return tagDef;
}
}
function getChangeHandler(tag, attr) {
const changeAttrName = attr.name + "Change";
let modifier;
if (attr.modifier != null) {
if (!_marko_compiler.types.isValidIdentifier(attr.modifier)) throw tag.hub.buildError(attr.value.loc?.end && { loc: {
start: {
line: attr.value.loc.start.line,
column: attr.value.loc.start.column - attr.modifier.length - 2
},
end: {
line: attr.value.loc.start.line,
column: attr.value.loc.start.column - 2
}
} }, "Bound attribute refinement shorthand must be a valid JavaScript identifier.");
modifier = withPreviousLocation(_marko_compiler.types.identifier(attr.modifier), attr);
}
if (_marko_compiler.types.isIdentifier(attr.value)) {
const binding = tag.scope.getBinding(attr.value.name);
if (!binding) return _marko_compiler.types.markoAttribute(changeAttrName, buildChangeHandlerFunction(attr.value, modifier));
const modifierKey = modifier?.name ?? "";
let handlerByModifier = BINDING_CHANGE_HANDLER.get(binding.identifier);
if (!handlerByModifier) BINDING_CHANGE_HANDLER.set(binding.identifier, handlerByModifier = /* @__PURE__ */ new Map());
const existingChangedAttr = handlerByModifier.get(modifierKey);
if (!existingChangedAttr) {
const bindingIdentifierPath = binding.path.getOuterBindingIdentifierPaths()[binding.identifier.name];
let changeAttrExpr = bindingIdentifierPath ? bindingIdentifierPath.parentPath === binding.path ? buildChangeHandlerFunction(attr.value, modifier) : bindingIdentifierPath.parentPath.isObjectProperty() ? getChangeHandlerFromObjectPattern(bindingIdentifierPath.parentPath) : void 0 : void 0;
if (!changeAttrExpr) throw tag.hub.buildError(attr.value, bindingIdentifierPath?.parentPath?.isArrayPattern() ? `Cannot two-way bind to \`${attr.value.name}\` because it comes from array destructuring, which has no change handler. Use object destructuring or pass an explicit \`${changeAttrName}\` attribute.` : bindingIdentifierPath?.parentPath?.isObjectProperty({ computed: true }) ? `Cannot two-way bind to \`${attr.value.name}\` because it is destructured with a dynamically computed key, so its change handler cannot be derived. Use a static key or pass an explicit \`${changeAttrName}\` attribute.` : "Unable to bind to value.");
if (modifier && _marko_compiler.types.isIdentifier(changeAttrExpr)) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.cloneNode(changeAttrExpr), modifier));
const changeHandlerAttr = _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
handlerByModifier.set(modifierKey, changeHandlerAttr);
return changeHandlerAttr;
}
if (existingChangedAttr.type === "Identifier") return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(existingChangedAttr.name), attr.value));
const markoRoot = isMarko(binding.path) ? binding.path : getMarkoRoot(binding.path);
if (!(markoRoot?.isMarkoTag() || markoRoot?.isMarkoTagBody())) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
const changeHandlerId = generateUid(changeAttrName);
const changeHandlerConst = _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", existingChangedAttr.value, null, null, true)], _marko_compiler.types.markoTagBody([]), null, _marko_compiler.types.identifier(changeHandlerId));
handlerByModifier.set(modifierKey, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
if (markoRoot.isMarkoTag()) markoRoot.insertAfter(changeHandlerConst);
else markoRoot.unshiftContainer("body", changeHandlerConst);
return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(changeHandlerId), attr.value));
} else if (_marko_compiler.types.isMemberExpression(attr.value) || _marko_compiler.types.isOptionalMemberExpression(attr.value)) {
const prop = attr.value.property;
if (!_marko_compiler.types.isPrivateName(attr.value.property)) {
const memberObj = _marko_compiler.types.cloneNode(attr.value.object);
const memberProp = !attr.value.computed && prop.type === "Identifier" ? withPreviousLocation(_marko_compiler.types.identifier(prop.name + "Change"), prop) : _marko_compiler.types.binaryExpression("+", _marko_compiler.types.cloneNode(prop), _marko_compiler.types.stringLiteral("Change"));
const computed = memberProp.type !== "Identifier";
let changeAttrExpr = attr.value.optional ? _marko_compiler.types.optionalMemberExpression(memberObj, memberProp, computed, true) : _marko_compiler.types.memberExpression(memberObj, memberProp, computed);
if (modifier) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.memberExpression(memberObj, memberProp, computed), modifier));
return _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
}
}
throw tag.hub.buildError(attr.value, "Attributes may only be bound to identifiers or member expressions");
}
function buildModifierForwarder(changeHandler, modifier) {
const newValueId = generateUid("next");
return _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier(newValueId)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(changeHandler, [_marko_compiler.types.callExpression(_marko_compiler.types.cloneNode(modifier), [_marko_compiler.types.identifier(newValueId)])]))]));
}
function buildChangeHandlerFunction(id, modifier) {
const newId = "_new_" + id.name;
let newValue = withPreviousLocation(_marko_compiler.types.identifier(newId), id);
if (modifier) newValue = _marko_compiler.types.callExpression(modifier, [newValue]);
return _marko_compiler.types.arrowFunctionExpression([withPreviousLocation(_marko_compiler.types.identifier(newId), id)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", withPreviousLocation(_marko_compiler.types.identifier(id.name), id), newValue))]));
}
function getChangeHandlerFromObjectPattern(parent) {
let changeKey;
const pattern = parent.parentPath;
const keyName = getStaticKeyName(parent.node);
if (keyName === void 0) return;
const searchKey = `${keyName}Change`;
for (const prop of pattern.get("properties")) if (prop.isObjectProperty()) {
const propValue = prop.get("value");
if (getStaticKeyName(prop.node) === searchKey && propValue.isIdentifier()) {
changeKey = propValue.node;
break;
}
}
if (!changeKey) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.stringLiteral(searchKey), changeKey = generateUidIdentifier(searchKey)));
return changeKey;
}
function getStaticKeyName(prop) {
return prop.computed && !_marko_compiler.types.isStringLiteral(prop.key) ? void 0 : getLiteralName(prop.key);
}
function getLiteralName(node) {
switch (node.type) {
case "Identifier": return node.name;
case "StringLiteral": return node.value;
}
}
function getAssignmentInsertions(node, insertions) {
switch (node.type) {
case "ObjectPattern":
for (const prop of node.properties) if (prop.type === "ObjectProperty") if (prop.value.type === "AssignmentPattern") {
const { left, right } = prop.value;
const sourceName = generateUid(getLiteralName(left) || getLiteralName(prop.key) || "pattern");
prop.shorthand = false;
prop.value = _marko_compiler.types.identifier(sourceName);
(insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
getAssignmentInsertions(left, insertions);
} else insertions = getAssignmentInsertions(prop.value, insertions);
break;
case "ArrayPattern":
for (let i = 0, len = node.elements.length; i < len; i++) {
const el = node.elements[i];
if (el != null) if (el.type === "AssignmentPattern") {
const { left, right } = el;
const sourceName = generateUid(getLiteralName(left) || "pattern");
node.elements[i] = _marko_compiler.types.identifier(sourceName);
(insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
getAssignmentInsertions(left, insertions);
} else insertions = getAssignmentInsertions(el, insertions);
}
break;
}
return insertions;
}
function toFallbackExpr(id, fallback) {
return _marko_compiler.types.conditionalExpression(_marko_compiler.types.binaryExpression("!==", buildUndefined(), _marko_compiler.types.identifier(id)), _marko_compiler.types.identifier(id), fallback);
}
function toConstTag(id, expr) {
return _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", expr, null, null, true)], _marko_compiler.types.markoTagBody(), null, id);
}
function buildUndefined() {
return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
}
//#endregion
//#region src/translator/visitors/program/index.ts
let scopeIdentifier;
let localsIdentifier;
var program_default = {
migrate: {
enter(program) {
program.node.params = [_marko_compiler.types.identifier("input")];
},
exit(program) {
program.scope.crawl();
}
},
transform: { exit: preAnalyze },
analyze: {
enter(program) {
startSection(program);
trackParamsReferences(program, 2);
const programExtra = program.node.extra ??= {};
const inputBinding = program.node.params[0].extra?.binding;
if (inputBinding) inputBinding.nullable = false;
programExtra.domExports = {
template: generateUid("template"),
walks: generateUid("walks"),
setup: generateUid("setup"),
params: void 0
};
const styleFile = getStyleFile((0, _marko_compiler_babel_utils.getFile)());
if (styleFile) {
programExtra.styleFile = styleFile;
addAssetImport(styleFile);
}
},
exit(program) {
if (hasAnalyzeErrors()) return;
finalizeReferences();
const programExtra = program.node.extra;
const paramsBinding = programExtra.binding;
if (paramsBinding && !paramsBinding.pruned) programExtra.domExports.params = getBindingPropTree(paramsBinding);
const section = programExtra.section;
forEachSection((childSection) => {
programExtra.hasResumes ||= !!(childSection.serializeReason || childSection.serializeReasons.size || childSection !== section && !isSectionRendererElided(childSection) && getSectionRegisterReasons(childSection));
});
if (!section.hoistedTo && !sectionHasSetupStatements(section)) programExtra.domExports.setupEmpty = true;
}
},
translate: {
enter(program) {
scopeIdentifier = isOutputDOM() ? generateUidIdentifier("scope") : null;
localsIdentifier = isOutputDOM() ? generateUidIdentifier("locals") : null;
{
const markoOpts = getMarkoOpts();
const { output, entry, runtimeId } = markoOpts;
const isLoadEntry = entry === "load";
const isDOMPageEntry = output === "dom" && entry === "page" || output === "hydrate";
const isServerEntry = output === "html" && entry === "page";
if (entry && !markoOpts.linkAssets) throw program.buildCodeFrameError("The \"entry\" option requires the `linkAssets` compiler option to be configured.");
if (runtimeId && !/^[_a-z][_a-z0-9]*$/i.test(runtimeId)) throw program.buildCodeFrameError(`Invalid runtimeId: "${runtimeId}". The runtimeId must start with a letter or underscore and only contain letters, numbers, and underscores.`);
if (isLoadEntry) {
const entryFile = (0, _marko_compiler_babel_utils.getFile)();
const { filename } = entryFile.opts;
const readyId = getReadyId(entryFile);
const report = !markoOpts.optimize;
program.node.body = [_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("ready"), _marko_compiler.types.identifier("ready")), ...report ? [_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("readyFailed"), _marko_compiler.types.identifier("readyFailed"))] : []], _marko_compiler.types.stringLiteral(getRuntimePath("dom"))), _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(_marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename))]), _marko_compiler.types.identifier("then")), [_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.identifier("ready"), [_marko_compiler.types.stringLiteral(readyId)])), ...report ? [_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.identifier("readyFailed"), [_marko_compiler.types.stringLiteral(readyId)]))] : []]))];
program.skip();
return;
}
if (isDOMPageEntry) {
const entryFile = (0, _marko_compiler_babel_utils.getFile)();
builder.visit(entryFile, entryFile);
program.node.body = builder.build(entryFile);
program.skip();
return;
}
if (isServerEntry) {
const entryFile = (0, _marko_compiler_babel_utils.getFile)();
const { filename } = entryFile.opts;
const relativeImport = (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename);
const templateId = (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename);
const pageAssetArgs = [
_marko_compiler.types.identifier("template"),
_marko_compiler.types.identifier("flush"),
_marko_compiler.types.stringLiteral(templateId)
];
if (runtimeId) pageAssetArgs.push(_marko_compiler.types.stringLiteral(runtimeId));
markoOpts.linkAssets.onAsset("page", filename, templateId);
program.node.body = [
_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("flush"), _marko_compiler.types.identifier("flush"))], _marko_compiler.types.stringLiteral(markoOpts.linkAssets.runtime)),
_marko_compiler.types.importDeclaration([_marko_compiler.types.importDefaultSpecifier(_marko_compiler.types.identifier("template"))], _marko_compiler.types.stringLiteral(relativeImport)),
_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("withPageAssets"), _marko_compiler.types.identifier("withPageAssets"))], _marko_compiler.types.stringLiteral(getRuntimePath("html"))),
_marko_compiler.types.exportAllDeclaration(_marko_compiler.types.stringLiteral(relativeImport)),
_marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.callExpression(_marko_compiler.types.identifier("withPageAssets"), pageAssetArgs))
];
program.skip();
return;
}
}
if (isOutputHTML()) html_default.translate.enter();
else dom_default.translate.enter(program);
},
exit(program) {
if (isOutputHTML()) html_default.translate.exit(program);
else dom_default.translate.exit(program);
if (program.node.extra?.needsCompat) {
const compatFile = getCompatRuntimeFile();
const body = [void 0];
for (const child of program.node.body) if (child.type === "ImportDeclaration" && child.source.value === compatFile) body[0] = child;
else body.push(child);
body[0] ??= _marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(compatFile));
program.node.body = body;
}
}
}
};
//#endregion
//#region src/translator/util/set-tag-sections-downstream.ts
const [getTagDownstreams] = createSectionState("tag-downstreams", () => /* @__PURE__ */ new Map());
function setTagDownstream(tag, binding, exprs) {
if (binding) getTagDownstreams(getSection(tag)).set(tag, {
binding,
exprs
});
}
function finalizeTagDownstreams(section) {
for (const [tag, { binding, exprs }] of getTagDownstreams(section)) crawlSectionsAndSetBinding(tag, tag.node.extra, binding, exprs);
}
function crawlSectionsAndSetBinding(tag, downstreamTag, binding, exprs, properties, skip) {
if (!skip) {
const contentSection = getSectionForBody(tag.get("body"));
if (contentSection) {
let target = binding;
forEach(properties, (property) => {
target = target?.propertyAliases.get(property);
});
const serialized = !(target && (target.noSerialize || includes(target.noSerializeProperties, "content")));
contentSection.downstream = {
tag: downstreamTag,
binding: serialized ? binding : void 0,
properties: serialized ? concat(properties, "content") : void 0,
exprs: serialized ? exprs : void 0
};
}
}
const attrTagLookup = analyzeAttributeTags(tag);
if (!attrTagLookup) return;
const attrTags = getAttrTagPaths(tag);
for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const attrTagMeta = attrTagLookup[getTagName(child)];
crawlSectionsAndSetBinding(child, downstreamTag, binding, exprs, concat(properties, attrTagMeta.name));
} else crawlSectionsAndSetBinding(child, downstreamTag, binding, exprs, properties, true);
}
//#endregion
//#region src/translator/util/translate-var.ts
function translateVar(tag, initialValue, kind = "const", statements) {
const { node: { var: tagVar } } = tag;
if (!tagVar) return;
const tagSection = getOrCreateSection(tag);
forEachIdentifierPath(tag.get("var"), (id) => {
if (id.node === tagVar) return;
const idExtra = id.node.extra;
if (!idExtra) return;
const binding = idExtra.binding;
if (!binding?.upstreamAlias) return;
if (binding.assignmentSections && binding.property !== void 0) {
const changeName = binding.property + "Change";
const changeBinding = binding.upstreamAlias.propertyAliases.get(changeName);
if (changeBinding && changeName !== changeBinding.name) {
const pattern = getDestructurePattern(id);
if (pattern) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.identifier(changeName), _marko_compiler.types.identifier(changeBinding.name)));
}
}
if (binding.section !== tagSection && binding.excludeProperties !== void 0 && getSerializeReason(binding.section, binding)) {
const restPath = id.parentPath;
if (restPath.type !== "RestElement") throw restPath.buildCodeFrameError("Invalid compiler state, found a rest binding outside of a rest element.");
let curPath = tag.parentPath;
while (curPath) {
if (curPath.node.extra?.section === binding.section) {
const canonicalUpstreamAlias = getCanonicalBinding(binding.upstreamAlias);
const props = toArray(binding.excludeProperties, (name) => _marko_compiler.types.objectProperty(toPropertyName(name), generateUidIdentifier(name)));
props.push(restPath.node);
curPath.insertBefore(_marko_compiler.types.variableDeclaration(kind, [_marko_compiler.types.variableDeclarator(_marko_compiler.types.objectPattern(props), canonicalUpstreamAlias.nullable ? _marko_compiler.types.logicalExpression("||", getDeclaredBindingExpression(canonicalUpstreamAlias), _marko_compiler.types.objectExpression([])) : getDeclaredBindingExpression(canonicalUpstreamAlias))]));
break;
}
curPath = curPath.parentPath;
}
restPath.remove();
}
});
const declaration = _marko_compiler.types.variableDeclaration(kind, [_marko_compiler.types.variableDeclarator(tagVar, initialValue)]);
if (statements) statements.push(declaration);
else tag.insertBefore(declaration);
}
function getDestructurePattern(id) {
let cur = id;
while (cur) {
if (cur.node.type === "ObjectPattern") return cur;
cur = cur.parentPath;
}
}
//#endregion
//#region src/translator/util/known-tag.ts
const [getKnownTags] = createSectionState("known tags", () => []);
const kContentSection = Symbol("known tag content section");
const kChildScopeBinding = Symbol("known tag scope binding");
const kChildOffsetScopeBinding$1 = Symbol("known tag scope offset binding");
const kKnownExprs = Symbol("known tag exprs");
function knownTagAnalyze(tag, contentSection, propTree) {
analyzeAttributeTags(tag);
const section = getOrCreateSection(tag);
const tagBody = tag.get("body");
const tagExtra = tag.node.extra ??= {};
const childScopeBinding = tagExtra[kChildScopeBinding] = createBinding("#childScope", 0, section);
const attrExprs = /* @__PURE__ */ new Set([tagExtra]);
startSection(tagBody);
trackParamsReferences(tagBody, 3);
getKnownTags(section).push(tagExtra);
tagExtra[kContentSection] = contentSection;
const varBinding = trackVarReferences(tag, 5);
const exprs = tagExtra[kKnownExprs] = analyzeParams(tagExtra, section, tag, propTree, attrExprs);
setTagDownstream(tag, propTree?.props?.[0]?.binding, exprs);
if (varBinding) {
addSetupStatement(section);
const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
const varExpr = tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, contentSection.returnSerializeReason && (contentSection.returnSerializeReason === true || !!contentSection.returnSerializeReason.state || contentSection.returnSerializeReason.param));
varBinding.scopeOffset = tagExtra[kChildOffsetScopeBinding$1] = createBinding("#scopeOffset", 0, section);
setBindingDownstream(varBinding, varExpr);
if (mutatesTagVar) addSerializeExpr(section, true, childScopeBinding);
addSerializeExpr(section, varExpr, childScopeBinding);
}
addSerializeExpr(section, fromIter(attrExprs), childScopeBinding);
}
function knownTagTranslateHTML(tag, tagIdentifier, contentSection, propTree) {
const tagBody = tag.get("body");
const { node } = tag;
const tagExtra = node.extra;
flushInto(tag);
writeHTMLResumeStatements(tagBody);
const tagVar = node.var;
const section = getSection(tag);
const attrsPropTree = propTree?.props?.[tag.node.arguments?.length || 0];
const { properties, statements } = propTree && !propTree.props || attrsPropTree ? translateAttrs(tag, attrsPropTree) : {
properties: [],
statements: []
};
const childScopeBinding = tagExtra[kChildScopeBinding];
const childScopeSerializeReason = getSerializeReason(section, childScopeBinding);
let varStatement;
if (childScopeSerializeReason) {
const peekScopeId = generateUidIdentifier(childScopeBinding?.name);
statements.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(peekScopeId, callRuntime("_peek_scope_id"))]));
setBindingSerializedValue(section, childScopeBinding, callRuntime("_existing_scope", peekScopeId));
if (tagVar) varStatement = _marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(section), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding$1]), peekScopeId, _marko_compiler.types.stringLiteral(getResumeRegisterId(section, tagVar.extra?.binding, "var"))));
}
if (contentSection.paramReasonGroups) {
let childSerializeReasonExpr;
if (contentSection.paramReasonGroups.length === 1) {
const [group] = contentSection.paramReasonGroups;
const reason = getSerializeReason(section, childScopeBinding, group.id);
childSerializeReasonExpr = reason && getSerializeGuard(section, reason, false);
} else {
const props = [];
let bitmask = 0;
let bitmaskNames = "";
let hasDynamicReasons = false;
let hasSkippedReasons = false;
for (let i = 0; i < contentSection.paramReasonGroups.length; i++) {
const group = contentSection.paramReasonGroups[i];
const reason = getSerializeReason(section, childScopeBinding, group.id);
if (reason) {
hasDynamicReasons ||= reason !== true && !reason.state;
const guard = getSerializeGuard(section, reason, false);
if (bitmask >= 0) if (guard.type === "NumericLiteral" && guard.value === 1 && i < 30) {
bitmask |= 1 << i + 1;
const names = getDebugNames(group.reason);
if (names) bitmaskNames += bitmaskNames ? ` | ${names}` : names;
} else bitmask = -1;
props.push(_marko_compiler.types.objectProperty(withLeadingComment(_marko_compiler.types.numericLiteral(i), getDebugNames(group.reason)), guard));
} else hasSkippedReasons = true;
}
if (props.length) childSerializeReasonExpr = !(hasDynamicReasons || hasSkippedReasons) ? _marko_compiler.types.numericLiteral(1) : bitmask > 0 ? withLeadingComment(_marko_compiler.types.numericLiteral(bitmask), bitmaskNames) : _marko_compiler.types.objectExpression(props);
}
if (childSerializeReasonExpr) tag.insertBefore(_marko_compiler.types.expressionStatement(callRuntime("_set_serialize_reason", childSerializeReasonExpr)));
}
const getArgs = () => {
let renderArgs = [];
if (tag.node.arguments) renderArgs = [...renderArgs, ...tag.node.arguments];
if (!tag.node.arguments?.length || properties.length) renderArgs.push(propsToExpression(properties));
return renderArgs;
};
if (tagVar) {
translateVar(tag, callExpression(tagIdentifier, ...getArgs()), "let", statements);
if (varStatement) statements.push(varStatement);
} else statements.push(callStatement(tagIdentifier, ...getArgs()));
for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
}
function knownTagTranslateDOM(tag, propTree, getBindingIdentifier, callSetup) {
const tagSection = getSection(tag);
const { node } = tag;
const childScopeBinding = node.extra[kChildScopeBinding];
if (node.var) {
const varBinding = node.var.extra.binding;
const source = initValue(varBinding);
source.register = !!getSerializeReason(tagSection, childScopeBinding);
source.referenced = true;
source.buildAssignment = (valueSection, value) => {
const changeArgs = [createScopeReadExpression(childScopeBinding, valueSection), value];
if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
return _marko_compiler.types.callExpression(importRuntime("_var_change"), changeArgs);
};
addStatement("prepare", tagSection, void 0, _marko_compiler.types.expressionStatement(callRuntime("_var", scopeIdentifier, getScopeAccessorLiteral(childScopeBinding, true), source.identifier)));
}
callSetup?.(tagSection, childScopeBinding);
if (propTree) writeParamsToSignals(tag, propTree, getTagName(tag) || "tag", {
tagSection,
getBindingIdentifier,
childScopeBinding,
attrTagCallsByTag: void 0
});
}
function finalizeKnownTags(section) {
for (const tagExtra of getKnownTags(section)) {
const scopeBinding = tagExtra[kChildScopeBinding];
const knownExprs = tagExtra[kKnownExprs];
const contentSection = tagExtra[kContentSection];
if (knownExprs && scopeBinding && contentSection.paramReasonGroups) for (const group of contentSection.paramReasonGroups) addSerializeReason(section, getSerializeSourcesForExprs(mapParamReasonToExpr(knownExprs, group.reason)), scopeBinding, group.id);
}
}
function analyzeParams(rootTagExtra, section, tag, propTree, rootAttrExprs) {
const inputExpr = {};
if (!propTree) {
dropNodes(getAllTagReferenceNodes(tag.node));
return inputExpr;
}
if (!propTree.props || propTree.rest || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
const extra = inputExpr.value = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
setBindingDownstream(propTree.binding, extra, inputExpr);
return inputExpr;
}
const known = inputExpr.known = {};
let i = 0;
if (tag.node.arguments) for (const arg of tag.node.arguments) {
if (propTree.props[i]) {
const argValueExtra = arg.extra ??= {};
known[i] = { value: argValueExtra };
rootAttrExprs.add(argValueExtra);
addSetupExpr(section, arg);
} else dropNodes(arg);
i++;
}
const attrPropsTree = propTree.props[i];
if (attrPropsTree) known[i] = analyzeAttrs(rootTagExtra, section, tag, attrPropsTree, rootAttrExprs, inputExpr);
else {
const args = tag.node.arguments;
tag.node.arguments = null;
dropNodes(getAllTagReferenceNodes(tag.node));
tag.node.arguments = args;
}
return inputExpr;
}
function analyzeAttrs(rootTagExtra, section, tag, propTree, rootAttrExprs, rootExprs) {
const inputExpr = {};
if (!propTree.props) {
const extra = inputExpr.value = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
setBindingDownstream(propTree.binding, extra, rootExprs);
return inputExpr;
}
const known = inputExpr.known = {};
const attrTagLookup = analyzeAttributeTags(tag);
const seen = /* @__PURE__ */ new Set();
const remaining = new Set(getAllKnownPropNames(propTree));
const dropReferenceNodes = [];
let restReferenceNodes;
if (attrTagLookup) {
const nodeReferencesByGroup = /* @__PURE__ */ new Map();
const analyzeDynamicAttrTagChildGroup = (group, child) => {
const referenceNodes = getAllTagReferenceNodes(child.node);
const groupReferences = nodeReferencesByGroup.get(group);
if (groupReferences) groupReferences.referenceNodes = groupReferences.referenceNodes.concat(referenceNodes);
else nodeReferencesByGroup.set(group, {
firstTag: child,
referenceNodes
});
};
for (const attrTagName in attrTagLookup) seen.add(attrTagLookup[attrTagName].name);
const attrTags = getAttrTagPaths(tag);
for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const attrTagMeta = attrTagLookup[getTagName(child)];
const childAttrExport = getKnownFromPropTree(propTree, attrTagMeta.name);
if (!childAttrExport) getAllTagReferenceNodes(child.node, dropReferenceNodes);
else if (attrTagMeta.dynamic) analyzeDynamicAttrTagChildGroup(attrTagMeta.group, child);
else if (childAttrExport === true) {
getAllTagReferenceNodes(child.node, restReferenceNodes ||= []);
known[attrTagMeta.name] = { value: rootTagExtra };
} else if (childAttrExport.props) {
remaining.delete(attrTagMeta.name);
known[attrTagMeta.name] = analyzeAttrs(rootTagExtra, section, child, childAttrExport, rootAttrExprs, rootExprs);
} else analyzeDynamicAttrTagChildGroup(attrTagMeta.group, child);
} else {
const group = child.node.extra.attributeTagGroup;
let childUsesGroupProp = false;
for (const name of group) if (getKnownFromPropTree(propTree, attrTagLookup[name].name)) {
childUsesGroupProp = true;
break;
}
if (childUsesGroupProp) analyzeDynamicAttrTagChildGroup(group, child);
else getAllTagReferenceNodes(child.node, dropReferenceNodes);
}
for (const [group, { firstTag: { node }, referenceNodes }] of nodeReferencesByGroup) {
let bindings;
let hasRest = false;
for (const tagName of group) {
const templateExportAttr = getKnownFromPropTree(propTree, tagName.slice(1));
if (templateExportAttr === true) {
hasRest = true;
break;
} else bindings = bindingUtil.add(bindings, templateExportAttr.binding);
}
if (hasRest) {
const groupKnownValue = { value: rootTagExtra };
restReferenceNodes ||= [];
for (const node of referenceNodes) restReferenceNodes.push(node);
for (const name of group) {
const attrTagMeta = attrTagLookup[name];
known[attrTagMeta.name] = groupKnownValue;
}
continue;
}
const groupExtra = mergeReferences(section, node, referenceNodes);
const groupKnownValue = { value: groupExtra };
rootAttrExprs.add(groupExtra);
forEach(bindings, (binding) => {
setBindingDownstream(binding, groupExtra, rootExprs);
});
for (const name of group) {
const attrTagMeta = attrTagLookup[name];
remaining.delete(attrTagMeta.name);
known[attrTagMeta.name] = groupKnownValue;
}
}
}
const contentExport = getKnownFromPropTree(propTree, "content");
if (contentExport && !seen.has("content")) {
if (getSectionForBody(tag.get("body"))) {
seen.add("content");
if (contentExport === true) known.content = { value: rootTagExtra };
else {
remaining.delete("content");
known.content = { value: void 0 };
addSetupStatement(section);
}
}
}
let knownSpread;
let spreadReferenceNodes;
const { attributes } = tag.node;
for (let i = attributes.length; i--;) {
const attr = attributes[i];
if (_marko_compiler.types.isMarkoAttribute(attr)) {
const templateExportAttr = getKnownFromPropTree(propTree, attr.name);
if (!templateExportAttr || seen.has(attr.name)) {
dropReferenceNodes.push(attr.value);
continue;
}
seen.add(attr.name);
if (spreadReferenceNodes) spreadReferenceNodes.push(attr.value);
else if (templateExportAttr === true) {
(restReferenceNodes ||= []).push(attr.value);
known[attr.name] = { value: rootTagExtra };
} else {
const attrExtra = attr.value.extra ??= {};
remaining.delete(attr.name);
known[attr.name] = { value: attrExtra };
rootAttrExprs.add(attrExtra);
addSetupExpr(section, attr.value);
setBindingDownstream(templateExportAttr.binding, attrExtra, rootExprs);
if (getRootSection(templateExportAttr.binding.section) !== (0, _marko_compiler_babel_utils.getProgram)().node.extra.section && isInvokeOnlyBinding(templateExportAttr.binding)) attrExtra.invokeOnly = true;
if (knownSpread && !includes(knownSpread.binding.excludeProperties, attr.name)) addRead(attrExtra, {}, getOrCreatePropertyAlias(knownSpread.binding, attr.name), section, void 0);
}
} else if (spreadReferenceNodes) spreadReferenceNodes.push(attr.value);
else {
knownSpread = hasAllKnownProps(propTree) ? getSingleKnownSpread(attributes) : void 0;
if (knownSpread) dropNodes(attr.value);
else (spreadReferenceNodes = restReferenceNodes || []).push(attr.value);
}
}
if (knownSpread) for (const prop of remaining) {
const propBinding = getOrCreatePropertyAlias(knownSpread.binding, prop);
const propExtra = { section };
const templateExportAttr = getKnownFromPropTree(propTree, prop);
known[prop] = { value: propExtra };
rootAttrExprs.add(propExtra);
addRead(propExtra, propExtra, propBinding, section, void 0);
setBindingDownstream(templateExportAttr === true ? propTree.rest.binding : templateExportAttr.binding, propExtra, rootExprs);
}
else if (spreadReferenceNodes) if (remaining.size || propTree.rest && !propTree.rest.props) {
inputExpr.value = mergeReferences(section, tag.node, spreadReferenceNodes);
setBindingDownstream(propTree.rest?.binding || propTree.binding, inputExpr.value, rootExprs);
} else dropNodes(spreadReferenceNodes);
else {
if (restReferenceNodes) {
inputExpr.value = mergeReferences(section, tag.node, restReferenceNodes);
setBindingDownstream(propTree.rest.binding, inputExpr.value, rootExprs);
}
if (remaining.size) addSetupStatement(section);
if (propTree.rest && !propTree.rest.props) addSetupExpr(section, tag.node);
}
dropNodes(dropReferenceNodes);
return inputExpr;
}
function getSingleKnownSpread(attributes) {
let binding;
let extra;
for (let i = attributes.length; i--;) {
const attr = attributes[i];
if (attr.type === "MarkoSpreadAttribute" ? binding || !(binding = (extra = attr.value.extra)?.spreadFrom) : binding && !includes(binding.excludeProperties, attr.name)) return;
}
if (binding) return {
extra,
binding
};
}
function writeParamsToSignals(tag, propTree, importAlias, info) {
if (!propTree.props || propTree.rest || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
const referencedBindings = tag.node.extra?.referencedBindings;
const tagInputIdentifier = info.getBindingIdentifier(propTree.binding, `${importAlias}_params`);
const translatedAttrs = translateAttrs(tag);
if (translatedAttrs.statements.length) addStatement("render", info.tagSection, referencedBindings, translatedAttrs.statements);
const renderParams = tag.node.arguments ? [...tag.node.arguments] : [];
if (!tag.node.arguments?.length || translatedAttrs.properties.length) renderParams.push(propsToExpression(translatedAttrs.properties));
addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.arrayExpression(renderParams)])));
return;
}
let i = 0;
if (tag.node.arguments) for (const arg of tag.node.arguments) {
const argExport = propTree.props[i];
if (argExport) {
const argExportIdentifier = info.getBindingIdentifier(argExport.binding, `${importAlias}_param_${i}`);
addStatement("render", info.tagSection, arg.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(argExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), arg])), true);
}
i++;
}
const attrPropsTree = propTree.props[i];
if (attrPropsTree) writeAttrsToSignals(tag, attrPropsTree, `${importAlias}_input`, info);
}
function applyAttrObject(tag, propTree, tagInputIdentifier, info) {
const referencedBindings = tag.node.extra?.referencedBindings;
const translatedAttrs = translateAttrs(tag, true, propTree.rest && new Set(toIter(propTree.rest.binding.excludeProperties)));
let translatedProps = propsToExpression(translatedAttrs.properties);
if (translatedAttrs.statements.length) addStatement("render", info.tagSection, referencedBindings, translatedAttrs.statements);
if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
const repeated = analyzeAttributeTags(tag.parentPath)?.[getTagName(tag)]?.repeated;
const mergedProps = getAttrTagProps(tag, repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
if (!mergedProps) return;
translatedProps = mergedProps;
}
addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), translatedProps])), true);
}
function translateAttrTag(tag, attrTagMeta, info, statements) {
const translatedAttrs = translateAttrs(tag, true, void 0, statements);
return getAttrTagProps(tag, attrTagMeta.repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
}
function getAttrTagProps(tag, repeated, translatedProps, info) {
if (!repeated) return callRuntime("attrTag", translatedProps);
const attrTagName = getTagName(tag);
const parentTag = tag.parentPath;
let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
const attrTagCall = attrTagCallsForTag.get(attrTagName);
if (attrTagCall) {
attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
return;
}
const wrappedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps));
attrTagCallsForTag.set(attrTagName, wrappedProps);
return wrappedProps;
}
function writeAttrsToSignals(tag, propTree, importAlias, info) {
if (!propTree.props) {
applyAttrObject(tag, propTree, info.getBindingIdentifier(propTree.binding, importAlias), info);
return;
}
const attrTagLookup = analyzeAttributeTags(tag);
const seen = /* @__PURE__ */ new Set();
const tagReferencedBindings = tag.node.extra?.referencedBindings;
const remaining = new Set(getAllKnownPropNames(propTree));
let restProps;
if (attrTagLookup) {
const attrTags = tag.get("attributeTags");
const statementsByGroup = /* @__PURE__ */ new Map();
const translateDynamicAttrTagChildInGroup = (group, index) => {
const child = attrTags[index];
let statements = statementsByGroup.get(group)?.statements;
if (!statements) {
statements = [];
statementsByGroup.set(group, {
referencedBindings: child.node.extra?.referencedBindings,
statements
});
}
return addDynamicAttrTagStatements(attrTags, index, attrTagLookup, statements, propTree);
};
for (const attrTagName in attrTagLookup) seen.add(attrTagLookup[attrTagName].name);
for (let i = 0; i < attrTags.length; i++) {
const child = attrTags[i];
if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
const attrTagMeta = attrTagLookup[getTagName(child)];
const childAttrExport = getKnownFromPropTree(propTree, attrTagMeta.name);
if (!childAttrExport) {} else if (attrTagMeta.dynamic) i = translateDynamicAttrTagChildInGroup(attrTagMeta.group, i);
else if (childAttrExport === true) {
const statements = [];
const translatedAttrs = translateAttrTag(child, attrTagMeta, info, statements);
addStatement("render", info.tagSection, tagReferencedBindings, statements);
if (translatedAttrs) (restProps ||= []).push(toObjectProperty(attrTagMeta.name, translatedAttrs));
} else {
remaining.delete(attrTagMeta.name);
writeAttrsToSignals(child, childAttrExport, `${importAlias}_${attrTagMeta.name}`, info);
}
} else {
const group = child.node.extra.attributeTagGroup;
let childUsesGroupProp = false;
for (const name of group) if (getKnownFromPropTree(propTree, attrTagLookup[name].name)) {
childUsesGroupProp = true;
break;
}
if (childUsesGroupProp) i = translateDynamicAttrTagChildInGroup(group, i);
else if (getTagName(child) === "if") while (++i < attrTags.length) {
const nextTag = attrTags[i];
switch (nextTag.isMarkoTag() && getTagName(nextTag)) {
case "else":
case "else-if": continue;
}
i--;
break;
}
}
}
for (const [group, { referencedBindings, statements }] of statementsByGroup) {
const decls = [];
let hasRest = false;
for (const name of group) {
const attrTagMeta = attrTagLookup[name];
const childAttrExports = getKnownFromPropTree(propTree, attrTagMeta.name);
decls.push(_marko_compiler.types.variableDeclarator(getAttrTagIdentifier(attrTagMeta)));
if (childAttrExports === true) hasRest = true;
}
addStatement("render", info.tagSection, hasRest ? tagReferencedBindings : referencedBindings, [_marko_compiler.types.variableDeclaration("let", decls), ...statements]);
if (hasRest) for (const name of group) {
const attrTagMeta = attrTagLookup[name];
(restProps ||= []).push(toObjectProperty(attrTagMeta.name, getAttrTagIdentifier(attrTagMeta)));
}
else for (const name of group) {
const attrTagMeta = attrTagLookup[name];
const childAttrExports = getKnownFromPropTree(propTree, attrTagMeta.name);
remaining.delete(attrTagMeta.name);
addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${attrTagMeta.name}`), [createScopeReadExpression(info.childScopeBinding, info.tagSection), getAttrTagIdentifier(attrTagMeta)])));
}
}
}
const contentExport = getKnownFromPropTree(propTree, "content");
if (!seen.has("content") && contentExport) {
const bodySection = getSectionForBody(tag.get("body"));
if (bodySection) {
seen.add("content");
const bodyValue = _marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), [scopeIdentifier]);
if (contentExport === true) (restProps ||= []).push(toObjectProperty("content", bodyValue));
else {
remaining.delete("content");
const directContent = !bodySection.params;
addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(contentExport.binding, `${importAlias}_content`, directContent), [createScopeReadExpression(info.childScopeBinding, info.tagSection), bodyValue])), true);
}
}
}
let knownSpread;
let spreadProps;
const staticAttrs = [];
const { attributes } = tag.node;
for (let i = attributes.length; i--;) {
const attr = attributes[i];
if (_marko_compiler.types.isMarkoAttribute(attr)) {
const templateExportAttr = getKnownFromPropTree(propTree, attr.name);
if (!templateExportAttr || seen.has(attr.name)) continue;
seen.add(attr.name);
if (spreadProps) spreadProps.push(toObjectProperty(attr.name, attr.value));
else if (templateExportAttr === true) (restProps ||= []).push(toObjectProperty(attr.name, attr.value));
else staticAttrs.push(attr);
} else if (spreadProps) spreadProps.push(_marko_compiler.types.spreadElement(attr.value));
else {
knownSpread = hasAllKnownProps(propTree) ? getSingleKnownSpread(attributes) : void 0;
if (!knownSpread) (spreadProps = restProps || []).push(_marko_compiler.types.spreadElement(attr.value));
}
}
for (let i = staticAttrs.length; i--;) {
const attr = staticAttrs[i];
const childAttrExports = getKnownFromPropTree(propTree, attr.name);
const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${attr.name}`);
remaining.delete(attr.name);
addStatement("render", info.tagSection, attr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), attr.value])), true);
}
if (knownSpread) for (const prop of remaining) {
const childAttrExports = getKnownFromPropTree(propTree, prop);
const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${prop}`);
const propBinding = knownSpread.binding.propertyAliases.get(prop);
addStatement("render", info.tagSection, propBinding, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), createScopeReadExpression(propBinding, info.tagSection)])), true);
}
else if (spreadProps && (remaining.size || propTree.rest && !propTree.rest.props)) {
const spreadExpr = propsToExpression(spreadProps.reverse());
let spreadId = spreadExpr;
if (!isSimpleReference(spreadExpr)) {
spreadId = generateUidIdentifier(`${importAlias}_spread`);
addStatement("render", info.tagSection, tagReferencedBindings, [_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(spreadId, spreadExpr)])]);
}
for (const name of remaining) {
const childAttrExports = getKnownFromPropTree(propTree, name);
const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${name}`);
addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), toMemberExpression(_marko_compiler.types.cloneNode(spreadId, true), name)])));
}
if (propTree.rest && !propTree.rest.props) {
const props = [];
const restId = _marko_compiler.types.identifier(propTree.rest.binding.name);
forEach(propTree.rest.binding.excludeProperties, (name) => {
const propId = toPropertyName(name);
const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
});
props.push(_marko_compiler.types.restElement(restId));
addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.objectPattern(props)], restId), [spreadId])])), true);
}
} else {
for (const name of remaining) {
const childAttrExports = getKnownFromPropTree(propTree, name);
const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${name}`);
addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection)])));
}
if (propTree.rest && !propTree.rest.props) addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.objectExpression(restProps || [])])), true);
}
}
function callStatement(id, ...args) {
return _marko_compiler.types.expressionStatement(callExpression(id, ...args));
}
function callExpression(id, ...args) {
return _marko_compiler.types.callExpression(id, args.filter(Boolean));
}
function isSimpleReference(expr) {
switch (expr.type) {
case "Identifier": return true;
case "MemberExpression": return !expr.computed && isSimpleReference(expr.object);
default: return false;
}
}
function getRootSection(section) {
while (section.parent) section = section.parent;
return section;
}
//#endregion
//#region src/translator/util/references.ts
const kBranchSerializeReason = Symbol("branch serialize reason");
const globalSources = {
state: void 0,
param: void 0,
global: true
};
const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
function createBinding(name, type, refSection, upstreamAlias, property, excludeProperties, loc = null, refDeclared = false) {
const id = getNextBindingId();
const section = upstreamAlias ? upstreamAlias.section : refSection;
const sameSection = refSection === section;
const declared = sameSection && refDeclared;
const binding = {
id,
uid: id,
name,
originalName: void 0,
type,
loc,
section,
property,
declared,
closureSections: void 0,
assignmentSections: void 0,
excludeProperties,
noSerialize: false,
noSerializeProperties: void 0,
sources: void 0,
reads: /* @__PURE__ */ new Set(),
aliases: /* @__PURE__ */ new Set(),
hoists: void 0,
getters: /* @__PURE__ */ new Map(),
propertyAliases: /* @__PURE__ */ new Map(),
upstreamAlias,
restOffset: void 0,
scopeOffset: void 0,
scopeAccessor: void 0,
export: void 0,
directContentExport: void 0,
nullable: !sameSection || excludeProperties === void 0,
pruned: void 0,
exposed: false,
forcePersist: false,
serializePropKeys: void 0,
reserveSize: 0
};
if (property) {
if (declared) upstreamAlias.nullable = false;
const propBinding = upstreamAlias.propertyAliases.get(property);
if (propBinding) {
binding.property = void 0;
binding.upstreamAlias = propBinding;
propBinding.aliases.add(binding);
} else upstreamAlias.propertyAliases.set(property, binding);
} else if (upstreamAlias) upstreamAlias.aliases.add(binding);
setNextBindingId(id + 1);
getBindings().add(binding);
return binding;
}
function getOrCreatePropertyAlias(binding, property) {
return binding.propertyAliases.get(property) || createBinding(`${binding.name}_${property.replace(/[^a-zA-Z0-9_$]/g, "_")}`, binding.type, binding.section, binding, property);
}
function trackDomVarReferences(tag, binding) {
const tagVar = tag.node.var;
if (!tagVar) return;
const babelBinding = tag.scope.getBinding(tagVar.name);
const section = getOrCreateSection(tag);
binding.originalName = tagVar.name;
if (babelBinding.constantViolations.length) for (const ref of babelBinding.constantViolations) throw ref.type === "MarkoTag" ? ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.originalName}\`.`) : ref.buildCodeFrameError(`\`${binding.originalName}\` is a [tag variable](https://markojs.com/docs/reference/language#tag-variables) on a native element (an element reference) and cannot be assigned to.`);
for (const ref of babelBinding.referencePaths) {
const refSection = getOrCreateSection(ref);
const invoked = isInvokedFunction(ref);
const hoisted = isReferenceHoisted(babelBinding.path, ref) ? getCommonSection(refSection, binding.section) : false;
setReferencesScope(ref);
addReadToExpression(ref, binding, !invoked || hoisted && hoisted !== binding.section ? {
hoisted,
invoked
} : void 0);
if (refSection !== binding.section) {
setReadsOwner(refSection, section);
addOwnerSerializeReason(refSection, section, true);
}
}
return binding;
}
function trackVarReferences(tag, type, upstreamAlias) {
const tagVar = tag.node.var;
if (tagVar) {
const section = getOrCreateSection(tag);
let canonicalUpstreamAlias = upstreamAlias && getCanonicalBinding(upstreamAlias);
if (canonicalUpstreamAlias) {
const { excludeProperties, restOffset } = canonicalUpstreamAlias;
if (excludeProperties !== void 0) canonicalUpstreamAlias = canonicalUpstreamAlias.upstreamAlias;
createBindingsAndTrackReferences(tagVar, canonicalUpstreamAlias.type, tag.scope, section, canonicalUpstreamAlias, void 0, excludeProperties, restOffset);
return canonicalUpstreamAlias;
}
createBindingsAndTrackReferences(tagVar, type, tag.scope, section, void 0, void 0, void 0);
return tagVar.extra?.binding;
}
}
function trackParamsReferences(body, type) {
const params = body.node.params;
if (body.node.body.length && params.length) {
const section = getOrCreateSection(body);
const paramsBinding = (body.node.extra ??= {}).binding = createBinding(generateUid("params"), type, section, void 0, void 0, void 0, params[0].loc);
const bodySection = getSectionForBody(body);
if (bodySection) bodySection.params = paramsBinding;
for (let i = 0; i < params.length; i++) {
const param = params[i];
if (i === 0 && param.type === "RestElement" && param.argument.type === "Identifier") {
const { argument } = param;
paramsBinding.name = argument.name;
paramsBinding.declared = true;
(argument.extra ??= {}).binding = paramsBinding;
trackReferencesForBinding(body.scope.getBinding(argument.name), paramsBinding);
} else if (param.type === "RestElement") createBindingsAndTrackReferences(param.argument, type, body.scope, section, paramsBinding, void 0, i > 0 ? addNumericPropertiesUntil(void 0, i) : void 0, i);
else if (_marko_compiler.types.isLVal(param)) createBindingsAndTrackReferences(param, type, body.scope, section, paramsBinding, i + "", void 0);
}
return paramsBinding;
}
}
function getMarkoRootAsTag(path) {
const tag = path.isMarkoTag() ? path : getMarkoRoot(path)?.parentPath;
if (tag?.isMarkoTag()) return tag;
}
function isReferenceInOwnBody(bindingPath, reference) {
const tag = getMarkoRootAsTag(bindingPath);
if (!tag) return false;
const body = tag.get("body");
let cur = reference;
while (cur) {
if (cur === body) return true;
cur = cur.parentPath;
}
return false;
}
function isReferenceHoisted(bindingPath, reference) {
const tag = getMarkoRootAsTag(bindingPath);
if (!tag) return false;
const body = tag.parentPath;
let cur = reference;
while (cur) {
if (cur.parentPath === body) return +tag.key > +cur.key;
cur = cur.parentPath;
}
return true;
}
function trackReferencesForBinding(babelBinding, binding) {
const { referencePaths, constantViolations } = babelBinding;
for (const ref of referencePaths) {
const refSection = getOrCreateSection(ref);
const markoRoot = getMarkoRoot(ref);
if (markoRoot?.type === "MarkoAttribute" && markoRoot.parentPath === babelBinding.path && !getFnRoot(ref)) throw ref.buildCodeFrameError(`\`${ref.node.name}\` is the [tag variable](https://markojs.com/docs/reference/language#tag-variables) this tag declares, so its own attributes cannot read it.`);
else if (isReferenceHoisted(babelBinding.path, ref)) {
const invoked = isInvokedFunction(ref);
if (invoked) setReferencesScope(ref);
addReadToExpression(ref, binding, {
hoisted: getCommonSection(refSection, binding.section),
invoked
});
} else if (binding.type !== 4 || refSection !== binding.section) trackReference(ref, binding);
else {
const fnRoot = getFnRoot(ref);
if (fnRoot) {
const fnExtra = fnRoot.node.extra ??= {};
fnExtra.referencedLocalBindingsInFunction = bindingUtil.add(fnExtra.referencedLocalBindingsInFunction, binding);
const refExtra = ref.node.extra ??= {};
refExtra.section = refSection;
refExtra.read = createRead(binding, void 0);
refExtra.read.localFn = fnExtra;
}
}
}
for (const ref of constantViolations) {
if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.name}\`.`);
if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError(`\`${binding.name}\` is declared by a tag below this assignment; a [tag variable](https://markojs.com/docs/reference/language#tag-variables) can only be assigned below its declaration. Move the declaring tag above this code.`);
if (ref.isUpdateExpression()) trackAssignment(ref.get("argument"), binding);
else if (ref.isAssignmentExpression()) {
trackAssignment(ref.get("left"), binding);
if (ref.node.operator !== "=") {
const left = ref.get("left");
if (left.isIdentifier()) trackReference(left, binding);
}
} else if (ref.isForXStatement()) throw ref.get("left").buildCodeFrameError(`\`${binding.name}\` is a [tag variable](https://markojs.com/docs/reference/language#tag-variables), so a \`for...${ref.isForOfStatement() ? "of" : "in"}\` cannot assign to it. Loop into a local variable and assign \`${binding.name}\` from it instead.`);
}
}
function trackAssignment(assignment, binding) {
const fnParent = getFnParent(assignment);
if (!fnParent) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag ${binding.type === 3 ? "parameter" : "variable"} and can only be assigned within a script or function.`);
if (binding.type === 4) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
const fnRoot = getFnRoot(fnParent);
const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
const section = getOrCreateSection(assignment);
setReferencesScope(assignment);
forEachIdentifierPath(assignment, (id) => {
if (id.node.name === binding.name) {
const idExtra = id.node.extra ??= {};
idExtra.assignment = binding;
idExtra.section = section;
binding.assignmentSections = sectionUtil.add(binding.assignmentSections, section);
if (fnExtra) {
idExtra.assignmentFunction = fnExtra;
fnExtra.section = idExtra.section = section;
}
if (binding.upstreamAlias && binding.property !== void 0) {
if (binding.upstreamAlias === binding.section.params) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
const changePropName = binding.property + "Change";
const changeBinding = binding.upstreamAlias.propertyAliases.get(changePropName) || createBinding(generateUid(changePropName), binding.type, binding.section, binding.upstreamAlias, changePropName, void 0, id.node.loc, true);
idExtra.assignmentTo = changeBinding;
addReadToExpression(id, changeBinding, void 0);
}
}
});
}
function setReferencesScope(path) {
const fnRoot = getFnRoot(path);
if (fnRoot) (fnRoot.node.extra ??= {}).referencesScope = true;
}
const [getGlobalBinding] = createProgramState(() => createBinding("$global", 7, getOrCreateSection((0, _marko_compiler_babel_utils.getProgram)())));
function trackGlobalReference(path) {
(0, _marko_compiler_babel_utils.getProgram)().node.extra.hasGlobalRead = true;
trackReference(path, getGlobalBinding());
}
function createBindingsAndTrackReferences(lVal, type, scope, section, upstreamAlias, property, excludeProperties, restOffset) {
switch (lVal.type) {
case "Identifier": {
const binding = (lVal.extra ??= {}).binding = createBinding(lVal.name, type, section, upstreamAlias, property, excludeProperties, lVal.loc, true);
if (restOffset) binding.restOffset = restOffset;
trackReferencesForBinding(scope.getBinding(lVal.name), binding);
break;
}
case "ObjectPattern": {
const patternBinding = (property ? upstreamAlias.propertyAliases.get(property) : upstreamAlias) || ((lVal.extra ??= {}).binding = createBinding(generateUid(property || "pattern"), type, section, upstreamAlias, property, excludeProperties, lVal.loc));
const hasRest = lVal.properties[lVal.properties.length - 1]?.type === "RestElement";
for (const prop of lVal.properties) if (prop.type === "RestElement") createBindingsAndTrackReferences(prop.argument, type, scope, section, patternBinding, void 0, excludeProperties);
else {
let key;
if (!prop.computed && prop.key.type === "Identifier") key = prop.key.name;
else if (prop.key.type === "StringLiteral") key = prop.key.value;
else throw scope.path.hub.buildError(prop.key, "Only identifier and string literal keys are supported when destructuring.");
if (hasRest) excludeProperties = propsUtil.add(excludeProperties, key);
if (_marko_compiler.types.isLVal(prop.value)) {
createBindingsAndTrackReferences(prop.value, type, scope, section, patternBinding, key, void 0);
if (hasRest && prop.value.extra?.binding?.assignmentSections) excludeProperties = propsUtil.add(excludeProperties, `${key}Change`);
}
}
break;
}
case "ArrayPattern": {
const patternBinding = (property ? upstreamAlias.propertyAliases.get(property) : upstreamAlias) || ((lVal.extra ??= {}).binding = createBinding(generateUid(property || "pattern"), type, section, upstreamAlias, property, excludeProperties, lVal.loc));
let index = (restOffset || 0) - 1;
for (const element of lVal.elements) {
index++;
if (element) {
if (element.type === "RestElement") {
excludeProperties = index > 0 ? addNumericPropertiesUntil(excludeProperties, index) : void 0;
createBindingsAndTrackReferences(element.argument, type, scope, section, patternBinding, void 0, excludeProperties, index);
} else if (_marko_compiler.types.isLVal(element)) createBindingsAndTrackReferences(element, type, scope, section, patternBinding, `${index}`, void 0);
}
}
break;
}
}
}
function trackReference(referencePath, binding) {
let root = referencePath;
let reference = binding;
while (true) {
const { parent } = root;
if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent)) break;
let prop = getMemberExpressionPropString(parent);
if (prop === void 0) break;
if (reference.upstreamAlias && reference.excludeProperties !== void 0) {
if (reference.restOffset) {
if (/^\d+$/.test(prop)) {
prop = `${+prop + reference.restOffset}`;
reference = reference.upstreamAlias;
}
} else if (!propsUtil.has(reference.excludeProperties, prop)) reference = reference.upstreamAlias;
}
if (isInvokedFunction(root.parentPath) && !isEventOrChangeHandler(prop)) break;
root = root.parentPath;
reference = getOrCreatePropertyAlias(reference, prop);
}
addReadToExpression(root, reference, void 0);
}
function mergeReferences(section, target, nodes) {
const targetExtra = target.extra ??= {};
const readsByExpression = getReadsByExpression();
const fnReadsByExpression = getFunctionReadsByExpression();
let reads = readsByExpression.get(targetExtra);
let exprFnReads = fnReadsByExpression.get(targetExtra);
let { isEffect, dynamicTagInput } = targetExtra;
for (const node of nodes) {
if (!node) continue;
const extra = node.extra ??= {};
if (extra === targetExtra) continue;
extra.merged = targetExtra;
if (isReferencedExtra(extra)) {
const additionalReads = readsByExpression.get(extra);
const additionalExprFnReads = fnReadsByExpression.get(extra);
isEffect ||= extra.isEffect;
dynamicTagInput ||= extra.dynamicTagInput;
if (additionalReads) {
forEach(additionalReads, (read) => {
read.binding.reads.delete(extra);
read.binding.reads.add(targetExtra);
});
reads = concat(reads, additionalReads);
readsByExpression.delete(extra);
}
if (additionalExprFnReads) if (exprFnReads) for (const [key, value] of additionalExprFnReads) exprFnReads.set(key, value);
else fnReadsByExpression.set(targetExtra, exprFnReads = new Map(additionalExprFnReads));
} else if (extra?.pruned)
/* v8 ignore next -- a dropped reference is never merged into another */
throw new Error("Cannot merged a dropped reference.");
}
readsByExpression.set(targetExtra, reads);
targetExtra.isEffect = isEffect;
targetExtra.dynamicTagInput = dynamicTagInput;
targetExtra.section = section;
return targetExtra;
}
function compareReferences(a, b) {
return a === b ? 0 : a ? b ? Array.isArray(a) ? Array.isArray(b) ? compareIntersections(a, b) : -1 : Array.isArray(b) ? 1 : bindingUtil.compare(a, b) : 1 : b ? -1 : 0;
}
/**
* reference group priority is sorted by number of references,
* then if needed by reference order.
*/
function compareIntersections(a, b) {
const len = a.length;
const lenDelta = len - b.length;
if (lenDelta !== 0) return lenDelta;
for (let i = 0; i < len; i++) {
const compareResult = bindingUtil.compare(a[i], b[i]);
if (compareResult !== 0) return compareResult;
}
return 0;
}
function finalizeReferences() {
const bindings = getBindings();
const readsByExpression = getReadsByExpression();
const fnReadsByExpression = getFunctionReadsByExpression();
const intersectionsBySection = /* @__PURE__ */ new Map();
for (const [expr, reads] of readsByExpression) if (isReferencedExtra(expr)) {
const exprBindings = resolveReferencedBindings(expr, reads, intersectionsBySection);
expr.referencedBindings = exprBindings.referencedBindings;
expr.lazyBindings = exprBindings.lazyBindings;
expr.globalBindings = exprBindings.globalBindings;
if (!exprBindings.referencedBindings) addSetupStatement(expr.section);
forEach(exprBindings.lazyBindings, (binding) => {
binding.forcePersist = true;
});
if (exprBindings.hoistedBindings) expr.section.referencedHoists = bindingUtil.union(expr.section.referencedHoists, exprBindings.hoistedBindings);
if (expr.isEffect) {
forEach(exprBindings.referencedBindings, (binding) => {
addSerializeReason(binding.section, true, binding);
});
forEach(exprBindings.constantBindings, (binding) => {
addSerializeReason(binding.section, true, binding);
});
forEach(exprBindings.lazyBindings, (binding) => {
addSerializeReason(binding.section, true, binding);
});
} else forEach(reads, (read) => {
if (read.serializedValue) addSerializeExpr(read.binding.section, expr, read.binding);
});
if (exprBindings.allBindings) {
const exprFnReads = fnReadsByExpression.get(expr);
if (exprFnReads) for (const [fn, fnReads] of exprFnReads) {
const fnBindings = fn === expr ? exprBindings : resolveReferencedBindingsInFunction(exprBindings.allBindings, fnReads);
fn.referencedBindingsInFunction = fn === expr ? bindingUtil.union(fnBindings.referencedBindings, exprBindings.lazyBindings) : fnBindings.referencedBindings;
fn.constantBindingsInFunction = fnBindings.constantBindings;
}
}
}
const bindingNamesBySection = /* @__PURE__ */ new Map();
for (const binding of bindings) {
if (binding.type !== 0) {
if (pruneBinding(binding)) bindings.delete(binding);
}
if (binding.noSerialize) if (isPureSpreadResolved(binding)) if (hasAnyMemberAccess(binding)) {
let kept = void 0;
binding.noSerialize = false;
forEach(binding.noSerializeProperties, (property) => {
if (!isPropertyMemberAccessed(binding, property)) kept = push(kept, property);
});
binding.noSerializeProperties = kept;
} else binding.noSerializeProperties = void 0;
else {
binding.noSerialize = false;
binding.noSerializeProperties = void 0;
}
}
forEachSection(finalizeTagDownstreams);
for (const binding of bindings) {
const { name, section } = binding;
if (binding.type === 7) {
resolveBindingSources(binding);
continue;
}
if (binding.type !== 0) {
resolveBindingSources(binding);
forEach(binding.assignmentSections, (assignedSection) => {
setReadsOwner(assignedSection, section);
addOwnerSerializeReason(assignedSection, section, true);
});
let bindingNames = bindingNamesBySection.get(section);
if (!bindingNames) {
bindingNamesBySection.set(section, bindingNames = /* @__PURE__ */ new Set());
forEach(section.bindings, ({ name }) => bindingNames.add(name));
}
if (bindingNames.has(binding.name)) binding.name = generateUid(name);
}
if (binding.hoists) {
let highestHoistSection;
forEach(binding.hoists, (hoistSection) => {
if (!highestHoistSection || hoistSection.depth < highestHoistSection.depth) highestHoistSection = hoistSection;
hoistSection.hoistedTo = bindingUtil.add(hoistSection.hoistedTo, binding);
addSerializeReason(binding.section, true, binding);
});
binding.section.hoisted = bindingUtil.add(binding.section.hoisted, binding);
let currentSection = binding.section.parent;
while (currentSection && currentSection !== highestHoistSection) {
currentSection.isHoistThrough = true;
currentSection = currentSection.parent;
}
}
const canonicalBinding = getCanonicalBinding(binding);
section.bindings = bindingUtil.add(section.bindings, canonicalBinding);
bindingNamesBySection.get(section)?.add(canonicalBinding.name);
for (const exprExtra of binding.reads) {
const { isEffect, section } = exprExtra;
if (section.depth > binding.section.depth) {
if (binding.type === 4) section.referencedLocalClosures = bindingUtil.add(section.referencedLocalClosures, binding);
else if (binding.type !== 0) {
const canonicalUpstreamAlias = getCanonicalBinding(binding);
if (!bindingUtil.has(exprExtra.lazyBindings, binding)) {
canonicalUpstreamAlias.closureSections = sectionUtil.add(canonicalUpstreamAlias.closureSections, section);
section.referencedClosures = bindingUtil.add(section.referencedClosures, canonicalUpstreamAlias);
}
setReadsOwner(section, canonicalUpstreamAlias.section);
if (isEffect) addOwnerSerializeReason(section, canonicalUpstreamAlias.section, true);
addOwnerSerializeReason(section, canonicalUpstreamAlias.section, canonicalUpstreamAlias.sources);
}
}
}
}
forEachSection((section) => {
if (section.isHoistThrough) addSerializeReason(section, true);
forEach(section.referencedHoists, (hoistedBinding) => {
setReadsOwner(section, hoistedBinding.section);
addOwnerSerializeReason(section, hoistedBinding.section, true);
});
if (section.parent && section.isBranch && section.sectionAccessor && section.upstreamExpression) {
if (section.isHoistThrough || section.hoisted) addSerializeReason(section, true, kBranchSerializeReason);
addSerializeReason(section, getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
addSerializeExpr(section, section.upstreamExpression, kBranchSerializeReason);
addSerializeExpr(section.parent, section.upstreamExpression, section.sectionAccessor.binding);
}
});
forEachSection(applySerializeExprs);
forEachSection((section) => {
const intersections = intersectionsBySection.get(section);
if (intersections) for (const intersection of intersections) {
const numReferences = intersection.length;
for (let i = 0; i < numReferences - 1; i++) for (let j = i + 1; j < numReferences; j++) {
const binding1 = intersection[i];
const binding2 = intersection[j];
if (!isForceSerialized(section, binding1) && !isSupersetSources(binding1, binding2)) {
if (!isSameOrChildSection(section, binding1.section)) addOwnerSerializeReason(section, binding1.section, mergeSources(binding1.sources, binding2.sources));
addSerializeReason(binding1.section, binding2.sources, binding1);
}
if (!isForceSerialized(section, binding2) && !isSupersetSources(binding2, binding1)) {
if (!isSameOrChildSection(section, binding2.section)) addOwnerSerializeReason(section, binding2.section, mergeSources(binding1.sources, binding2.sources));
addSerializeReason(binding2.section, binding1.sources, binding2);
}
}
}
});
forEachSection((section) => {
forEach(section.referencedLocalClosures, (closure) => {
addSerializeReason(section, getSerializeReason(closure.section, closure), closure);
});
forEach(section.referencedClosures, (closure) => {
const sourceSection = closure.section;
let currentSection = section;
let branchesForced = false;
let branchesSources;
while (currentSection !== sourceSection) {
const upstreamReason = currentSection.downstream?.binding ? getSectionRegisterReasons(currentSection) || void 0 : !currentSection.upstreamExpression || getSerializeSourcesForExpr(currentSection.upstreamExpression);
if (upstreamReason === true) branchesForced = true;
else if (upstreamReason) branchesSources = mergeSources(branchesSources, upstreamReason);
currentSection = currentSection.parent;
}
const branchesReason = branchesForced || branchesSources;
if (branchesForced) addSerializeReason(sourceSection, branchesSources, closure);
addSerializeReason(sourceSection, branchesReason, closure);
addSerializeReason(sourceSection, getSerializeReason(sourceSection, closure));
if (isDynamicClosure(section, closure)) {
addOwnerSerializeReason(section, sourceSection, branchesReason);
if (closure.sources) {
addSerializeReason(sourceSection, closure.sources, closure, getAccessorPrefix().ClosureScopes);
if (getDynamicClosureIndex(closure, section)) addSerializeReason(section, closure.sources, closure, getAccessorPrefix().ClosureSignalIndex);
}
}
});
});
finalizeFunctionRegistry();
const referencedExprs = /* @__PURE__ */ new Set();
for (const binding of bindings) for (const expr of binding.reads) referencedExprs.add(expr);
for (const expr of referencedExprs) {
const exprFnReads = fnReadsByExpression.get(expr);
if (exprFnReads) {
for (const fn of exprFnReads.keys()) if (fn.registerReason) {
forEach(fn.referencedBindingsInFunction, (binding) => {
addSerializeReason(binding.section, fn.registerReason, binding);
if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
});
forEach(fn.constantBindingsInFunction, (binding) => {
addSerializeReason(binding.section, fn.registerReason, binding);
if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
});
}
}
}
forEachSection(finalizeParamSerializeReasonGroups);
forEachSectionReverse((section) => {
finalizeKnownTags(section);
finalizeSerializeReason(section);
finalizeParamSerializeReasonGroups(section);
});
forEachSection((section) => {
const { id, bindings } = section;
const isOwnedBinding = ({ section }) => section.id === id;
const ownedBindings = filter(bindings, isOwnedBinding);
const intersections = (intersectionsBySection.get(section) || []).filter((intersection) => {
const collapseSource = getCollapsibleIntersectionSource(intersection, section);
if (collapseSource) collapsedIntersectionSource.set(intersection, collapseSource);
return !collapseSource;
});
let anchors;
if (intersections.length) {
const sectionAnchors = anchors = /* @__PURE__ */ new Map();
for (const intersection of intersections) for (let i = intersection.length; i--;) if (isOwnedBinding(intersection[i])) {
sectionAnchors.set(intersection, intersection[i]);
break;
}
intersections.sort((a, b) => {
const aAnchor = sectionAnchors.get(a);
const bAnchor = sectionAnchors.get(b);
return aAnchor ? bAnchor ? bindingUtil.compare(aAnchor, bAnchor) : 1 : bAnchor ? -1 : 0;
});
}
let intersectionIndex = 0;
let nextId = 0;
let intersection;
forEach(ownedBindings, (binding) => {
if (binding.type !== 0) while (intersectionIndex < intersections.length && !anchors.get(intersection = intersections[intersectionIndex])) {
intersectionIndex++;
intersectionMeta.set(intersection, {
id: nextId++,
scopeOffset: getMaxOwnSourceOffset(intersection, section)
});
}
binding.id = nextId++;
nextId += binding.reserveSize;
while (intersectionIndex < intersections.length && anchors.get(intersection = intersections[intersectionIndex]) === binding) {
intersectionIndex++;
intersectionMeta.set(intersection, {
id: nextId++,
scopeOffset: getMaxOwnSourceOffset(intersection, section)
});
}
});
while (intersectionIndex < intersections.length) {
intersection = intersections[intersectionIndex];
intersectionIndex++;
intersectionMeta.set(intersection, {
id: nextId++,
scopeOffset: getMaxOwnSourceOffset(intersection, section)
});
}
forEach(ownedBindings, (binding) => {
if (binding.closureSections) closureAccessorIds.set(binding, nextId++);
});
});
const programSection = (0, _marko_compiler_babel_utils.getProgram)().node.extra.section;
if (programSection.returnValueExpr) programSection.returnSerializeReason = getSerializeSourcesForExpr(programSection.returnValueExpr);
for (const finalize of getReferenceFinalizers()) finalize();
readsByExpression.clear();
fnReadsByExpression.clear();
}
function dropReferencedBindings(expr, drop) {
let kept;
forEach(expr.referencedBindings, (binding) => {
if (!bindingUtil.has(drop, binding)) kept = bindingUtil.add(kept, binding);
});
if (Array.isArray(kept)) return false;
expr.referencedBindings = kept;
return true;
}
function getMaxOwnSourceOffset(intersection, section) {
let scopeOffset;
const trackScopeOffset = (source) => {
if (source.scopeOffset && (!scopeOffset || scopeOffset.id < source.scopeOffset.id)) scopeOffset = source.scopeOffset;
};
for (const binding of intersection) if (binding.section === section && binding.sources) {
forEach(binding.sources.state, trackScopeOffset);
forEach(binding.sources.param, trackScopeOffset);
}
return scopeOffset;
}
const intersectionMeta = /* @__PURE__ */ new WeakMap();
const closureAccessorIds = /* @__PURE__ */ new WeakMap();
const collapsedIntersectionSource = /* @__PURE__ */ new WeakMap();
function getCollapsibleIntersectionSource(intersection, section) {
let sources;
for (const member of intersection) {
if (!member.sources) return void 0;
const isDirectAlias = member.upstreamAlias && member.property === void 0 && member.excludeProperties === void 0;
if (member.section !== section || isDirectAlias) return void 0;
sources = mergeSources(sources, member.sources);
}
if (!sources || sources.state && sources.param) return;
const source = sources.state || sources.param;
return source && !Array.isArray(source) && source.section === section && !source.scopeOffset ? source : void 0;
}
function setBindingDownstream(binding, expr, exprs) {
getBindingValueExprs().set(binding, expr || false);
if (expr && expr !== true) forEach(expr, (expr) => {
expr.downstream = bindingUtil.add(expr.downstream, binding);
if (exprs) expr.downstreamExprs = exprs;
});
}
const [getResolvedSources] = createProgramState(() => /* @__PURE__ */ new Set());
const [getBindingValueExprs] = createProgramState(() => /* @__PURE__ */ new Map());
function resolveBindingSources(binding) {
const resolvedSources = getResolvedSources();
if (resolvedSources.has(binding)) return;
resolvedSources.add(binding);
switch (binding.type) {
case 1: {
const aliasRoot = getAliasRoot(binding);
if (aliasRoot) {
resolveBindingSources(aliasRoot);
binding.sources = aliasRoot.sources;
} else if (binding.assignmentSections) binding.sources = createSources(binding, void 0);
else resolveDerivedSources(binding);
return;
}
case 2:
binding.sources = createSources(void 0, getCanonicalBinding(binding));
return;
case 3:
binding.sources = createSources(void 0, getCanonicalBinding(binding));
return;
case 7:
binding.sources = globalSources;
return;
}
const aliasRoot = getAliasRoot(binding);
if (aliasRoot) {
if (!resolvedSources.has(aliasRoot)) {
resolvedSources.add(aliasRoot);
resolveDerivedSources(aliasRoot);
}
binding.sources = aliasRoot.sources;
} else resolveDerivedSources(binding);
}
function getAliasRoot(binding) {
let alias = binding.upstreamAlias;
while (alias) {
if (!alias.upstreamAlias) return alias;
alias = alias.upstreamAlias;
}
return alias;
}
function resolveDerivedSources(binding) {
const bindingValueExprs = getBindingValueExprs();
const exprs = bindingValueExprs.get(binding);
bindingValueExprs.delete(binding);
if (exprs === void 0 || exprs === true) binding.sources = createSources(binding, void 0);
else if (exprs) {
const seen = /* @__PURE__ */ new Set();
forEach(exprs, (expr) => {
if (isReferencedExtra(expr)) forEach(expr.referencedBindings, (ref) => {
if (!seen.has(ref)) {
seen.add(ref);
resolveBindingSources(ref);
binding.sources = mergeSources(binding.sources, ref.sources);
}
});
});
}
}
function createSources(state, param, global) {
/* v8 ignore next 6 -- every caller passes at least one source */
if (!(state || param || global)) throw new Error("Cannot create a serialize reason that does not reference state, a param, or $global.");
return {
state,
param,
global
};
}
function compareSources(a, b) {
let delta;
if (a.global !== b.global) return a.global ? 1 : -1;
if (a.param) {
if (!b.param) return 1;
if (delta = compareReferences(a.param, b.param)) return delta;
} else if (b.param) return -1;
if (a.state) {
if (!b.state) return 1;
if (delta = compareReferences(a.state, b.state)) return delta;
} else if (b.state) return -1;
return 0;
}
function mergeSources(a, b) {
if (!a) return b;
if (!b) return a;
if (a.state === b.state && a.param === b.param && a.global === b.global) return a;
return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param), a.global || b.global);
}
function unionParamSources(a, b) {
const merged = bindingUtil.union(a, b);
if (merged && Array.isArray(merged)) return filter(merged, (binding) => {
let alias = binding.upstreamAlias;
while (alias) {
if (bindingUtil.has(merged, alias)) return false;
alias = alias.upstreamAlias;
}
return true;
});
return merged;
}
const bindingUtil = new Sorted(function compareBindings(a, b) {
return a === b ? 0 : a.section.id - b.section.id || (a.type !== b.type && (a.type === 0 || b.type === 0) ? a.type - b.type || a.id - b.id : a.id - b.id) || a.uid - b.uid;
});
const propsUtil = new Sorted(function compareProps(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
});
const [getReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
const [getFunctionReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
const [getReferenceFinalizers] = createProgramState(() => []);
function onFinalizeReferences(finalize) {
getReferenceFinalizers().push(finalize);
}
function getExpressionReads(exprExtra) {
return getReadsByExpression().get(exprExtra);
}
function addRead(exprExtra, extra, binding, section, getter) {
const readsByExpression = getReadsByExpression();
const read = {
binding,
extra,
getter,
ownVar: false,
comparedTo: void 0,
deferred: false
};
binding.reads.add(exprExtra);
exprExtra.section = section;
readsByExpression.set(exprExtra, push(readsByExpression.get(exprExtra), read));
return read;
}
function dropNodes(node) {
if (Array.isArray(node)) for (const item of node) dropExtra(item.extra ??= {});
else dropExtra(node.extra ??= {});
}
function dropExtra(exprExtra) {
/* v8 ignore next 3 -- a merged reference is never dropped */
if (exprExtra.merged) throw new Error("Cannot drop a merged reference");
const readsByExpr = getReadsByExpression();
const reads = readsByExpr.get(exprExtra);
exprExtra.pruned = true;
if (reads) {
readsByExpr.delete(exprExtra);
forEach(reads, (read) => {
read.binding.reads.delete(exprExtra);
});
}
}
function isSerializedChangeHandlerRead(exprRoot) {
const markoRoot = getMarkoRoot(exprRoot);
if (!markoRoot?.isMarkoAttribute()) return false;
const attr = markoRoot.node;
if (!isEventOrChangeHandler(attr.name) || isEventHandler(attr.name) || _marko_compiler.types.isFunction(attr.value)) return false;
const tag = markoRoot.parentPath;
return tag.isMarkoTag() && (tag.node.name.type !== "StringLiteral" || (0, _marko_compiler_babel_utils.isNativeTag)(tag));
}
function addReadToExpression(root, binding, getter) {
const { node } = root;
const fnRoot = getFnRoot(root);
const exprRoot = getExprRoot(fnRoot || root);
const section = getOrCreateSection(exprRoot);
const exprExtra = getCanonicalExtra(exprRoot.node.extra ??= { section });
const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
if (!fnRoot && isSerializedChangeHandlerRead(exprRoot)) read.serializedValue = true;
const { parent } = root;
if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
if (!getter && binding.type === 5) {
const babelBinding = root.scope.getBinding(binding.name);
read.ownVar = !!babelBinding && babelBinding.kind !== "param" && isReferenceInOwnBody(babelBinding.path, root);
}
if (root.parent.type === "MarkoSpreadAttribute") exprExtra.spreadFrom = binding;
if (fnRoot) {
read.deferred = fnRoot.node.type !== "ObjectMethod" || fnRoot.node.kind === "method";
const fnReadsByExpr = getFunctionReadsByExpression();
let exprFnReads = fnReadsByExpr.get(exprExtra);
if (!exprFnReads) fnReadsByExpr.set(exprExtra, exprFnReads = /* @__PURE__ */ new Map());
const fnExtra = fnRoot.node.extra ??= {};
fnExtra.section = section;
exprFnReads.set(fnExtra, push(exprFnReads.get(fnExtra), read));
}
}
function getCanonicalBinding(binding) {
const alias = binding.upstreamAlias;
if (alias && binding.property === void 0 && binding.excludeProperties === void 0) return alias;
return binding;
}
function getAllTagReferenceNodes(tag, referenceNodes = []) {
if (tag.arguments) for (const arg of tag.arguments) referenceNodes.push(arg);
for (const attr of tag.attributes) referenceNodes.push(attr.value);
for (const child of tag.body.attributeTags ? tag.body.body : tag.attributeTags) switch (child.type) {
case "MarkoTag":
getAllTagReferenceNodes(child, referenceNodes);
break;
case "MarkoScriptlet":
for (const statement of child.body) referenceNodes.push(statement);
break;
}
return referenceNodes;
}
function getScopeAccessorLiteral(binding, encoded, includeId) {
const canonicalBinding = getCanonicalBinding(binding);
if (canonicalBinding.type === 6) return _marko_compiler.types.stringLiteral(canonicalBinding.scopeAccessor ?? canonicalBinding.name);
else if (isOptimize()) return encoded ? _marko_compiler.types.numericLiteral(canonicalBinding.id) : _marko_compiler.types.stringLiteral(decodeAccessor(canonicalBinding.id));
else if (includeId || canonicalBinding.type === 0) return _marko_compiler.types.stringLiteral(`${canonicalBinding.name}/${canonicalBinding.id}`);
return _marko_compiler.types.stringLiteral(canonicalBinding.scopeAccessor ?? canonicalBinding.name);
}
function getScopeAccessor(binding, encoded, includeId) {
const canonicalBinding = getCanonicalBinding(binding);
if (canonicalBinding.type === 6) return canonicalBinding.scopeAccessor ?? canonicalBinding.name;
else if (isOptimize()) return encoded ? canonicalBinding.id + "" : decodeAccessor(canonicalBinding.id);
else if (includeId || canonicalBinding.type === 0) return `${canonicalBinding.name}/${canonicalBinding.id}`;
return canonicalBinding.scopeAccessor ?? canonicalBinding.name;
}
function getLocalsScopeAccessor(binding) {
return getScopeAccessor(binding, false, true);
}
function getPrefixedScopeAccessor(binding, prefix) {
const canonicalBinding = getCanonicalBinding(binding);
if (isOptimize()) switch (prefix) {
case getAccessorPrefix().TagVariableChange: return decodeAccessor(canonicalBinding.id + 1);
case getAccessorPrefix().ClosureScopes: return decodeAccessor(getClosureAccessorId(canonicalBinding));
case getAccessorPrefix().ClosureSignalIndex: return prefix + decodeAccessor(getClosureAccessorId(canonicalBinding));
}
return prefix + getScopeAccessor(binding);
}
function getClosureAccessorId(binding) {
const id = closureAccessorIds.get(getCanonicalBinding(binding));
/* v8 ignore next 5 -- analyze reserves an id for every closure binding */
if (id === void 0) throw new Error(`No closure accessor id was reserved for "${binding.name}".`);
return id;
}
function getDebugScopeAccess(binding) {
let root = binding;
let access = "";
while (!(root.loc || root.declared) && root.upstreamAlias && root.excludeProperties === void 0) {
if (root.property !== void 0) access = toAccess(root.property) + access;
root = root.upstreamAlias;
}
return {
root,
access
};
}
function getDebugName(binding) {
if (binding.type === 2) {
let root = binding;
let access = "";
while (root.upstreamAlias !== root.section.params && root.excludeProperties === void 0) {
if (root.property !== void 0) access = toAccess(root.property) + access;
root = root.upstreamAlias;
}
return root.name + access;
}
const { root, access } = getDebugScopeAccess(binding);
return root.name + access;
}
function getDebugNames(refs) {
return mapToString(refs, ", ", getDebugName);
}
function getDebugNamesAsIdentifier(refs) {
return mapToString(refs, "__OR__", getDebugNameAsIdentifier);
}
function getDebugNameAsIdentifier(binding) {
let root = binding;
let access = "";
if (binding.type === 2) while (root.upstreamAlias !== root.section.params && root.excludeProperties === void 0) {
if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
root = root.upstreamAlias;
}
else while (!(root.loc || root.declared) && root.upstreamAlias && root.excludeProperties === void 0) {
if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
root = root.upstreamAlias;
}
return root.name + access;
}
function getSectionInstancesAccessor(section) {
return section.sectionAccessor ? section.sectionAccessor.prefix + getScopeAccessor(section.sectionAccessor.binding) : getAccessorPrefix().ClosureScopes + section.id;
}
function getSectionInstancesAccessorLiteral(section) {
return _marko_compiler.types.stringLiteral(getSectionInstancesAccessor(section));
}
function getReadReplacement(node, signal) {
const { extra } = node;
if (!extra || extra.assignment) return;
const { read, binding } = extra;
if (read) {
const readBinding = read.binding;
let replacement;
if (read.props === void 0) {
if (read.getter?.invoked) return;
if (isOutputDOM()) {
if (read.localFn) {
if (isRegisteredFnExtra(read.localFn)) return toMemberExpression(localsIdentifier, getLocalsScopeAccessor(readBinding));
if (node.type === "Identifier" && node.name !== readBinding.name) node.name = readBinding.name;
return;
}
const inlined = getSignals(extra.section).get(readBinding)?.inline?.value;
if (inlined) replacement = _marko_compiler.types.cloneNode(inlined, true);
else if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
else if (read.getter?.hoisted) replacement = readBinding.upstreamAlias ? callRuntime("_hoist_read_error") : _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, read.getter.hoisted), [getScopeExpression(extra.section, read.getter.hoisted)]);
else if (readBinding.type === 0) {
if (read.getter) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, readBinding.section), [getScopeExpression(extra.section, readBinding.section)]);
} else if (!isOptimize() && read.ownVar) replacement = callRuntime("_assert_init", extra.section ? getScopeExpression(extra.section, readBinding.section) : scopeIdentifier, getScopeAccessorLiteral(readBinding));
else replacement = createScopeReadExpression(readBinding, extra.section);
} else if (node.type !== "Identifier") replacement = _marko_compiler.types.identifier(readBinding.name);
else if (read.getter?.hoisted) replacement = readBinding.upstreamAlias ? callRuntime("_hoist_read_error") : getBindingGetterIdentifier(readBinding, read.getter.hoisted);
else if (readBinding.type === 0) {
if (readBinding.getters.has(readBinding.section)) replacement = getBindingGetterIdentifier(readBinding, readBinding.section);
} else if (readBinding.name !== node.name) node.name = readBinding.name;
} else {
const props = read.props ? Array.isArray(read.props) ? read.props.slice() : [read.props] : [];
let curNode = node;
let curBinding = readBinding;
let replaceMember;
if (isOutputDOM()) if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
else replacement = createScopeReadExpression(readBinding, extra.section);
else replacement = _marko_compiler.types.identifier(readBinding.name);
while (props.length && (curNode.type === "MemberExpression" || curNode.type === "OptionalMemberExpression")) {
const prop = props.pop();
if (getMemberExpressionPropString(curNode) !== prop) break;
replaceMember = curNode;
curNode = curNode.object;
}
for (const prop of props) {
if (curBinding) curBinding = curBinding.propertyAliases.get(prop);
replacement = toMemberExpression(replacement, prop, !!curBinding?.nullable);
}
if (replaceMember) {
if (readBinding.nullable && replaceMember.object.type !== replacement.type) {
replaceMember.type = "OptionalMemberExpression";
replaceMember.optional = true;
}
replaceMember.object = withPreviousLocation(replacement, replaceMember.object);
replacement = void 0;
}
}
return replacement && withPreviousLocation(replacement, node);
} else if (binding && node.type == "Identifier" && node.name !== binding.name) node.name = binding.name;
}
function isInvokeOnlyBinding(binding) {
if (binding.assignmentSections || binding.hoists || binding.getters.size || binding.propertyAliases.size || binding.excludeProperties) return false;
for (const expr of binding.reads) if (!expr.invokeOnly) return false;
for (const alias of binding.aliases) if (!isInvokeOnlyBinding(alias)) return false;
return true;
}
function hasNonConstantPropertyAlias(ref) {
for (const alias of ref.propertyAliases.values()) if (alias.type !== 6) return true;
return false;
}
function pruneBinding(binding) {
if (binding.pruned !== void 0) return binding.pruned;
for (const read of binding.reads) {
let upstream = binding.upstreamAlias;
while (upstream && !upstream.reads.has(read)) upstream = upstream.upstreamAlias;
if (upstream) binding.reads.delete(read);
}
let shouldPrune = !binding.reads.size && !binding.reserveSize;
for (const alias of binding.aliases) if (pruneBinding(alias)) binding.aliases.delete(alias);
else if (alias.type !== 6) shouldPrune = false;
for (const [key, alias] of binding.propertyAliases) if (pruneBinding(alias)) binding.propertyAliases.delete(key);
else if (alias.type !== 6) shouldPrune = false;
binding.pruned = shouldPrune;
return shouldPrune;
}
function resolveReferencedBindingsInFunction(refs, reads) {
let referencedBindings;
let constantBindings;
if (reads) if (Array.isArray(reads)) for (const read of reads) {
const { getter, binding } = read;
if (getter) {} else if (binding.type === 6) {
if (bindingUtil.find(refs, binding)) constantBindings = bindingUtil.add(constantBindings, binding);
} else if (binding.type !== 0 && binding.type !== 7) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
}
else {
const { getter, binding } = reads;
if (getter) {} else if (binding.type === 6) {
if (bindingUtil.find(refs, binding)) constantBindings = binding;
} else if (binding.type !== 0 && binding.type !== 7) referencedBindings = findClosestReference(binding, refs);
}
return {
referencedBindings,
constantBindings
};
}
function findClosestReference(from, refs) {
if (Array.isArray(refs)) {
if (bindingUtil.has(refs, from)) return from;
for (const ref of refs) {
const closest = findClosestUpstream(from, ref);
if (closest) return closest;
}
} else {
const closest = findClosestUpstream(from, refs);
if (closest) return closest;
}
}
function findClosestUpstream(from, to) {
let closest = from;
do
if (closest === to) return closest;
while (closest = closest.upstreamAlias);
}
function getRootBindings(reads) {
let rootRefs;
let allBindings;
for (const { binding } of reads) allBindings = bindingUtil.add(allBindings, binding);
for (const { binding } of reads) {
let alias = binding.upstreamAlias;
while (alias) {
if (bindingUtil.has(allBindings, alias)) break;
alias = alias.upstreamAlias;
}
if (!alias) rootRefs = bindingUtil.add(rootRefs, binding);
}
return rootRefs;
}
function addBindingGetter(binding, { invoked, hoisted }) {
if (!invoked || !binding.getters.has(hoisted)) {
if (hoisted === binding.section) binding.getters.delete(false);
if (hoisted || !binding.getters.has(binding.section)) binding.getters.set(hoisted, !invoked);
}
}
function isLazyRead(expr, read, binding, isChangeHandlerRead) {
return !!(expr.invokeOnly && read.deferred && !isChangeHandlerRead && (!binding.upstreamAlias || isParamBinding(binding)) && binding.type !== 0 && binding.type !== 6 && (binding.type !== 4 || binding.section === expr.section));
}
function isParamBinding(binding) {
let root = binding;
while (root.upstreamAlias) root = root.upstreamAlias;
return root === root.section.params;
}
function resolveReferencedBindings(expr, reads, intersectionsBySection) {
let referencedBindings;
let constantBindings;
let hoistedBindings;
let allBindings;
let lazyBindings;
let globalBindings;
if (Array.isArray(reads)) {
const rootBindings = getRootBindings(reads);
for (const read of reads) {
let { binding } = read;
const { extra, getter } = read;
if (getter) {
extra.section = expr.section;
extra.read = createGetterRead(binding, void 0, getter);
addBindingGetter(binding, getter);
if (getter.hoisted) {
binding.hoists = sectionUtil.add(binding.hoists, getter.hoisted);
hoistedBindings = bindingUtil.add(hoistedBindings, binding);
}
} else {
const isChangeHandlerRead = extra.assignmentTo === binding;
if (isChangeHandlerRead) {
const upstreamRoot = binding.upstreamAlias && findClosestReference(binding.upstreamAlias, rootBindings);
if (upstreamRoot) binding = upstreamRoot;
} else if (binding.type !== 7) {
extra.section = expr.section;
({binding} = extra.read ??= resolveExpressionReference(rootBindings, binding));
}
if (binding.type === 7) globalBindings = bindingUtil.add(globalBindings, binding);
else if (isLazyRead(expr, read, binding, isChangeHandlerRead)) lazyBindings = bindingUtil.add(lazyBindings, binding);
else if (binding.type === 6) constantBindings = bindingUtil.add(constantBindings, binding);
else if (binding.type !== 0) referencedBindings = bindingUtil.add(referencedBindings, binding);
}
allBindings = bindingUtil.add(allBindings, binding);
}
} else if (reads) {
const { binding, extra, getter, ownVar } = reads;
if (getter) {
extra.read = createGetterRead(binding, void 0, getter);
addBindingGetter(binding, getter);
if (getter.hoisted) {
binding.hoists = sectionUtil.add(binding.hoists, getter.hoisted);
hoistedBindings = bindingUtil.add(hoistedBindings, binding);
}
} else if (binding.type === 7) globalBindings = binding;
else {
extra.read = createRead(binding, void 0, ownVar);
if (isLazyRead(expr, reads, binding, extra.assignmentTo === binding)) lazyBindings = binding;
else if (binding.type === 6) constantBindings = binding;
else if (binding.type !== 0) referencedBindings = binding;
}
extra.section = expr.section;
allBindings = binding;
}
if (lazyBindings) {
let onlyLazy;
forEach(lazyBindings, (binding) => {
if (!bindingUtil.has(referencedBindings, binding)) onlyLazy = bindingUtil.add(onlyLazy, binding);
});
lazyBindings = onlyLazy;
}
if (Array.isArray(referencedBindings)) {
const intersections = intersectionsBySection.get(expr.section) || [];
const intersection = findSorted(compareIntersections, intersections, referencedBindings);
if (intersection) referencedBindings = intersection;
else intersectionsBySection.set(expr.section, addSorted(compareIntersections, intersections, referencedBindings));
}
if (referencedBindings && constantBindings) {
const intersections = intersectionsBySection.get(expr.section) || [];
const combined = bindingUtil.union(referencedBindings, constantBindings);
if (!findSorted(compareIntersections, intersections, combined)) intersectionsBySection.set(expr.section, addSorted(compareIntersections, intersections, combined));
}
return {
referencedBindings,
constantBindings,
hoistedBindings,
allBindings,
lazyBindings,
globalBindings
};
}
function resolveExpressionReference(rootBindings, readBinding) {
const upstreamRoot = readBinding.upstreamAlias && findClosestReference(readBinding.upstreamAlias, rootBindings);
if (!upstreamRoot) return createRead(readBinding, void 0);
let curBinding = readBinding;
let props;
while (curBinding !== upstreamRoot) {
if (curBinding.property !== void 0) props = push(props, curBinding.property);
curBinding = curBinding.upstreamAlias;
}
if (Array.isArray(props)) props.reverse();
return createRead(upstreamRoot, props);
}
function isSupersetSources(a, b) {
if (!b.sources) return true;
if (!a.sources) return false;
return bindingUtil.isSuperset(a.sources.state, b.sources.state) && bindingUtil.isSuperset(a.sources.param, b.sources.param);
}
function createRead(binding, props, ownVar = false) {
return {
binding,
props,
ownVar,
getter: void 0
};
}
function createGetterRead(binding, props, getter) {
return {
binding,
props,
ownVar: false,
getter
};
}
function isReferencedExtra(extra) {
return !!(extra && !extra.pruned && extra.section);
}
function isAssignedBindingExtra(extra) {
return isReferencedExtra(extra) && extra.assignment !== void 0;
}
function isRegisteredFnExtra(extra) {
return isReferencedExtra(extra) && extra.registerId !== void 0;
}
function getCanonicalExtra(extra) {
while (extra.merged) extra = extra.merged;
return extra;
}
const serializeReasonCache = /* @__PURE__ */ new WeakMap();
const registerReasonCache = /* @__PURE__ */ new WeakMap();
function getAllSerializeReasonsForExtra(extra, register) {
if (extra.isEffect || register && extra.dynamicTagInput) return true;
const cache = register ? registerReasonCache : serializeReasonCache;
let reason = cache.get(extra);
if (reason === false) return;
if (reason === void 0) {
if (extra === (0, _marko_compiler_babel_utils.getProgram)().node.extra?.section.returnValueExpr) reason = true;
else {
cache.set(extra, false);
forEach(extra.downstream, (binding) => {
let linked = getAllSerializeReasonsForBinding(binding, true, register);
if (linked && linked !== true) {
const exprs = extra.downstreamExprs;
if (exprs) linked = mapDownstreamReason(binding.section.program, linked, exprs);
}
reason = mergeSerializeReasons(reason, linked);
});
}
if (reason) cache.set(extra, reason);
}
return reason;
}
function getAllSerializeReasonsForBinding(binding, properties, register) {
const cache = register ? registerReasonCache : serializeReasonCache;
let reason = cache.get(binding);
if (reason === void 0) {
reason = getSerializeReason(binding.section, binding);
if (reason !== true) {
cache.set(binding, reason || false);
if (properties !== true && binding.upstreamAlias) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(binding.upstreamAlias, binding.property, register));
if (reason !== true) {
for (const expr of binding.reads) {
reason = mergeSerializeReasons(reason, getAllSerializeReasonsForExtra(expr, register));
if (reason === true) break;
}
if (reason !== true) for (const alias of binding.aliases) {
reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(alias, properties, register));
if (reason === true) break;
}
}
}
if (reason) cache.set(binding, reason);
}
if (reason === false) reason = void 0;
if (properties !== void 0) if (properties === true) {
if (reason !== true) for (const propBinding of binding.propertyAliases.values()) {
reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, true, register));
if (reason === true) break;
}
} else {
let property;
let rest;
if (Array.isArray(properties)) {
property = properties[0];
rest = properties.length === 2 ? properties[1] : properties.slice(1);
} else property = properties;
if (includes(binding.excludeProperties, property)) reason = void 0;
else {
const propBinding = binding.propertyAliases.get(property);
if (propBinding) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, rest, register));
if (reason !== true) for (const alias of binding.aliases) {
const propBinding = alias.propertyAliases.get(property);
if (propBinding) {
reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, rest, register));
if (reason === true) break;
}
}
}
}
return reason;
}
function isPureSpreadResolved(binding) {
for (const read of binding.reads) if (!read.nativeTagSpread || read.nativeTagSpreadMerged) return false;
for (const alias of binding.aliases) if (!isPureSpreadResolved(alias)) return false;
return true;
}
function hasAnyMemberAccess(binding) {
if (binding.propertyAliases.size) return true;
for (const alias of binding.aliases) if (hasAnyMemberAccess(alias)) return true;
return false;
}
function isPropertyMemberAccessed(binding, property) {
if (binding.propertyAliases.has(property)) return true;
for (const alias of binding.aliases) if (isPropertyMemberAccessed(alias, property)) return true;
return false;
}
function addNumericPropertiesUntil(props, len) {
let result = props;
for (let i = len; i--;) result = propsUtil.add(result, i + "");
return result;
}
function setReadsOwner(from, to) {
let cur = from;
while (cur !== to && cur.parent) {
cur.readsOwner = true;
cur = cur.parent;
}
}
function mapParamReasonToExpr(exprs, reason) {
if (reason) {
if (reason === true) return true;
const result = /* @__PURE__ */ new Set();
forEach(reason, (prop) => {
forEach(mapParamBindingToExpr(exprs, prop), (expr) => {
result.add(expr);
});
});
return fromIter(result);
}
}
function mapParamBindingToExpr(exprs, binding) {
const isWholeAlias = binding.property === void 0 && binding.upstreamAlias !== void 0;
const props = [];
let curBinding = isWholeAlias ? binding.upstreamAlias : binding;
while (curBinding && (curBinding.property !== void 0 || curBinding.upstreamAlias)) {
if (curBinding.property !== void 0) props.push(curBinding.property);
curBinding = curBinding.upstreamAlias;
}
let curExpr = exprs;
for (let i = props.length; i--;) {
const nestedExpr = curExpr.known?.[props[i]];
if (!nestedExpr) return curExpr.value;
curExpr = nestedExpr;
}
if (isWholeAlias) {
let result = curExpr.value;
if (curExpr.known) {
for (const key in curExpr.known) if (!includes(binding.excludeProperties, key)) result = concat(result, curExpr.known[key].value);
}
return result;
}
return curExpr.value;
}
//#endregion
//#region src/translator/core/await.ts
const kDOMBinding$2 = Symbol("await tag dom binding");
var await_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag, "Write the promise as a value attribute and receive the result as a tag parameter instead: `<await|result|=promise>`.");
assertNoSpreadAttrs(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag, "For pending and error UI, wrap the `<await>` in a [`<try>` tag](https://markojs.com/docs/reference/core-tag#try) with `<@placeholder>` and `<@catch|err|>` attribute tags.");
const { node } = tag;
const tagBody = tag.get("body");
const section = getOrCreateSection(tag);
const [valueAttr] = node.attributes;
const tagExtra = tag.node.extra ??= {};
tagExtra[kDOMBinding$2] = createBinding("#text", 0, section);
if (!valueAttr) throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
if (node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
if (!node.body.body.length) throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) requires [content](https://markojs.com/docs/reference/language#tag-content).");
if (node.body.params.length && (node.body.params.length > 1 || _marko_compiler.types.isSpreadElement(node.body.params[0]))) throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) only supports a single parameter.");
const bodySection = startSection(tagBody);
const valueExtra = evaluate(valueAttr.value);
const paramsBinding = trackParamsReferences(tagBody, 5);
if (paramsBinding) setBindingDownstream(paramsBinding, valueExtra);
bodySection.upstreamExpression = valueAttr.value.extra;
addSetupStatement(section);
visit(tag, 37);
enterShallow(tag);
},
translate: translateByTarget({
html: {
enter(tag) {
const bodySection = getSectionForBody(tag.get("body"));
if (!bodySection) {
tag.remove();
return;
}
setSectionParentIsOwner(bodySection, true);
flushBefore(tag);
},
exit(tag) {
const { node } = tag;
const [valueAttr] = node.attributes;
const nodeRef = node.extra[kDOMBinding$2];
const tagBody = tag.get("body");
const section = getSection(tag);
const bodySection = getSectionForBody(tagBody);
flushInto(tag);
writeHTMLResumeStatements(tagBody);
tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_await", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeRef), valueAttr.value, _marko_compiler.types.arrowFunctionExpression(node.body.params, toFirstExpressionOrBlock(node.body.body)), getSerializeGuard(section, bodySection?.serializeReason, true))))[0].skip();
}
},
dom: {
enter(tag) {
const bodySection = getSectionForBody(tag.get("body"));
if (!bodySection) {
tag.remove();
return;
}
setSectionParentIsOwner(bodySection, true);
},
exit(tag) {
const { node } = tag;
const nodeRef = node.extra[kDOMBinding$2];
const section = getSection(tag);
const bodySection = getSectionForBody(tag.get("body"));
const signal = getSignal(section, nodeRef, "await_promise");
const valueExpr = node.attributes[0].value;
signal.build = () => {
const branchRenderArgs = getBranchRendererArgs(bodySection);
const branchParams = branchRenderArgs.pop();
(signal.prependStatements ||= []).push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(bodySection.name), callRuntime("_await_content", getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(branchRenderArgs)))]));
importRuntimeFeature("catch");
return callRuntime("_await_promise", getScopeAccessorLiteral(nodeRef, true), branchParams);
};
addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), [scopeIdentifier])));
addValue(section, valueExpr.extra?.referencedBindings, signal, valueExpr);
tag.remove();
}
}
}),
attributes: {},
autocomplete: [{
description: "Use to consume asynchronous data.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#await"
}],
types: runtime_info_default.name + "/tags/await.d.marko"
};
//#endregion
//#region src/translator/core/class.ts
var class_default = {
parse(tag) {
throw tag.hub.buildError(tag.node.name, "class {} component blocks are no longer supported. Use <let> and <const> tags for state.");
},
parseOptions: {
statement: true,
rawOpenTag: true
}
};
//#endregion
//#region src/translator/util/statement-tag.ts
function createStatementTag(keyword) {
const target = keyword === "static" ? void 0 : keyword;
const keywordReg = new RegExp(`^${keyword}\\s*`);
return {
parse(tag) {
const { node } = tag;
const file = (0, _marko_compiler_babel_utils.getFile)();
const rawValue = node.rawValue;
const code = rawValue.replace(keywordReg, "");
const start = node.start + (rawValue.length - code.length);
let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, target));
},
parseOptions: {
statement: true,
rawOpenTag: true
},
autocomplete: [{
displayText: `${keyword} <statement>`,
description: `A JavaScript statement which is only evaluated once your template is loaded${target ? ` on the ${target}` : ""}.`,
descriptionMoreURL: `https://markojs.com/docs/reference/language#${keyword === "static" ? "static" : "server-and-client"}`
}]
};
}
//#endregion
//#region src/translator/core/client.ts
var client_default = createStatementTag("client");
//#endregion
//#region src/translator/core/const.ts
var const_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
const { node } = tag;
const [valueAttr] = node.attributes;
if (!node.var) {
const looksLikeDeclaration = !node.attributes.some((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.default || attr.name === "value")) && node.attributes.length === 1 && _marko_compiler.types.isMarkoAttribute(node.attributes[0]) && /^[A-Za-z_$][\w$]*$/.test(node.attributes[0].name);
throw tag.get("name").buildCodeFrameError(`The [\`<const>\` tag](https://markojs.com/docs/reference/core-tag#const) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables)${looksLikeDeclaration ? `; the variable goes after a slash: \`<const/${node.attributes[0].name}=...>\`. For a one time module level value, prefix a plain JavaScript statement with \`static\`.` : ", e.g. `<const/doubled=count * 2>`."}`);
}
if (!valueAttr) throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
if (node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
const valueExtra = evaluate(valueAttr.value);
const upstreamAlias = _marko_compiler.types.isIdentifier(valueAttr.value) ? tag.scope.getBinding(valueAttr.value.name)?.identifier.extra?.binding : void 0;
if (upstreamAlias) dropNodes(valueAttr.value);
const binding = trackVarReferences(tag, 5, upstreamAlias);
if (binding) {
assertNoTagVarMutation(tag);
if (!valueExtra.nullable) binding.nullable = false;
if (!upstreamAlias) {
setBindingDownstream(binding, valueExtra);
addSetupExpr(getOrCreateSection(tag), valueAttr.value);
}
}
},
translate: { exit(tag) {
const { node } = tag;
const [valueAttr] = node.attributes;
const { value } = valueAttr;
if (isOutputDOM()) {
const section = getSection(tag);
const varBinding = node.var.extra?.binding;
if (varBinding && !varBinding.upstreamAlias) {
const derivation = initValue(varBinding);
addValue(section, value.extra?.referencedBindings, derivation, value);
}
} else translateVar(tag, value);
tag.remove();
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
description: "Use to create a constant binding.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#const"
}],
types: runtime_info_default.name + "/tags/const.d.marko"
};
//#endregion
//#region src/translator/core/debug.ts
var debug_default = {
analyze(tag) {
const [valueAttr] = tag.node.attributes;
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
if (tag.node.attributes.length > 1 || tag.node.attributes.length === 1 && (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value")) throw tag.get("name").buildCodeFrameError("The [`<debug>` tag](https://markojs.com/docs/reference/core-tag#debug) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
addSetupExpr(getOrCreateSection(tag), valueAttr?.value);
},
translate: { exit(tag) {
const section = getSection(tag);
const [valueAttr] = tag.node.attributes;
const referencedBindings = valueAttr?.value.extra?.referencedBindings;
const statement = withPreviousLocation(_marko_compiler.types.debuggerStatement(), tag.node);
if (isOutputHTML()) tag.insertBefore(statement);
else addStatement("render", section, referencedBindings, statement);
tag.remove();
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
description: "Debug on value change.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#debug"
}],
types: runtime_info_default.name + "/tags/debug.d.marko"
};
//#endregion
//#region src/translator/core/define.ts
var define_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
if (!tag.node.var) throw tag.get("name").buildCodeFrameError("The [`<define>` tag](https://markojs.com/docs/reference/core-tag#define) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
const tagBody = tag.get("body");
const bodySection = startSection(tagBody);
const varBinding = trackVarReferences(tag, 5);
if (!varBinding) {
dropNodes(getAllTagReferenceNodes(tag.node));
return;
}
assertNoTagVarMutation(tag);
const paramsBinding = trackParamsReferences(tagBody, 3);
setTagDownstream(tag, varBinding);
if (bodySection) {
if (_marko_compiler.types.isIdentifier(tag.node.var)) {
const babelBinding = tag.scope.getBinding(tag.node.var.name);
let allDirectReferences = true;
let allHaveInput = true;
for (const ref of babelBinding.referencePaths) {
if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError("Hoisted values must be functions. The `<define>` tag variable may not be hoisted. Please move the `<define>` tag prior to any references or extract to a separate `.marko` file.");
if (ref.parent.type === "MarkoTag" && ref.parent.name === ref.node) {
(ref.parent.extra ??= {}).defineBodySection = bodySection;
allHaveInput &&= !ref.parent.arguments?.length;
dropNodes(ref.parent.name);
} else {
allHaveInput = false;
allDirectReferences = false;
}
}
if (allDirectReferences) {
const inputAlias = allHaveInput && paramsBinding?.propertyAliases.get("0");
if (inputAlias) inputAlias.nullable = false;
dropNodes(getAllTagReferenceNodes(tag.node));
return;
}
}
}
analyzeAttributeTags(tag);
setBindingDownstream(varBinding, mergeReferences(getOrCreateSection(tag), tag.node, getAllTagReferenceNodes(tag.node)));
},
translate: {
enter(tag) {
if (!tag.node.var) {
tag.remove();
return;
}
if (isOutputHTML()) flushBefore(tag);
},
exit(tag) {
const { node } = tag;
const translatedAttrs = translateAttrs(tag);
if (isOutputHTML()) {
flushInto(tag);
writeHTMLResumeStatements(tag.get("body"));
translateVar(tag, propsToExpression(translatedAttrs.properties), "const", translatedAttrs.statements);
tag.insertBefore(translatedAttrs.statements);
} else {
if (_marko_compiler.types.isIdentifier(node.var)) {
const babelBinding = tag.scope.getBinding(node.var.name);
let hasDirectReferences = false;
let allDirectReferences = true;
for (const ref of babelBinding.referencePaths) if (ref.parent.type === "MarkoTag" && ref.parent.name === ref.node) hasDirectReferences = true;
else allDirectReferences = false;
if (allDirectReferences) {
const bodySection = getSectionForBody(tag.get("body"));
if (bodySection) {
if (hasDirectReferences) {
const signal = getSignal(bodySection, void 0);
signal.build = () => {
if (signalHasStatements(signal)) return callRuntime("_child_setup", getSignalFn(signal));
};
}
tag.remove();
return;
}
}
}
const section = getSection(tag);
const referencedBindings = node.extra?.referencedBindings;
if (translatedAttrs.statements.length) addStatement("render", section, referencedBindings, translatedAttrs.statements);
addValue(section, referencedBindings, initValue(tag.get("var").node.extra.binding), propsToExpression(translatedAttrs.properties));
}
tag.remove();
}
},
attributes: {},
autocomplete: [{
description: "Use to create a constant object binding that can be rendered.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#define"
}],
types: runtime_info_default.name + "/tags/define.d.marko"
};
//#endregion
//#region src/translator/core/effect.ts
var effect_default = {
migrate: [(tag) => {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
assertNoSpreadAttrs(tag);
(0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, ["value"]);
(0, _marko_compiler_babel_utils.diagnosticDeprecate)(tag, {
label: "The 'effect' tag has been replaced by the 'script' tag.",
fix() {
const { node } = tag;
tag.replaceWith(_marko_compiler.types.markoTag(withPreviousLocation(_marko_compiler.types.stringLiteral("script"), node.name), node.attributes, node.body, node.arguments, node.var, node.attributeTags));
}
});
}],
attributes: {},
types: runtime_info_default.name + "/tags/effect.d.marko"
};
//#endregion
//#region src/translator/core/export.ts
var export_default = {
parse(tag) {
const { node } = tag;
const statements = (0, _marko_compiler_babel_utils.parseStatements)((0, _marko_compiler_babel_utils.getFile)(), node.rawValue, node.start, node.end);
if (statements.length > 1) throw tag.hub.buildError(statements[1], "The `<export>` tag takes a single export statement.");
const defaultExport = getDefaultExport(statements[0]);
if (defaultExport) throw tag.hub.buildError(defaultExport, "A template is already its own default export. Use a named export instead.");
tag.replaceWith(statements[0]);
},
parseOptions: {
statement: true,
rawOpenTag: true
},
autocomplete: [{ displayText: "export <value>" }]
};
function getDefaultExport(statement) {
if (statement.type === "ExportDefaultDeclaration") return statement;
if (statement.type !== "ExportNamedDeclaration") return;
for (const specifier of statement.specifiers) {
const { exported } = specifier;
if (exported && (exported.type === "Identifier" ? exported.name : exported.value) === "default") return specifier;
}
}
//#endregion
//#region src/translator/core/html-comment.ts
const kNodeBinding$1 = Symbol("comment tag binding");
const escapeCommentText = (text) => text.replace(/>/g, ">");
var html_comment_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
(0, _marko_compiler_babel_utils.assertNoAttributes)(tag);
const tagVar = tag.node.var;
let needsBinding = false;
if (tagVar) {
if (!_marko_compiler.types.isIdentifier(tagVar)) throw tag.get("var").buildCodeFrameError("The [`<html-comment>` tag](https://markojs.com/docs/reference/core-tag#html-comment) tag variable cannot be destructured.");
needsBinding = true;
}
let nodeBinding;
const referenceNodes = [];
for (const child of tag.get("body").get("body")) if (child.isMarkoPlaceholder()) {
referenceNodes.push(child.node.value);
needsBinding = true;
} else if (!child.isMarkoText()) throw child.buildCodeFrameError("Invalid child. Only text is allowed inside an html comment.");
if (needsBinding) {
const tagSection = getOrCreateSection(tag);
const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
trackDomVarReferences(tag, nodeBinding);
if (tagVar) addSerializeExpr(tagSection, true, nodeBinding);
addSerializeExpr(tagSection, tagExtra, nodeBinding);
}
const write = writeTo(tag);
if (nodeBinding) visit(tag, 32);
enter(tag);
write`<!--`;
const textLiteral = bodyToRawTextLiteral(tag.node.body);
if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${escapeCommentText(textLiteral.value)}`;
exit(tag);
write`-->`;
tag.skip();
},
translate: { exit(tag) {
const tagSection = getSection(tag);
const tagExtra = tag.node.extra;
const nodeBinding = tagExtra[kNodeBinding$1];
const write = writeTo$1(tag);
if (isOutputHTML()) {
const { body } = tag.node.body;
write`<!--`;
if (nodeBinding && isEmptiableCommentBody(body)) if (body.length) write`${_marko_compiler.types.logicalExpression("||", buildCommentValue(body), _marko_compiler.types.stringLiteral(" "))}`;
else write` `;
else for (const child of body) if (_marko_compiler.types.isMarkoText(child)) write`${escapeCommentText(child.value)}`;
else if (_marko_compiler.types.isMarkoPlaceholder(child)) write`${callRuntime(child.escape ? "_escape_comment" : "_unescaped", child.value)}`;
write`-->`;
} else {
const textLiteral = bodyToTextLiteral(tag.node.body);
if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
}
if (nodeBinding) markNode(tag, nodeBinding, getSerializeReason(tagSection, nodeBinding));
tag.remove();
} },
parseOptions: { text: true },
types: runtime_info_default.name + "/tags/html-comment.d.marko",
autocomplete: [{
description: "Use to create an html comment that is not stripped from the output.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-comment"
}]
};
function isEmptiableCommentBody(body) {
for (const child of body) if (!_marko_compiler.types.isMarkoPlaceholder(child) || isNonEmptyLiteral(child.value)) return false;
return true;
}
function isNonEmptyLiteral(value) {
return _marko_compiler.types.isStringLiteral(value) ? !!value.value : _marko_compiler.types.isNumericLiteral(value);
}
function buildCommentValue(body) {
let value;
for (const child of body) {
const part = callRuntime(child.escape ? "_escape_comment" : "_unescaped", child.value);
value = value ? _marko_compiler.types.binaryExpression("+", value, part) : part;
}
return value;
}
//#endregion
//#region src/translator/core/html-script.ts
var html_script_default = {
types: runtime_info_default.name + "/tags/html-script.d.marko",
html: true,
parseOptions: {
text: true,
preserveWhitespace: true
},
autocomplete: [{
description: "Use instead of `<script>` to render a native tag directly, without processing by Marko.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
}]
};
//#endregion
//#region src/translator/core/html-style.ts
var html_style_default = {
types: runtime_info_default.name + "/tags/html-style.d.marko",
html: true,
parseOptions: {
text: true,
preserveWhitespace: true
},
autocomplete: [{
description: "Use instead of `<style>` to render a native tag directly, without processing by Marko.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
}]
};
//#endregion
//#region src/translator/core/id.ts
var id_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
const { node } = tag;
const [valueAttr] = node.attributes;
if (!node.var) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
if (!_marko_compiler.types.isIdentifier(node.var)) throw tag.get("var").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) cannot be destructured.");
if (tag.node.attributes.length > 1 || tag.node.attributes.length === 1 && (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value")) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
const binding = trackVarReferences(tag, 5);
if (binding) {
assertNoTagVarMutation(tag);
setBindingDownstream(binding, !!valueAttr && evaluate(valueAttr.value));
}
addSetupExpr(getOrCreateSection(tag), valueAttr?.value);
},
translate: { exit(tag) {
const { node } = tag;
const id = isOutputHTML() ? callRuntime("_id") : callRuntime("_id", scopeIdentifier);
const [valueAttr] = tag.node.attributes;
if (isOutputHTML()) tag.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, valueAttr ? _marko_compiler.types.logicalExpression("||", valueAttr.value, id) : id)]));
else {
const section = getSection(tag);
const source = initValue(node.var.extra.binding);
if (valueAttr) {
const { value } = valueAttr;
addValue(section, value.extra?.referencedBindings, source, _marko_compiler.types.logicalExpression("||", value, evaluate(value).confident ? id : callRuntime("_id", scopeIdentifier, _marko_compiler.types.stringLiteral(getPrefixedScopeAccessor(node.var.extra.binding, getAccessorPrefix().IdFallback)))));
} else addValue(section, void 0, source, id);
tag.remove();
}
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
displayText: "id/<name>",
description: "Use to create a unique identifier.",
snippet: "id/${1:name}",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#id"
}],
types: runtime_info_default.name + "/tags/id.d.marko"
};
//#endregion
//#region src/translator/core/import.ts
var import_default = {
parse(tag) {
const { node } = tag;
const statements = (0, _marko_compiler_babel_utils.parseStatements)((0, _marko_compiler_babel_utils.getFile)(), node.rawValue, node.start, node.end);
if (statements.length > 1) throw tag.hub.buildError(statements[1], "The [`<import>` tag](https://markojs.com/docs/reference/language#import) takes a single import statement.");
tag.replaceWith(statements[0]);
},
parseOptions: {
statement: true,
rawOpenTag: true
},
autocomplete: [{
displayText: "import <scope> from \"<path>\"",
description: "Use to import external modules, follows the same syntax as JavaScript imports.",
snippet: "import ${2} from \"${1:path}\"",
descriptionMoreURL: "https://markojs.com/docs/reference/language#import"
}]
};
//#endregion
//#region src/translator/core/let.ts
var let_default = {
analyze(tag) {
const { node } = tag;
const tagVar = node.var;
let valueAttr;
let valueChangeAttr;
for (const attr of node.attributes) if (_marko_compiler.types.isMarkoAttribute(attr)) if (attr.name === "value") {
if (valueAttr) throw tag.hub.buildError(attr, "Invalid duplicate value attribute.");
valueAttr = attr;
} else if (attr.name === "valueChange") {
if (valueChangeAttr) throw tag.hub.buildError(attr, "Invalid duplicate valueChange attribute.");
valueChangeAttr = attr;
} else {
const start = attr.loc?.start;
const end = attr.loc?.end;
let msg = "The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value) and its change handler.";
if (!tagVar && /^[A-Za-z_$][\w$]*$/.test(attr.name)) msg += ` To declare reactive state, the variable goes after a slash: \`<let/${attr.name}=...>\`. For a one time module level value, prefix a plain JavaScript statement with \`static\`.`;
if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
else throw tag.hub.buildError({ loc: {
start,
end
} }, msg, Error);
}
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
assertNoSpreadAttrs(tag);
if (!tagVar) throw tag.get("name").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables), e.g. `<let/count=0>`.");
if (!_marko_compiler.types.isIdentifier(tagVar)) throw tag.get("var").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) variable cannot be destructured.");
if (valueChangeAttr && (0, _marko_compiler_babel_utils.computeNode)(valueChangeAttr.value)?.value) throw tag.get("attributes").find((attr) => attr.node === valueChangeAttr).get("value").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) [`valueChange=` attribute](https://markojs.com/docs/reference/core-tag#controllable-let) must be a function.");
const tagSection = getOrCreateSection(tag);
const binding = trackVarReferences(tag, 1);
const tagExtra = mergeReferences(tagSection, tag.node, [valueAttr?.value, valueChangeAttr?.value]);
if (valueChangeAttr) {
binding.reserveSize = 1;
setBindingDownstream(binding, tagExtra);
if (binding.assignmentSections) addSerializeReason(tagSection, true, binding, getAccessorPrefix().TagVariableChange);
} else setBindingDownstream(binding, false);
},
translate: { exit(tag) {
const { node } = tag;
const tagVar = node.var;
const valueAttr = node.attributes.find((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.default || attr.name === "value")) ?? _marko_compiler.types.markoAttribute("value", _marko_compiler.types.identifier("undefined"));
const valueChangeAttr = node.attributes.find((attr) => _marko_compiler.types.isMarkoAttribute(attr) && attr.name === "valueChange");
const section = getSection(tag);
const binding = tagVar.extra.binding;
if (isOutputDOM()) {
const signal = initValue(binding, true);
const referencedBindings = tag.node.extra.referencedBindings;
addValue(section, referencedBindings, signal, valueAttr.value);
if (valueChangeAttr) signal.extraArgs = [valueChangeAttr.value];
signal.buildAssignment = (valueSection, value) => {
if (valueChangeAttr || signalHasStatements(signal)) return _marko_compiler.types.callExpression(signal.identifier, [getScopeExpression(valueSection, signal.section), value]);
};
} else {
translateVar(tag, valueAttr.value, "let");
if (valueChangeAttr) setBindingSerializedValue(section, binding, _marko_compiler.types.logicalExpression("||", valueChangeAttr.value, _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0))), getAccessorPrefix().TagVariableChange);
}
tag.remove();
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
description: "Use to create a mutable binding.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#let"
}],
types: runtime_info_default.name + "/tags/let.d.marko"
};
//#endregion
//#region src/translator/core/lifecycle.ts
const [getIndex, setIndex] = createSectionState("lifecycleIndex", () => 0);
var lifecycle_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
const { node } = tag;
const section = getOrCreateSection(tag);
const tagExtra = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
tagExtra.isEffect = true;
section.hasAbortSignal = true;
if (node.attributes.length === 0) throw tag.get("name").buildCodeFrameError("The [`<lifecycle>` tag](https://markojs.com/docs/reference/core-tag#lifecycle) requires at least one attribute.");
for (const attr of node.attributes) if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) throw tag.get("name").buildCodeFrameError("The [`<lifecycle>` tag](https://markojs.com/docs/reference/core-tag#lifecycle) does not support [`...spread` attributes](https://markojs.com/docs/reference/language#spread-attributes).");
(0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
},
translate: { exit(tag) {
const { node } = tag;
const section = getSection(tag);
const { referencedBindings } = node.extra;
if (isOutputDOM()) {
const translatedAttrs = translateAttrs(tag);
const index = getIndex(section);
setIndex(section, index + 1);
translatedAttrs.statements.push(_marko_compiler.types.expressionStatement(callRuntime("_lifecycle", scopeIdentifier, propsToExpression(translatedAttrs.properties), index > 0 ? _marko_compiler.types.numericLiteral(index) : void 0)));
addStatement("effect", section, referencedBindings, translatedAttrs.statements);
} else addHTMLEffectCall(section, referencedBindings);
tag.remove();
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
description: "Use to create side effects.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#lifecycle"
}],
types: runtime_info_default.name + "/tags/lifecycle.d.marko"
};
//#endregion
//#region src/translator/core/log.ts
var log_default = {
analyze(tag) {
const [valueAttr] = tag.node.attributes;
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
if (!valueAttr) throw tag.get("name").buildCodeFrameError("The [`<log>` tag](https://markojs.com/docs/reference/core-tag#log) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
if (tag.node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<log>` tag](https://markojs.com/docs/reference/core-tag#log) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
addSetupExpr(getOrCreateSection(tag), valueAttr.value);
},
translate: { exit(tag) {
const section = getSection(tag);
const [valueAttr] = tag.node.attributes;
const { value } = valueAttr;
const referencedBindings = value.extra?.referencedBindings;
const statement = _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(_marko_compiler.types.identifier("console"), _marko_compiler.types.identifier("log")), [value]));
if (isOutputHTML()) tag.insertBefore(statement);
else addStatement("render", section, referencedBindings, statement);
tag.remove();
} },
parseOptions: { openTagOnly: true },
attributes: {},
autocomplete: [{
description: "Use to log a value to the console.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#log"
}],
types: runtime_info_default.name + "/tags/log.d.marko"
};
//#endregion
//#region src/translator/core/script.ts
var script_default = {
parse(tag) {
const { node } = tag;
const { body } = node.body;
if (body.length) {
let code = "";
for (const child of body) {
if (child.type !== "MarkoText") throw (0, _marko_compiler_babel_utils.getFile)().hub.buildError(child, "Unexpected content in [`<script>` tag](https://markojs.com/docs/reference/core-tag#script). Only javascript and typescript is supported. For a native html [`<script>` tag](https://markojs.com/docs/reference/core-tag#script) use the `html-script` core tag instead.", SyntaxError);
code += child.value;
}
const start = body[0]?.start;
const end = body[body.length - 1]?.end;
const bodyStatements = (0, _marko_compiler_babel_utils.parseStatements)((0, _marko_compiler_babel_utils.getFile)(), code, start, end);
if (bodyStatements.length) {
const valueFn = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement(bodyStatements), !!traverseFindAwait(bodyStatements));
node.attributes.push(_marko_compiler.types.markoAttribute("value", valueFn));
}
node.body.body = [];
}
},
analyze(tag) {
const { node } = tag;
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoBodyContent(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
if (node.var) throw tag.hub.buildError(node.var, "The [`<script>` tag](https://markojs.com/docs/reference/core-tag#script) does not support a tag variable reference. For a native html [`<script>` tag](https://markojs.com/docs/reference/core-tag#script) use the `html-script` core tag instead.");
let seenValueAttr = false;
for (const attr of node.attributes) if (attr.type === "MarkoAttribute" && attr.name === "value") {
if (seenValueAttr) throw tag.hub.buildError(attr, "Invalid duplicate value attribute.");
seenValueAttr = true;
(attr.value.extra ??= {}).isEffect = true;
addSetupExpr(getOrCreateSection(tag), attr.value);
(0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
} else throw tag.hub.buildError(attr, "The [`<script>` tag](https://markojs.com/docs/reference/core-tag#script) does not support html attributes. For a native html [`<script>` tag](https://markojs.com/docs/reference/core-tag#script) use the `html-script` core tag instead.");
if (!seenValueAttr) dropNodes(getAllTagReferenceNodes(node));
},
translate: { exit(tag) {
const { node } = tag;
const [valueAttr] = node.attributes;
if (!valueAttr) {
tag.remove();
return;
}
const section = getSection(tag);
const { value } = valueAttr;
const referencedBindings = value.extra?.referencedBindings;
if ((_marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value)) && _marko_compiler.types.isBlockStatement(value.body) && traverseContains(value.body, isReturnedFunction)) (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The value returned from a [`<script>`](https://markojs.com/docs/reference/core-tag#script) body is discarded, so this cleanup function will never run. Register it with [`$signal.onabort`](https://markojs.com/docs/reference/language#signal) or use [`<lifecycle onDestroy>`](https://markojs.com/docs/reference/core-tag#lifecycle) instead." });
if (isOutputDOM()) {
const isFunction = _marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value);
let inlineBody = null;
if (isFunction) if (value.async || value.generator) {} else if (_marko_compiler.types.isBlockStatement(value.body)) {
if (!traverseContains(value.body, isReturnStatement)) {
let hasDeclaration = false;
for (const child of value.body.body) if (_marko_compiler.types.isDeclaration(child)) {
hasDeclaration = true;
break;
}
inlineBody = hasDeclaration ? value.body : value.body.body;
}
} else inlineBody = _marko_compiler.types.expressionStatement(value.body);
addStatement("effect", section, referencedBindings, inlineBody || _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value, [])));
} else addHTMLEffectCall(section, referencedBindings);
tag.remove();
} },
parseOptions: {
text: true,
preserveWhitespace: true
},
autocomplete: [{
description: "Use to create side effects.",
descriptionMoreURL: "https://markojs.com/docs/core-tags/#script"
}],
types: runtime_info_default.name + "/tags/script.d.marko"
};
function isReturnedFunction(node) {
switch (node.type) {
case "FunctionDeclaration":
case "FunctionExpression":
case "ArrowFunctionExpression":
case "ClassMethod":
case "ObjectMethod":
case "ClassPrivateMethod": return skip;
case "ReturnStatement": return _marko_compiler.types.isFunctionExpression(node.argument) || _marko_compiler.types.isArrowFunctionExpression(node.argument);
default: return false;
}
}
function isReturnStatement(node) {
switch (node.type) {
case "FunctionDeclaration":
case "FunctionExpression":
case "ArrowFunctionExpression":
case "ClassMethod":
case "ObjectMethod":
case "ClassPrivateMethod": return skip;
case "ReturnStatement": return true;
default: return false;
}
}
//#endregion
//#region src/translator/core/server.ts
var server_default = createStatementTag("server");
//#endregion
//#region src/translator/util/insertion-context.ts
const discardsUnknownChildren = /* @__PURE__ */ new Set([
"table",
"thead",
"tbody",
"tfoot",
"tr",
"colgroup",
"select",
"optgroup"
]);
function discardsWrapperChildren(tagName) {
return discardsUnknownChildren.has(tagName);
}
//#endregion
//#region src/translator/core/show.ts
const kStatefulReason = Symbol("<show> stateful reason");
const kStartBinding = Symbol("<show> range start binding");
const kEndBinding = Symbol("<show> range end binding");
const kStaticDisplay = Symbol("<show> static display");
const kSingleNodeBody = Symbol("<show> single node body");
const kDisplayRef = Symbol("<show> hoisted display reference");
var show_default = {
analyze: {
enter(tag) {
assertValidShow(tag);
const tagExtra = tag.node.extra ??= {};
const display = tag.node.attributes[0].value;
const displayEval = evaluate(display);
tagExtra[kSingleNodeBody] = isSingleNodeBody(tag);
if (displayEval.confident) tagExtra[kStaticDisplay] = !!displayEval.computed;
if (tagExtra[kStaticDisplay] === true) return;
assertLegalHiddenContext(tag);
const tagSection = getOrCreateSection(tag);
if (getOnlyChildParentTagName(tag)) getOptimizedOnlyChildNodeBinding(tag, tagSection);
else {
tagExtra[kStartBinding] = createBinding("#text", 0, tagSection);
visit(tag, 37);
enterShallow(tag);
}
if (tagExtra[kStaticDisplay] === void 0) {
mergeReferences(tagSection, tag.node, [display]);
addSerializeExpr(tagSection, tagExtra, kStatefulReason);
} else addSetupStatement(tagSection);
},
exit(tag) {
const tagExtra = tag.node.extra;
if (tagExtra[kStaticDisplay] === true) return;
const tagSection = getSection(tag);
if (tagExtra[kStartBinding]) {
if (!tagExtra[kSingleNodeBody]) {
tagExtra[kEndBinding] = createBinding("#text", 0, tagSection);
visit(tag, 37);
enterShallow(tag);
}
visit(tag, 37);
enterShallow(tag);
}
const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
if (tagExtra[kStaticDisplay] === void 0) addSerializeExpr(tagSection, tagExtra, nodeBinding);
}
},
translate: translateByTarget({
html: {
enter(tag) {
const tagExtra = tag.node.extra;
flushBefore(tag);
const staticDisplay = tagExtra[kStaticDisplay];
if (staticDisplay === true) return;
if (staticDisplay === false) {
writeTo$1(tag)`<t hidden>`;
return;
}
const display = tag.node.attributes[0].value;
if (!_marko_compiler.types.isIdentifier(display)) {
const displayRef = generateUidIdentifier("show");
tag.insertBefore(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(displayRef, display)]));
tagExtra[kDisplayRef] = displayRef;
}
},
exit(tag) {
const tagExtra = tag.node.extra;
const staticDisplay = tagExtra[kStaticDisplay];
if (staticDisplay === false) writeTo$1(tag)`</t>`;
flushInto(tag);
const bodyStatements = tag.node.body.body;
if (staticDisplay !== void 0) {
for (const replacement of tag.replaceWithMultiple(bodyStatements)) replacement.skip();
return;
}
const tagSection = getSection(tag);
const display = tagExtra[kDisplayRef] || tag.node.attributes[0].value;
const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
const onlyChildParentTagName = getOnlyChildParentTagName(tag);
const singleNode = tagExtra[kSingleNodeBody];
const statefulReason = getSerializeReason(tagSection, kStatefulReason);
const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
if (skipParentEnd) getParentTag(tag).node.extra[kSkipEndTag] = true;
const statefulSerializeArg = getSerializeGuard(tagSection, statefulReason, !(skipParentEnd || singleNode));
const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
let startMark;
if (!singleNode) {
startMark = getSerializeGuard(tagSection, markerSerializeReason, false);
if (skipParentEnd) startMark = _marko_compiler.types.logicalExpression("&&", startMark, getSerializeGuard(tagSection, statefulReason, false));
}
for (const replacement of tag.replaceWithMultiple([
_marko_compiler.types.expressionStatement(callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), startMark)),
...bodyStatements,
_marko_compiler.types.expressionStatement(callRuntime("_show_end", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), display, markerSerializeArg, statefulSerializeArg, skipParentEnd ? _marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`) : singleNode ? _marko_compiler.types.numericLiteral(0) : void 0, singleNode ? _marko_compiler.types.numericLiteral(1) : void 0))
])) replacement.skip();
}
},
dom: { exit(tag) {
const tagExtra = tag.node.extra;
if (tagExtra[kStaticDisplay] === true) {
tag.remove();
return;
}
const tagSection = getSection(tag);
const endBinding = tagExtra[kEndBinding];
const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
const startBinding = tagExtra[kStartBinding];
const display = tagExtra[kStaticDisplay] === false ? _marko_compiler.types.booleanLiteral(false) : tag.node.attributes[0].value;
const signal = getSignal(tagSection, nodeBinding, "show");
signal.build = () => {
return callRuntime("_show", getScopeAccessorLiteral(nodeBinding, true), startBinding ? getScopeAccessorLiteral(startBinding, true) : void 0, endBinding ? getScopeAccessorLiteral(endBinding, true) : void 0);
};
addValue(tagSection, tagExtra.referencedBindings, signal, display);
tag.remove();
} }
}),
parseOptions: { controlFlow: true },
autocomplete: [{
snippet: "show=${1:condition}",
description: "Use to render content that is always mounted but only displayed when the condition is met.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#show"
}],
types: runtime_info_default.name + "/tags/show.d.marko"
};
function isSingleNodeBody(tag) {
let elements = 0;
for (const child of tag.get("body").get("body")) {
if (child.isMarkoComment()) continue;
if (child.isMarkoTag() && analyzeTagNameType(child) === 0 && _marko_compiler.types.isStringLiteral(child.node.name)) elements++;
else return false;
}
return elements === 1;
}
function assertValidShow(tag) {
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag, "Write the condition as a value attribute instead: `<show=condition>`.");
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
assertNoSpreadAttrs(tag);
assertHasBody(tag);
assertHasValueAttribute(tag);
}
function assertLegalHiddenContext(tag) {
const parentName = getParentTag(tag)?.node.name;
if (_marko_compiler.types.isStringLiteral(parentName) && discardsWrapperChildren(parentName.value)) throw tag.get("name").buildCodeFrameError(`A [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) cannot be a direct child of \`<${parentName.value}>\`: hidden content is wrapped in an element that \`<${parentName.value}>\` discards, which would render the content instead of hiding it. Move the \`<${getTagName(tag)}>\` inside the row or option, or use [\`<if>\`](https://markojs.com/docs/reference/core-tag#if).`);
}
function assertHasBody(tag) {
if (!tag.node.body.body.length) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires [body content](https://markojs.com/docs/reference/language#tag-content).`);
if (tag.node.body.attributeTags) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) does not support [attribute tags](https://markojs.com/docs/reference/language#attribute-tags).`);
}
function assertHasValueAttribute(tag) {
const { node } = tag;
const [valueAttr] = node.attributes;
if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !(valueAttr.default || valueAttr.name === "value")) {
const wrongName = _marko_compiler.types.isMarkoAttribute(valueAttr) && valueAttr.name;
throw (wrongName ? tag.get("attributes")[0] : tag.get("name")).buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).${wrongName ? ` Use \`<${getTagName(tag)}=condition>\` instead of \`<${getTagName(tag)} ${wrongName}=condition>\`.` : ""}`);
}
if (node.attributes.length > 1) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
}
//#endregion
//#region src/translator/core/static.ts
var static_default = createStatementTag("static");
function checkStyleInterpolations(tag) {
const { body } = tag.node.body;
let stringQuote = "";
let inComment = false;
let groupDepth = 0;
let urlDepth = 0;
let blockDepth = 0;
let valueColon = false;
let runPlaceholder;
let runAfterColon = false;
let runDecl = false;
const endRun = (selector) => {
if (runPlaceholder && (selector || !runAfterColon && runDecl)) throw tag.hub.buildError(runPlaceholder, selector ? styleSelectorMsg : stylePropertyMsg);
valueColon = false;
runPlaceholder = void 0;
};
for (let i = 0; i < body.length; i++) {
const child = body[i];
if (_marko_compiler.types.isMarkoPlaceholder(child)) {
if (stringQuote) throw tag.hub.buildError(child, styleStringMsg);
if (urlDepth) throw tag.hub.buildError(child, styleUrlMsg);
if (!runPlaceholder) {
runPlaceholder = child;
runAfterColon = valueColon;
runDecl = blockDepth > 0;
}
const prev = body[i - 1];
if (_marko_compiler.types.isMarkoText(prev) && cssGluedBefore.test(prev.value)) throw tag.hub.buildError(child, styleGluedBeforeMsg);
const next = body[i + 1];
if (_marko_compiler.types.isMarkoText(next) && cssGluedValue.test(next.value)) throw tag.hub.buildError(child, styleGluedMsg);
continue;
}
const text = child.value;
for (let j = 0; j < text.length; j++) {
const c = text[j];
if (inComment) {
if (c === "*" && text[j + 1] === "/") {
inComment = false;
j++;
}
} else if (stringQuote) {
if (c === "\\") j++;
else if (c === stringQuote) stringQuote = "";
} else if (c === "\\") j++;
else if (c === "/" && text[j + 1] === "*") {
inComment = true;
j++;
} else if (c === "\"" || c === "'") stringQuote = c;
else if (c === "(" || c === "[") {
groupDepth++;
if (!urlDepth && cssUrlBefore.test(text.slice(0, j + 1)) && !cssQuotedArg.test(text.slice(j + 1))) urlDepth = groupDepth;
} else if (c === ")" || c === "]") {
if (groupDepth) {
if (urlDepth === groupDepth) urlDepth = 0;
groupDepth--;
}
} else if (!groupDepth) switch (c) {
case ":":
if (blockDepth) valueColon = true;
break;
case "{":
endRun(true);
blockDepth++;
break;
case ";":
endRun(!blockDepth);
break;
case "}":
endRun(false);
if (blockDepth) blockDepth--;
break;
}
}
}
endRun(!blockDepth);
}
const styleInterpolationMsg = "A `${...}` interpolation in a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) is substituted as a `var(--…)` custom property reference, which";
const styleSelectorMsg = `${styleInterpolationMsg} only resolves in a declaration value, not in a selector or at-rule prelude. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
const stylePropertyMsg = `${styleInterpolationMsg} cannot be used as a property name. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
const styleStringMsg = `${styleInterpolationMsg} is not substituted inside a quoted CSS string — the literal text \`var(--…)\` would be rendered instead of the value. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
const styleUrlMsg = `${styleInterpolationMsg} is not substituted inside an unquoted \`url()\` — the raw url token consumes the \`var(--…)\` text literally, invalidating the declaration. Move the whole \`url(...)\` into the interpolated value. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
const styleGluedMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so a unit written directly after it (eg \`\${x}px\`) becomes the invalid \`var(--…)px\`. Move the unit into the interpolated value (so it resolves to eg \`"10px"\`) or use \`calc(var(--…) * 1px)\`.`;
const styleGluedBeforeMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so text written directly before it (eg \`10\${x}\`) merges with the \`var(--…)\` into a single invalid token. Add whitespace before the interpolation or move the text into the interpolated value.`;
const cssGluedValue = /^(?:[%.\d]|(?:p[xtc]|in|[cm]m|q|r?em|ex|ch|r?lh|v[whib]|vmin|vmax|fr|deg|g?rad|turn|m?s|k?hz|dp(?:i|cm|px)|cq[whib]|cqmin|cqmax)(?![\w-]))/i;
const cssGluedBefore = /[\w%]$/;
const cssUrlBefore = /(?:^|[^\w-])url\($/i;
const cssQuotedArg = /^\s*["']/;
//#endregion
//#region src/translator/core/style.ts
const STYLE_EXT_REG = /^style((?:\.[a-zA-Z0-9$_-]+)+)?/;
const programStyleCounts = /* @__PURE__ */ new WeakMap();
const programDynamicStyleNameCounts = /* @__PURE__ */ new WeakMap();
var style_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
(0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
const { node } = tag;
assertNoStyleAttributes(tag);
const names = collectDynamicStyleNames(tag);
if (names) {
checkStyleInterpolations(tag);
checkDynamicStylePlacement(tag);
}
const importPath = getStyleImportPath((0, _marko_compiler_babel_utils.getFile)(), node, names);
(node.extra ??= {}).styleImportPath = importPath;
if (importPath) addAssetImport(importPath);
if (names) {
analyzeDynamicStyle(tag, names);
addSetupStatement(getOrCreateSection(tag));
visit(tag, 32);
writeTo(tag)`<style></style>`;
}
},
translate: translateByTarget({
html: { exit: translateHTML$1 },
dom: { exit: translateDOM$1 }
}),
parseOptions: {
html: false,
text: true,
rawOpenTag: true,
preserveWhitespace: true
},
attributes: {}
};
function analyzeDynamicStyle(tag, names) {
const { node } = tag;
const section = getOrCreateSection(tag);
const binding = createBinding("#style", 0, section);
node.extra.dynamicStyle = {
names,
binding
};
let exprExtras = mergeReferences(section, node, []);
for (const value of dynamicStyleValues(node)) exprExtras = push(exprExtras, value.extra ??= {});
addSerializeExpr(section, exprExtras, binding);
}
function collectDynamicStyleNames(tag) {
let names;
for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) {
const program = (0, _marko_compiler_babel_utils.getProgram)().node;
const index = programDynamicStyleNameCounts.get(program) ?? 0;
programDynamicStyleNameCounts.set(program, index + 1);
(names ??= []).push(dynamicStyleName(index));
} else if (!_marko_compiler.types.isMarkoText(child)) throw tag.hub.buildError(child, "The [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only supports text and `${...}` interpolations. For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.");
return names;
}
const styleNameUnsafeReg = /[^a-zA-Z0-9_]/g;
const encodeStyleNameChar = (c) => "-" + c.charCodeAt(0).toString(36);
function dynamicStyleName(index) {
const file = (0, _marko_compiler_babel_utils.getFile)();
const id = (0, _marko_compiler_babel_utils.getTemplateId)(file.markoOpts, file.opts.filename, index.toString(36));
return "--" + ((file.markoOpts.runtimeId || "M_") + id).replace(styleNameUnsafeReg, encodeStyleNameChar);
}
function checkDynamicStylePlacement(tag) {
for (const sibling of tag.getAllPrevSiblings()) {
if (isCoreTagName(sibling, "style")) continue;
if (sibling.isMarkoText() ? /\S/.test(sibling.node.value) : getNodeContentType(sibling, "startType") !== null) {
(0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The `${...}` values of a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only apply to the subsequent siblings of the `<style>` tag and their descendants, so the content before this tag will not receive them. Move the `<style>` tag above the content it styles." });
return;
}
}
}
function assertNoStyleAttributes(tag) {
const { node } = tag;
const extClass = (STYLE_EXT_REG.exec(node.rawValue || "")?.[1]?.slice(1))?.replace(/\./g, " ");
for (const attr of node.attributes) {
if (attr.start == null && attr.type === "MarkoAttribute" && attr.name === "class" && attr.value.type === "StringLiteral" && attr.value.value === extClass) continue;
throw tag.hub.buildError(attr.value, "The `style` does not support html attributes. For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.");
}
}
function translateHTML$1(tag) {
const { node } = tag;
const dynamic = node.extra?.dynamicStyle;
if (dynamic) {
const { binding } = dynamic;
const section = getSection(tag);
writeTo$1(tag)`${callRuntime("_style_html", buildStyleDecls(node))}`;
markNode(tag, binding, getSerializeReason(section, binding));
}
emitStyleImport(tag);
tag.remove();
}
function translateDOM$1(tag) {
const { node } = tag;
const dynamic = node.extra?.dynamicStyle;
if (dynamic) {
const { names, binding } = dynamic;
const section = getSection(tag);
const readEl = () => createScopeReadExpression(binding);
addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(callRuntime("_style_shell", scopeIdentifier, getScopeAccessorLiteral(binding))), true);
dynamicStyleValues(node).forEach((value, i) => {
const valueRef = value.extra?.referencedBindings;
addStatement("render", section, valueRef, _marko_compiler.types.expressionStatement(callRuntime("_style_rule_item", readEl(), _marko_compiler.types.stringLiteral(names[i]), value)), !valueRef);
});
}
emitStyleImport(tag);
tag.remove();
}
function dynamicStyleValues(node) {
const values = [];
for (const child of node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) values.push(child.value);
return values;
}
function emitStyleImport(tag) {
const { node } = tag;
const importPath = node.extra?.styleImportPath;
if (!importPath) return;
if (!node.var) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(importPath)));
else if (_marko_compiler.types.isIdentifier(node.var)) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([_marko_compiler.types.importNamespaceSpecifier(node.var)], _marko_compiler.types.stringLiteral(importPath)));
else {
const varDecl = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, (0, _marko_compiler_babel_utils.importStar)((0, _marko_compiler_babel_utils.getFile)(), importPath, "style"))]);
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(isOutputDOM() ? varDecl : _marko_compiler.types.markoScriptlet([varDecl], true));
}
}
function buildStyleDecls(node) {
const { names } = node.extra.dynamicStyle;
const parts = [];
dynamicStyleValues(node).forEach((value, i) => {
parts.push(`${names[i]}:`);
parts.push(callRuntime("_escape_style_value", value));
parts.push(";");
});
return normalizeStringExpression(parts);
}
/**
* Resolves a `<style>` block's text to its client-side import path by handing
* the css to the configured `resolveVirtualDependency` hook.
*/
function getStyleImportPath(file, node, names) {
const { resolveVirtualDependency, sourceMaps } = file.markoOpts;
if (!resolveVirtualDependency) return;
const { filename } = file.opts;
let ext = STYLE_EXT_REG.exec(node.rawValue || "")?.[1] || ".css";
if (node.var && !/\.module\./.test(ext)) ext = ".module" + ext;
const program = (0, _marko_compiler_babel_utils.getProgram)().node;
let counts = programStyleCounts.get(program);
if (!counts) programStyleCounts.set(program, counts = {});
const index = counts[ext] || 0;
counts[ext] = index + 1;
const magicString = sourceMaps ? new magic_string.default(file.code, { filename }) : void 0;
let code = "";
let last = 0;
let map;
let nameIndex = 0;
for (const child of node.body.body) {
const placeholder = _marko_compiler.types.isMarkoPlaceholder(child);
const text = placeholder ? `var(${names[nameIndex++]})` : child.value;
if (magicString) {
const start = (0, _marko_compiler_babel_utils.getStart)(file, child);
if (start === null) magicString.appendLeft(last, text);
else {
const end = (0, _marko_compiler_babel_utils.getEnd)(file, child);
if (start > last) magicString.remove(last, start);
if (placeholder) magicString.update(start, end, text);
last = end;
}
} else code += text;
}
if (magicString) {
if (file.code.length > last) magicString.remove(last, file.code.length);
code = magicString.toString();
map = magicString.generateMap({
source: filename,
includeContent: true
});
if (sourceMaps === "inline" || sourceMaps === "both") {
code += `\n/*# sourceMappingURL=${map.toUrl()}*/`;
if (sourceMaps === "inline") map = void 0;
}
}
return resolveVirtualDependency(filename, {
virtualPath: `./${path.default.basename(filename)}${index ? `.${index}` : ""}${ext}`,
code,
map
});
}
//#endregion
//#region src/translator/core/try.ts
const kDOMBinding$1 = Symbol("try tag dom binding");
var try_default = {
analyze(tag) {
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
(0, _marko_compiler_babel_utils.assertNoParams)(tag);
(0, _marko_compiler_babel_utils.assertNoAttributes)(tag);
const attrTags = analyzeAttributeTags(tag);
if (attrTags) {
for (const name in attrTags) if (name !== "@placeholder" && name !== "@catch") {
const suggestion = name[1] === "p" ? "`<@placeholder>`" : "`<@catch>`";
throw tag.buildCodeFrameError(`The [\`<try>\` tag](https://markojs.com/docs/reference/core-tag#try) only supports the \`<@placeholder>\` and \`<@catch>\` attribute tags, but received \`<${name}>\`. Did you mean ${suggestion}?`);
}
}
const section = getOrCreateSection(tag);
const tagExtra = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
tagExtra[kDOMBinding$1] = createBinding("#text", 0, section);
if (!tag.node.body.body.length) throw tag.get("name").buildCodeFrameError("The [`<try>` tag](https://markojs.com/docs/reference/core-tag#try) requires [body content](https://markojs.com/docs/reference/language#tag-content).");
const bodySection = startSection(tag.get("body"));
if (bodySection) {
bodySection.upstreamExpression = tagExtra;
visit(tag, 37);
enterShallow(tag);
}
},
translate: translateByTarget({
html: {
enter(tag) {
const bodySection = getSectionForBody(tag.get("body"));
if (!bodySection) {
tag.remove();
return;
}
if (tag.node.extra?.attributeTags?.["@placeholder"]) setTryHasPlaceholder(bodySection, true);
setSectionParentIsOwner(bodySection, true);
flushBefore(tag);
},
exit(tag) {
const { node } = tag;
const section = getSection(tag);
const tagExtra = node.extra;
const tagBody = tag.get("body");
const translatedAttrs = translateAttrs(tag);
const nodeRef = tagExtra[kDOMBinding$1];
const contentProp = getTranslatedBodyContentProperty(translatedAttrs.properties);
if (contentProp) translatedAttrs.properties.splice(translatedAttrs.properties.indexOf(contentProp), 1);
flushInto(tag);
writeHTMLResumeStatements(tagBody);
tag.insertBefore(translatedAttrs.statements);
tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_try", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeRef), contentProp?.value, propsToExpression(translatedAttrs.properties))))[0].skip();
}
},
dom: {
enter(tag) {
const bodySection = getSectionForBody(tag.get("body"));
if (tag.node.extra?.attributeTags?.["@placeholder"]) setTryHasPlaceholder(bodySection, true);
setSectionParentIsOwner(bodySection, true);
},
exit(tag) {
const { node } = tag;
const tagExtra = node.extra;
const nodeRef = tagExtra[kDOMBinding$1];
const referencedBindings = tagExtra.referencedBindings;
const translatedAttrs = translateAttrs(tag);
const contentProp = getTranslatedBodyContentProperty(translatedAttrs.properties);
if (contentProp) translatedAttrs.properties.splice(translatedAttrs.properties.indexOf(contentProp), 1);
const section = getSection(tag);
const bodySection = getSectionForBody(tag.get("body"));
const signal = getSignal(section, nodeRef, "try");
const hasPlaceholder = !!tag.node.extra?.attributeTags?.["@placeholder"];
signal.build = () => {
importRuntimeFeature("catch");
if (hasPlaceholder) importRuntimeFeature("placeholder");
return callRuntime("_try", getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
};
if (translatedAttrs.statements.length) addStatement("render", section, referencedBindings, translatedAttrs.statements);
addValue(section, referencedBindings, signal, propsToExpression(translatedAttrs.properties));
tag.remove();
}
}
}),
attributes: {},
autocomplete: [{
description: "Used to capture errors and display placeholders for nested content.",
descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#try"
}],
types: runtime_info_default.name + "/tags/try.d.marko"
};
//#endregion
//#region src/translator/core/index.ts
var core_default = {
taglibId: runtime_info_default.taglibId,
"<attrs>": attrs_default,
"<await>": await_default,
"<class>": class_default,
"<client>": client_default,
"<const>": const_default,
"<debug>": debug_default,
"<define>": define_default,
"<effect>": effect_default,
"<else-if>": ElseIfTag,
"<else>": ElseTag,
"<export>": export_default,
"<for>": for_default,
"<html-comment>": html_comment_default,
"<html-script>": html_script_default,
"<html-style>": html_style_default,
"<id>": id_default,
"<if>": IfTag,
"<import>": import_default,
"<let>": let_default,
"<lifecycle>": lifecycle_default,
"<log>": log_default,
"<return>": return_default,
"<script>": script_default,
"<server>": server_default,
"<show>": show_default,
"<static>": static_default,
"<style>": style_default,
"<try>": try_default
};
//#endregion
//#region src/translator/visitors/cdata.ts
var cdata_default = { translate: { enter(cdata) {
throw cdata.buildCodeFrameError("CDATA sections are not supported in Marko.");
} } };
//#endregion
//#region src/translator/visitors/comment.ts
var comment_default = { translate: { exit(comment) {
comment.remove();
} } };
//#endregion
//#region src/translator/visitors/declaration.ts
var declaration_default = { translate: { enter(decl) {
throw decl.buildCodeFrameError("XML declarations sections are not supported in Marko.");
} } };
//#endregion
//#region src/translator/visitors/document-type.ts
var document_type_default = { translate: { exit(documentType) {
if (isOutputHTML()) {
writeTo$1(documentType)`<!${documentType.node.value}>`;
if (getMarkoOpts().linkAssets && !isBeforeHtmlOrHead(documentType)) writeTo$1(documentType)`${callRuntime("_flush_head")}`;
}
documentType.remove();
} } };
function isBeforeHtmlOrHead(documentType) {
let next = documentType.getNextSibling();
while (next.node) {
if (next.isMarkoTag()) {
const { name } = next.node;
return name.type === "StringLiteral" && (name.value === "html" || name.value === "head");
}
next = next.getNextSibling();
}
return false;
}
//#endregion
//#region src/translator/visitors/export-declaration.ts
var export_declaration_default = {
analyze(exportDecl) {
const { node } = exportDecl;
const { source } = node;
if (source) {
const tagImport = (0, _marko_compiler_babel_utils.resolveTagImport)(exportDecl, source.value);
if (tagImport) {
(node.extra ??= {}).tagImport = tagImport;
const tags = (0, _marko_compiler_babel_utils.getFile)().metadata.marko.tags;
if (!tags.includes(tagImport)) tags.push(tagImport);
}
}
},
translate: { exit(exportDecl) {
const { node } = exportDecl;
const tagImport = node.extra?.tagImport;
if (tagImport) node.source.value = tagImport;
} }
};
//#endregion
//#region src/translator/visitors/import-declaration.ts
const triggerRegExp = /\s*([\w-]+)\s*([^?|]+?)?\s*(?:\?([^|]*?))?\s*(?:\||$)/g;
const [getHtmlLoadWrapped] = createProgramState(() => /* @__PURE__ */ new Map());
var import_declaration_default = {
analyze(importDecl) {
const { node } = importDecl;
const { source } = node;
const { value } = source;
if (_marko_compiler.types.isProgram(importDecl.parent) && isClientAssetImport((0, _marko_compiler_babel_utils.getFile)(), value)) addAssetImport(value);
const tagImport = (0, _marko_compiler_babel_utils.resolveTagImport)(importDecl, value);
if (tagImport) {
(node.extra ??= {}).tagImport = tagImport;
const tags = (0, _marko_compiler_babel_utils.getFile)().metadata.marko.tags;
if (!tags.includes(tagImport)) tags.push(tagImport);
trackImportedRegisteredFns(importDecl);
}
const loadAttrPath = node.attributes?.length ? importDecl.get("attributes").find((p) => (p.node.key.type === "Identifier" ? p.node.key.name : p.node.key.value) === "load") : void 0;
if (loadAttrPath) {
const loadImport = getLoadImportConfig(loadAttrPath.get("value"));
if ((node.importKind || "value") !== "value") throw importDecl.buildCodeFrameError("Invalid load import.");
for (const specifier of importDecl.get("specifiers")) if (!_marko_compiler.types.isImportDefaultSpecifier(specifier.node)) throw specifier.buildCodeFrameError("Invalid load import, only a default specifier is allowed.");
if (!node.specifiers.some(_marko_compiler.types.isImportDefaultSpecifier)) throw importDecl.buildCodeFrameError("Invalid load import, a default specifier is required.");
if (!getMarkoOpts().linkAssets) {
loadAttrPath.remove();
return;
}
(node.extra ??= {}).loadImport = loadImport;
const file = (0, _marko_compiler_babel_utils.getFile)();
const loadFile = tagImport && (0, _marko_compiler_babel_utils.loadFileForImport)(file, value);
if (!loadFile) throw importDecl.buildCodeFrameError("Unable to resolve marko file for load import.");
(file.path.node.extra.loadImports ??= /* @__PURE__ */ new Set()).add(loadFile.opts.filename);
if (loadFile.ast.program.extra?.featureType === "class") throw importDecl.buildCodeFrameError(`The [\`load\` import attribute](https://markojs.com/docs/reference/lazy-loading) is not supported for the Marko 5 (class API) tag \`${value}\`. Import it without \`load\`, or migrate the tag to the tags API.`);
}
},
translate: { exit(importDecl) {
const { node } = importDecl;
const { extra } = node;
const tagImport = extra?.tagImport;
const loadImport = extra?.loadImport;
if (tagImport) {
if (loadImport) {
const { local } = node.specifiers.find(_marko_compiler.types.isImportDefaultSpecifier);
const binding = importDecl.scope.getBinding(local.name);
if (isOutputHTML()) {
const loadFile = (0, _marko_compiler_babel_utils.loadFileForImport)((0, _marko_compiler_babel_utils.getFile)(), node.source.value);
const wrappedName = getOrCreateHtmlLoadWrapped(getReadyId(loadFile), _marko_compiler.types.identifier(local.name), loadFile.opts.filename, loadImport.render ? void 0 : loadImport.triggers);
for (const ref of binding.referencePaths) ref.replaceWith(_marko_compiler.types.identifier(wrappedName));
node.source.value = tagImport;
node.attributes = void 0;
return;
} else if (binding.referencePaths.every((ref) => _marko_compiler.types.isMarkoTag(ref.parent) && ref.parent.extra?.tagNameLoad)) importDecl.remove();
else {
const file = (0, _marko_compiler_babel_utils.getFile)();
const loadFile = (0, _marko_compiler_babel_utils.loadFileForImport)(file, node.source.value);
const resolvedPath = (0, _marko_compiler_babel_utils.resolveRelativePath)(file, loadFile.opts.filename);
importRuntimeFeature("catch");
importDecl.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(local, callRuntime("_load_template", _marko_compiler.types.stringLiteral(loadFile.metadata.marko.id), _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(_marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral(resolvedPath)]), _marko_compiler.types.identifier("then")), [_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier("mod")], toMemberExpression(_marko_compiler.types.identifier("mod"), "default"))]))))]));
}
return;
}
node.source.value = tagImport;
}
} }
};
function getOrCreateHtmlLoadWrapped(readyId, originalIdentifier, filename, triggers) {
const markoOpts = getMarkoOpts();
const loadWrapped = getHtmlLoadWrapped();
const existing = loadWrapped.get(readyId);
if (existing) return existing;
markoOpts.linkAssets?.onAsset("load", filename, readyId);
const wrappedName = generateUid(`${originalIdentifier.name ?? "tag"}_withLoadAssets`);
loadWrapped.set(readyId, wrappedName);
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(wrappedName), callRuntime("withLoadAssets", originalIdentifier, _marko_compiler.types.stringLiteral(readyId), triggers ? _marko_compiler.types.valueToNode(triggers) : void 0))])], true));
return wrappedName;
}
function trackImportedRegisteredFns(importDecl) {
const { node } = importDecl;
const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)((0, _marko_compiler_babel_utils.getFile)(), node.source.value);
if (!childFile) return;
for (const specifier of importDecl.get("specifiers")) {
if (!specifier.isImportSpecifier()) continue;
const { imported } = specifier.node;
const importedName = imported.type === "Identifier" ? imported.name : imported.value;
if (importedName === "default") continue;
const resolved = resolveRegisteredExport(childFile, importedName);
if (resolved) trackImportedFn(importDecl, specifier.node.local.name, resolved);
}
}
function getLoadImportConfig(attrValue) {
const raw = attrValue.node.value;
if (raw === "render") return { render: true };
const triggers = [];
for (const match of raw.matchAll(triggerRegExp)) {
const type = parseTriggerType(match[1]);
const selector = match[2];
const query = match[3];
if (!type) throw attrValue.buildCodeFrameError(`Unknown trigger type "${match[1]}". Supported triggers are "visible", "idle", "media", and "on*".`);
if (type === "render") throw attrValue.buildCodeFrameError("The \"render\" trigger must be used alone.");
if (type === "idle") {
if (selector) throw attrValue.buildCodeFrameError(`Selector is not supported for the "idle" trigger.`);
} else if (!selector) throw attrValue.buildCodeFrameError(type === "media" ? `A media query is required for the "media" trigger. (e.g. "media(max-width:768px)")` : `A selector is required for the "${type}" trigger. (e.g. "${type}.my-element")`);
const trigger = selector ? {
type,
selector
} : { type };
if (query) {
const params = new URLSearchParams(query);
switch (type) {
case "visible": {
let rootMargin;
for (const [key, value] of params) {
if (key !== "rootMargin") throw attrValue.buildCodeFrameError(`Unknown param "${key}" for the "visible" trigger. Supported params: "rootMargin".`);
rootMargin = value;
}
if (rootMargin) trigger.options = { rootMargin };
break;
}
case "idle": {
let timeout;
for (const [key, value] of params) {
if (key !== "timeout") throw attrValue.buildCodeFrameError(`Unknown param "${key}" for the "idle" trigger. Supported params: "timeout".`);
timeout = Number(value);
}
if (timeout) trigger.options = { timeout };
break;
}
default: throw attrValue.buildCodeFrameError(`Params are not supported for the "${type}" trigger.`);
}
}
triggers.push(trigger);
}
if (!triggers.length) throw attrValue.buildCodeFrameError("The \"load\" attribute requires \"render\" or at least one trigger (e.g. \"visible.my-element\").");
return {
render: false,
triggers
};
}
function parseTriggerType(type) {
switch (type) {
case "idle":
case "media":
case "render":
case "visible": return type;
default: return isEventHandler(type) ? `on-${getEventHandlerName(type)}` : void 0;
}
}
//#endregion
//#region src/translator/util/static-text.ts
function isStaticText(node) {
switch (node?.type) {
case "MarkoText": return true;
case "MarkoPlaceholder":
if (node.escape) {
const { confident, computed } = evaluate(node.value);
return confident && getHTMLRuntime()._escape(computed) !== "";
}
return false;
}
}
function getPrevStaticSibling(path) {
let prev = path.getPrevSibling();
while (prev.node && (getNodeContentType(prev, "endType") === null || prev.isMarkoPlaceholder() && isEmptyPlaceholder(prev.node))) prev = prev.getPrevSibling();
return prev.node;
}
function isEmptyPlaceholder(placeholder) {
const { confident, computed } = evaluate(placeholder.value);
return confident && getHTMLRuntime()[placeholder.escape ? "_escape" : "_unescaped"](computed) === "";
}
//#endregion
//#region src/translator/visitors/placeholder.ts
const kNodeBinding = Symbol("placeholder node binding");
const kSiblingText = Symbol("placeholder has sibling text");
var placeholder_default = {
analyze: {
enter(placeholder) {
if (isNonHTMLText(placeholder)) return;
const { node } = placeholder;
const valueExtra = evaluate(node.value);
const { confident, computed } = valueExtra;
if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") return;
if (!isStaticText(node)) {
const section = getOrCreateSection(placeholder);
const nodeBinding = (node.extra ??= {})[kNodeBinding] = createBinding("#text", 0, section);
analyzeSiblingText(placeholder);
addSetupExpr(section, node.value);
addSerializeExpr(section, valueExtra, nodeBinding);
}
},
exit(placeholder) {
if (isNonHTMLText(placeholder)) return;
const { node } = placeholder;
const { confident, computed } = evaluate(node.value);
const staticText = confident ? getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) : void 0;
if (staticText === "") return;
const extra = node.extra || {};
if (confident && node.escape) writeTextTo(placeholder, staticText);
else {
const siblingText = extra[kSiblingText];
if (siblingText === 1 || siblingText === 2) visit(placeholder, 37);
else {
writeTextTo(placeholder, " ");
visit(placeholder, 32);
}
}
if (!isStaticText(node) || !isStaticText(getPrevStaticSibling(placeholder))) enterShallow(placeholder);
}
},
translate: { exit(placeholder) {
translateExit(placeholder);
} }
};
function translateExit(placeholder) {
if (isNonHTMLText(placeholder)) return;
const { node } = placeholder;
const { value } = node;
if (node.extra?.[kRawText]) injectTextCoercion(value);
const valueExtra = evaluate(value);
const { confident, computed } = valueExtra;
if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") {
placeholder.remove();
return;
}
const isHTML = isOutputHTML();
const write = writeTo$1(placeholder);
const extra = node.extra || {};
const nodeBinding = extra[kNodeBinding];
const canWriteHTML = isHTML || confident && node.escape;
const method = canWriteHTML ? node.escape ? "_escape" : "_unescaped" : node.escape ? "_text" : "_html";
if (confident && canWriteHTML) {
if (isHTML) write`${getHTMLRuntime()[method](computed)}`;
} else {
const section = getSection(placeholder);
const siblingText = extra[kSiblingText];
const markerSerializeReason = nodeBinding && getSerializeReason(section, nodeBinding);
if (isHTML) if (markerSerializeReason) {
const guard = getSerializeGuard(section, markerSerializeReason, true);
write`${callRuntime(node.escape ? "_text_resume" : "_html_resume", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeBinding), value, siblingText === 1 ? guard ? _marko_compiler.types.binaryExpression("*", guard, _marko_compiler.types.numericLiteral(2)) : _marko_compiler.types.numericLiteral(2) : guard)}`;
} else write`${method === "_escape" ? buildEscapedTextExpression(value) : callRuntime(method, value)}`;
else addStatement("render", section, valueExtra.referencedBindings, _marko_compiler.types.expressionStatement(method === "_text" ? callRuntime("_text", createScopeReadExpression(nodeBinding), value) : callRuntime("_html", scopeIdentifier, value, getScopeAccessorLiteral(nodeBinding))), true);
}
placeholder.remove();
}
function buildEscapedTextExpression(value) {
const { _escape } = getHTMLRuntime();
switch (value.type) {
case "StringLiteral":
case "NumericLiteral":
case "BooleanLiteral": return _marko_compiler.types.stringLiteral(_escape(value.value));
case "NullLiteral": return _marko_compiler.types.stringLiteral("");
case "ConditionalExpression": return _marko_compiler.types.conditionalExpression(value.test, buildEscapedTextExpression(value.consequent), buildEscapedTextExpression(value.alternate));
case "TemplateLiteral": {
const parts = [];
value.quasis.forEach((quasi, i) => {
parts.push(_escape(quasi.value.cooked ?? ""));
const expression = value.expressions[i];
if (expression) parts.push(callRuntime("_escape", _marko_compiler.types.templateLiteral([_marko_compiler.types.templateElement({ raw: "" }), _marko_compiler.types.templateElement({ raw: "" }, true)], [expression])));
});
return normalizeStringExpression(parts) ?? _marko_compiler.types.stringLiteral("");
}
default: return callRuntime("_escape", value);
}
}
function analyzeSiblingText(placeholder) {
const placeholderExtra = placeholder.node.extra;
let prev = placeholder.getPrevSibling();
let prevParent = placeholder.parentPath;
for (;;) {
if (!prev.node) {
const showTag = getInlinedBodyTag(prevParent);
if (showTag) {
prev = showTag.getPrevSibling();
prevParent = showTag.parentPath;
continue;
}
break;
}
const contentType = getNodeContentType(prev, "endType");
if (contentType === null) prev = prev.getPrevSibling();
else if (contentType === 4 || contentType === 1 || contentType === 2) return placeholderExtra[kSiblingText] = 1;
else break;
}
if (!prev.node && prevParent.isProgram()) return placeholderExtra[kSiblingText] = 1;
let next = placeholder.getNextSibling();
let nextParent = placeholder.parentPath;
for (;;) {
if (!next.node) {
const showTag = getInlinedBodyTag(nextParent);
if (showTag) {
next = showTag.getNextSibling();
nextParent = showTag.parentPath;
continue;
}
break;
}
const contentType = getNodeContentType(next, "startType");
if (contentType === null) next = next.getNextSibling();
else if (contentType === 4 || contentType === 1 || contentType === 2) return placeholderExtra[kSiblingText] = 2;
else break;
}
if (!next.node && nextParent.isProgram()) return placeholderExtra[kSiblingText] = 2;
return placeholderExtra[kSiblingText] = 0;
}
function getInlinedBodyTag(parent) {
if (parent.isMarkoTagBody()) {
const tag = parent.parentPath;
if (tag.isMarkoTag() && isCoreTagName(tag, "show")) return tag;
}
}
//#endregion
//#region src/translator/visitors/referenced-identifier.ts
const [getAbortResetEmitted] = createSectionState("abortResetEmitted", () => /* @__PURE__ */ new Set());
var referenced_identifier_default = {
migrate(identifier) {
const { name } = identifier.node;
if (identifier.scope.hasBinding(name)) return;
switch (name) {
case "out":
if (_marko_compiler.types.isMemberExpression(identifier.parent) && _marko_compiler.types.isIdentifier(identifier.parent.property) && identifier.parent.property.name === "global") identifier.parentPath.replaceWith(_marko_compiler.types.identifier("$global"));
else throw identifier.buildCodeFrameError("Only `out.global` is supported for compatibility.");
break;
}
},
analyze(identifier) {
const { name } = identifier.node;
if (identifier.scope.hasBinding(name)) return;
if (name === "$global") {
setReferencesScope(identifier);
trackGlobalReference(identifier);
} else if (name === "$signal") {
const section = getOrCreateSection(identifier);
section.hasAbortSignal = true;
setReferencesScope(identifier);
const exprRoot = getExprRoot(identifier);
const rootExtra = exprRoot.node.extra ??= { section };
if (rootExtra.abortId === void 0) rootExtra.abortId = section.abortSignalExprs++;
}
},
translate(identifier) {
const { name } = identifier.node;
if (identifier.scope.hasBinding(name)) return;
switch (name) {
case "$global": {
if (isOutputHTML()) break;
const globalRead = _marko_compiler.types.memberExpression(scopeIdentifier, _marko_compiler.types.identifier(getAccessorProp().Global));
const key = !isOptimize() && getSignalGlobalKey(identifier);
if (key) identifier.parentPath.replaceWith(callRuntime("_global_read", globalRead, _marko_compiler.types.stringLiteral(key)));
else identifier.replaceWith(globalRead);
break;
}
case "$signal": if (isOutputHTML()) identifier.replaceWith(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([_marko_compiler.types.throwStatement(_marko_compiler.types.newExpression(_marko_compiler.types.identifier("Error"), [_marko_compiler.types.stringLiteral("Cannot use $signal in a server render.")]))])), []));
else {
const section = getSection(identifier);
const exprRoot = getExprRoot(identifier);
const exprId = exprRoot.node.extra.abortId;
const resetEmitted = getAbortResetEmitted(section);
if (!resetEmitted.has(exprRoot)) {
resetEmitted.add(exprRoot);
addStatement("render", section, exprRoot.node.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])));
}
identifier.replaceWith(_marko_compiler.types.callExpression(importRuntime("$signal"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)]));
}
}
}
};
function getSignalGlobalKey(identifier) {
const { parent } = identifier;
if (!_marko_compiler.types.isMemberExpression(parent) || parent.computed || !_marko_compiler.types.isIdentifier(parent.property) || parent.object !== identifier.node) return;
const { name } = parent.property;
if (name === "runtimeId" || name === "renderId") return;
return getExprRoot(identifier).node.extra?.referencedBindings ? name : void 0;
}
//#endregion
//#region src/translator/visitors/scriptlet.ts
var scriptlet_default = {
analyze(scriptlet) {
if (!scriptlet.node.static) {
reportAnalyzeError(scriptlet, scriptlet.buildCodeFrameError("Scriptlets are not supported when using the tags api."));
scriptlet.skip();
return;
}
mergeReferences(getOrCreateSection(scriptlet), scriptlet.node, scriptlet.node.body);
if (scriptlet.node.target === "client") (0, _marko_compiler_babel_utils.getProgram)().node.extra.hasClientStatement = true;
},
translate: { exit(scriptlet) {
const { node } = scriptlet;
const isHTML = isOutputHTML();
if (node.target && node.target !== (isHTML ? "server" : "client")) {
const ids = Object.keys(scriptlet.getOuterBindingIdentifiers());
const decl = ids.length && _marko_compiler.types.variableDeclaration("var", ids.map((key) => _marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(key))));
if (decl) if (isHTML) {
scriptlet.node.target = null;
scriptlet.node.body = [decl];
} else scriptlet.replaceWith(decl);
else scriptlet.remove();
return;
}
if (isHTML) {} else {
traverseReplace(node, "body", replaceRegisteredFunctionNode$1);
scriptlet.replaceWithMultiple(node.body);
}
} }
};
//#endregion
//#region src/translator/visitors/tag/attribute-tag.ts
var attribute_tag_default = {
analyze: { enter(tag) {
(0, _marko_compiler_babel_utils.assertNoVar)(tag);
(0, _marko_compiler_babel_utils.assertNoArgs)(tag);
const body = tag.get("body");
startSection(body);
trackParamsReferences(body, 3);
if (!(0, _marko_compiler_babel_utils.findParentTag)(tag)) throw tag.get("name").buildCodeFrameError("[Attribute tags](https://markojs.com/docs/reference/language#attribute-tags) must be nested within another tag.");
} },
translate: {
enter(tag) {
if (isOutputHTML()) flushBefore(tag);
},
exit(tag) {
if (isOutputHTML()) {
flushInto(tag);
writeHTMLResumeStatements(tag.get("body"));
}
}
}
};
//#endregion
//#region src/translator/visitors/tag/custom-tag.ts
const kLoadTagBinding = Symbol("load tag binding");
const [getLoadIdentifiers] = createProgramState(() => ({
triggers: /* @__PURE__ */ new Map(),
signals: /* @__PURE__ */ new Map()
}));
var custom_tag_default = {
analyze: { enter(tag) {
if (!(0, _marko_compiler_babel_utils.getTagTemplate)(tag)) throw tagNotFoundError(tag);
(0, _marko_compiler_babel_utils.assertAttributesOrSingleArg)(tag);
const childFile = (0, _marko_compiler_babel_utils.loadFileForTag)(tag);
if (!childFile) throw tag.get("name").buildCodeFrameError("Unable to resolve file for tag.");
const tagExtra = tag.node.extra ??= {};
const programExtra = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
const programSection = programExtra.section;
const childExtra = childFile.ast.program.extra;
const childSection = childExtra.section;
if (childExtra.page) programExtra.page ??= true;
if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
if (tagExtra.tagNameLoad || !childExtra.domExports?.setupEmpty) addSetupStatement(getOrCreateSection(tag));
knownTagAnalyze(tag, childSection, programSection === childSection ? programSection.params && getBindingPropTree(programSection.params) : childExtra.domExports?.params);
const tagName = getStaticTagName(tag.node);
if (tagExtra.tagNameLoad) {
visit(tag, 37);
child(tag, tagName);
enterShallow(tag);
} else child(tag, tagName, {
kind: ExportRef,
program: childExtra,
path: getTagRelativePath(tag),
hint: tagName
});
} },
translate: {
enter(tag) {
if (isOutputHTML()) flushBefore(tag);
},
exit(tag) {
if (isOutputHTML()) translateHTML(tag);
else translateDOM(tag);
}
}
};
function translateHTML(tag) {
const { node } = tag;
const childExtra = (0, _marko_compiler_babel_utils.loadFileForTag)(tag).ast.program.extra;
let tagIdentifier;
if (_marko_compiler.types.isStringLiteral(node.name)) {
const relativePath = getTagRelativePath(tag);
tagIdentifier = isCircularRequest((0, _marko_compiler_babel_utils.getFile)(), relativePath) ? _marko_compiler.types.identifier(getTemplateContentName()) : (0, _marko_compiler_babel_utils.importDefault)((0, _marko_compiler_babel_utils.getFile)(), relativePath, getTagName(tag));
} else tagIdentifier = node.name;
knownTagTranslateHTML(tag, tagIdentifier, childExtra.section, childExtra.domExports?.params);
}
function translateDOM(tag) {
const { node } = tag;
const file = (0, _marko_compiler_babel_utils.getFile)();
const relativePath = getTagRelativePath(tag);
const programSection = (0, _marko_compiler_babel_utils.getProgram)().node.extra.section;
const childFile = (0, _marko_compiler_babel_utils.loadFileForTag)(tag);
const childExtra = childFile.ast.program.extra;
const childExports = childExtra.domExports;
const childSection = childExtra.section;
const loadConfig = node.extra?.tagNameLoad;
const isLoad = !!loadConfig;
const tagName = getStaticTagName(node);
if (isLoad) {
const childFileName = childFile.opts.filename;
const { triggers, signals } = getLoadIdentifiers();
let triggerIdent = triggers.get(loadConfig);
if (!triggerIdent) {
const triggerExpr = loadTriggersToExpression(loadConfig);
if (triggerExpr) {
triggerIdent = generateUidIdentifier(`load_${tagName}_trigger`);
triggers.set(loadConfig, triggerIdent);
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(triggerIdent, triggerExpr)]));
}
}
knownTagTranslateDOM(tag, childExports.params, (binding) => {
const signalKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}\0${binding.export}`;
let signalIdent = signals.get(signalKey);
if (!signalIdent) {
signalIdent = generateUidIdentifier(`load_${tagName}_tag_${binding.name}`);
signals.set(signalKey, signalIdent);
const loadExpr = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral(buildLoadSignalVirtualModule(file, childFileName, binding.export, binding.name))]));
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(signalIdent, callRuntime("_load_signal", triggerIdent ? _marko_compiler.types.addComment(_marko_compiler.types.callExpression(triggerIdent, [loadExpr]), "leading", "@__PURE__") : loadExpr))]));
}
return signalIdent;
}, (section, childBinding) => {
const setupIdent = generateUidIdentifier(`load_${tagName}_setup`);
const setupLoadExpr = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral(buildLoadSetupVirtualModule(file, childFileName, childExports))]));
importRuntimeFeature("catch");
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(setupIdent, callRuntime("_load_setup", getScopeAccessorLiteral(node.extra[kLoadTagBinding], true), getScopeAccessorLiteral(childBinding, true), triggerIdent ? _marko_compiler.types.addComment(_marko_compiler.types.callExpression(triggerIdent, [setupLoadExpr]), "leading", "@__PURE__") : setupLoadExpr))]));
addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(setupIdent, [scopeIdentifier])));
});
} else if (programSection === childSection) knownTagTranslateDOM(tag, childExports.params, (binding, preferredName) => getSignal(programSection, binding, preferredName).identifier, childExports.setupEmpty ? void 0 : (section, childBinding) => {
addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.identifier(childExports.setup), [createScopeReadExpression(childBinding, section)])));
});
else {
knownTagTranslateDOM(tag, childExports.params, (binding, preferredName, directContent) => importOrSelfReferenceName((0, _marko_compiler_babel_utils.getFile)(), relativePath, directContent && binding.directContentExport || binding.export, preferredName), childExports.setupEmpty ? void 0 : (section, childBinding) => {
addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importOrSelfReferenceName(file, relativePath, childExports.setup, tagName), [createScopeReadExpression(childBinding, section)])));
});
(0, _marko_compiler_babel_utils.importNamed)(file, relativePath, childExports.template, `${tagName}_template`);
(0, _marko_compiler_babel_utils.importNamed)(file, relativePath, childExports.walks, `${tagName}_walks`);
}
tag.remove();
}
function getTagRelativePath(tag) {
const { node } = tag;
const file = (0, _marko_compiler_babel_utils.getFile)();
let relativePath;
if (_marko_compiler.types.isStringLiteral(node.name)) {
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
const template = node.extra?.featureType === "class" && tagDef?.renderer || (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
relativePath = template && (0, _marko_compiler_babel_utils.resolveRelativePath)(file, template, tagDef);
} else if (node.extra?.tagNameImported) relativePath = node.extra.tagNameImported;
if (!relativePath) throw tagNotFoundError(tag);
return relativePath;
}
const staticHint = "To declare module level JavaScript, prefix the statement with `static`.";
const knownWrongTags = /* @__PURE__ */ new Map([
["slot", "To render content passed to this tag, use a [dynamic tag](https://markojs.com/docs/reference/language#dynamic-tags): `<${input.content}/>`."],
["state", "Reactive state is declared with the [`<let>` tag](https://markojs.com/docs/reference/core-tag#let): `<let/name=initialValue>`."],
["fragment", "Marko templates and tag bodies may have multiple root nodes; no fragment wrapper is needed."],
["async", staticHint],
["class", staticHint],
["declare", staticHint],
["enum", staticHint],
["function", staticHint],
["interface", staticHint],
["type", staticHint]
]);
function tagNotFoundError(tag) {
const tagName = getTagName(tag);
if (tagName && tag.scope.hasBinding(tagName)) return tag.get("name").buildCodeFrameError(`Local variables must be in a [dynamic tag](https://markojs.com/docs/reference/language#dynamic-tags) unless they are PascalCase. Use \`<\${${tagName}}/>\` or rename to \`${tagName.charAt(0).toUpperCase() + tagName.slice(1)}\`.`);
let didYouMean = "";
const knownWrongTagHint = tagName && knownWrongTags.get(tagName);
const proseText = tagName && getProseText(tag);
if (knownWrongTagHint) didYouMean = ` ${knownWrongTagHint}`;
else if (proseText) didYouMean = ` If this line is meant to be text, prefix it with \`--\` (e.g. \`-- ${proseText}\`) or wrap it in an element such as \`<p>${proseText}</p>\`.`;
else if (tagName) {
const closestTag = (0, fastest_levenshtein.closest)(tagName, Object.keys((0, _marko_compiler_babel_utils.getTaglibLookup)((0, _marko_compiler_babel_utils.getFile)()).merged.tags));
if ((0, fastest_levenshtein.distance)(tagName, closestTag) < 4) didYouMean = ` Did you mean \`<${closestTag}>\`?`;
}
return tag.get("name").buildCodeFrameError(`Unable to find entry point for [custom tag](https://markojs.com/docs/reference/custom-tag#relative-custom-tags) \`<${tagName ?? getStaticTagName(tag.node)}>\`.${didYouMean}`);
}
const wordReg = /^[A-Za-z]+$/;
function getProseText(tag) {
const { node } = tag;
const tagName = getTagName(tag);
if (!tagName || !wordReg.test(tagName) || node.var || node.body.params.length || node.body.body.length || !node.attributes.length || !isConciseModeTag(node)) return;
return collectProseWords(node, tagName);
}
function isConciseModeTag(node) {
const tagLoc = node.loc;
const nameLoc = node.name.loc;
if (!tagLoc || !nameLoc) return false;
return tagLoc.start.line === nameLoc.start.line && tagLoc.start.column === nameLoc.start.column;
}
function collectProseWords(node, tagName) {
let text = tagName;
for (const attr of node.attributes) {
if (attr.type !== "MarkoAttribute" || attr.default || !wordReg.test(attr.name) || attr.value.type !== "BooleanLiteral" || attr.value.value !== true) return;
text += " " + attr.name;
}
return text;
}
function buildLoadSetupVirtualModule(file, childFileName, childExports) {
const parts = `${childExports.template}, ${childExports.walks}, ${childExports.setup}`;
return getMarkoOpts().resolveVirtualDependency(file.opts.filename, {
virtualPath: `${(0, _marko_compiler_babel_utils.resolveRelativePath)(file, childFileName)}.setup.js`,
code: `import { ${parts} } from "./${path.default.basename(childFileName)}"\nexport const _ = [${parts}]`
});
}
function buildLoadSignalVirtualModule(file, childFileName, childExport, childBinding) {
return getMarkoOpts().resolveVirtualDependency(file.opts.filename, {
virtualPath: `${(0, _marko_compiler_babel_utils.resolveRelativePath)(file, childFileName)}.${childBinding}.js`,
code: `export { ${childExport} as _ } from "./${path.default.basename(childFileName)}"`
});
}
function loadTriggersToExpression(loadConfig) {
if (!loadConfig || loadConfig.render) return;
const triggers = loadConfig.triggers.map(toDOMTriggerExpression);
return triggers.length === 1 ? triggers[0] : callRuntime("_load_race_trigger", ...triggers);
}
function toDOMTriggerExpression(trigger) {
switch (trigger.type) {
case "visible": return callRuntime("_load_visible_trigger", _marko_compiler.types.stringLiteral(trigger.selector), optionalValueToNode(trigger.options));
case "idle": return callRuntime("_load_idle_trigger", optionalValueToNode(trigger.options));
case "media": return callRuntime("_load_media_trigger", _marko_compiler.types.stringLiteral(trigger.selector));
default: return callRuntime("_load_event_trigger", _marko_compiler.types.stringLiteral(trigger.type.slice(3)), _marko_compiler.types.stringLiteral(trigger.selector));
}
}
function optionalValueToNode(value) {
return value ? _marko_compiler.types.valueToNode(value) : void 0;
}
//#endregion
//#region src/translator/visitors/tag/dynamic-tag.ts
const kDOMBinding = Symbol("dynamic tag dom binding");
const kChildOffsetScopeBinding = Symbol("custom tag scope offset");
const importedDynamicTagResume = /* @__PURE__ */ new WeakSet();
const importedDynamicTagVarResume = /* @__PURE__ */ new WeakSet();
const [getCompatRegistrations] = createProgramState(() => /* @__PURE__ */ new Set());
const [getCompatBoundaryCalls] = createProgramState(() => /* @__PURE__ */ new Map());
function pushCompatRegistration(key, statement) {
const keys = getCompatRegistrations();
if (keys.has(key)) return false;
keys.add(key);
(0, _marko_compiler_babel_utils.getProgram)().node.body.push(statement);
return true;
}
var dynamic_tag_default = {
analyze: { enter(tag) {
if (tag.node.extra?.tagNameUnresolved) throw tagNotFoundError(tag);
(0, _marko_compiler_babel_utils.assertAttributesOrArgs)(tag);
const { node } = tag;
const definedBodySection = node.extra?.defineBodySection;
if (definedBodySection) {
addSetupStatement(getOrCreateSection(tag));
knownTagAnalyze(tag, definedBodySection, definedBodySection.params && getBindingPropTree(definedBodySection.params));
child(tag, getStaticTagName(tag.node), {
kind: SectionRef,
section: definedBodySection
});
return;
}
analyzeAttributeTags(tag);
const tagSection = getOrCreateSection(tag);
const inputNodes = getAllTagReferenceNodes(node);
const tagExtra = mergeReferences(tagSection, node, [node.name, ...inputNodes]);
if (inputNodes.length) tagExtra.dynamicTagInput = true;
const tagBody = tag.get("body");
const hasVar = !!tag.node.var;
const nodeBinding = tagExtra[kDOMBinding] = createBinding("#text", 0, tagSection);
if (hasVar || tag.node.attributes.some((attr) => _marko_compiler.types.isMarkoSpreadAttribute(attr) || isEventOrChangeHandler(attr.name))) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
if (hasVar) {
trackVarReferences(tag, 5);
tag.node.var.extra.binding.scopeOffset = tagExtra[kChildOffsetScopeBinding] = createBinding("#scopeOffset", 0, tagSection);
}
const bodySection = startSection(tagBody);
trackParamsReferences(tagBody, 3);
if (hasVar) addSerializeExpr(tagSection, true, nodeBinding);
addSerializeExpr(tagSection, tagExtra, nodeBinding);
if (!hasVar && !node.arguments && !node.attributes.length && !node.body.body.length) tagExtra[kDirectContent] = true;
if (tagExtra.featureType !== "class" || (0, _marko_compiler_babel_utils.getTagTemplate)(tag)) {
visit(tag, hasVar ? 49 : 37);
enterShallow(tag);
} else if (bodySection) bodySection.structure = null;
} },
translate: {
enter(tag) {
if (tag.node.extra?.featureType === "class" && !isOutputHTML() && !(0, _marko_compiler_babel_utils.getTagTemplate)(tag)) {
tag.remove();
return;
}
if (isOutputHTML()) flushBefore(tag);
},
exit(tag) {
const { node } = tag;
const tagSection = getSection(tag);
const definedBodySection = node.extra?.defineBodySection;
if (definedBodySection) {
const paramsBinding = definedBodySection.params;
const propTree = paramsBinding && getBindingPropTree(paramsBinding);
if (isOutputHTML()) knownTagTranslateHTML(tag, _marko_compiler.types.memberExpression(tag.node.name, _marko_compiler.types.identifier("content")), definedBodySection, propTree);
else {
knownTagTranslateDOM(tag, propTree, (binding, preferredName, directContent) => directContent && binding.directContentExport ? _marko_compiler.types.identifier(binding.directContentExport) : getSignal(definedBodySection, binding, preferredName).identifier, (section, childBinding) => {
const signal = getSignal(definedBodySection, void 0);
if (signalHasStatements(signal)) addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(signal.identifier, _marko_compiler.types.identifier("_")), [createScopeReadExpression(childBinding, section), getScopeExpression(section, definedBodySection.parent)])));
else if (definedBodySection.readsOwner) addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", toMemberExpression(createScopeReadExpression(childBinding, section), getAccessorProp().Owner), getScopeExpression(section, definedBodySection.parent))));
});
tag.remove();
}
return;
}
const tagExtra = node.extra;
const nodeBinding = tagExtra[kDOMBinding];
const isClassAPI = tagExtra.featureType === "class";
const tagsSerializeReason = getSerializeReason(tagSection, nodeBinding);
const serializeReason = tagsSerializeReason;
let tagExpression = node.name;
if (isClassAPI) {
const classTagTemplate = (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
const classFile = classTagTemplate ? (0, _marko_compiler_babel_utils.loadFileForTag)(tag) : void 0;
const classHydration = classFile?.metadata.marko.classHydration;
if (!isOutputHTML() && isOptimize() && classTagTemplate && !tagsSerializeReason && !classHydration) {
tag.remove();
return;
}
((0, _marko_compiler_babel_utils.getProgram)().node.extra ??= {}).needsCompat = true;
if (_marko_compiler.types.isStringLiteral(tagExpression)) tagExpression = (0, _marko_compiler_babel_utils.importDefault)((0, _marko_compiler_babel_utils.getFile)(), getTagRelativePath(tag), tagExpression.value);
if (classTagTemplate) {
const preserveBoundary = !tagsSerializeReason && (classHydration === "descendant" || classHydration === "self" && !!classFile?.metadata.marko.hasComponentBrowser);
const classId = classFile.metadata.marko.id;
const registration = isOutputHTML() ? _marko_compiler.types.callExpression((0, _marko_compiler_babel_utils.importNamed)((0, _marko_compiler_babel_utils.getFile)(), getCompatRuntimeFile(), "s"), [
_marko_compiler.types.stringLiteral(classId),
_marko_compiler.types.identifier(tagExpression.name),
...preserveBoundary ? [_marko_compiler.types.stringLiteral("preserve")] : []
]) : void 0;
if (isOutputHTML() ? serializeReason || classHydration : serializeReason) {
if (pushCompatRegistration(classId, registration ? _marko_compiler.types.markoScriptlet([_marko_compiler.types.expressionStatement(registration)], true) : _marko_compiler.types.expressionStatement(callRuntime("_resume", _marko_compiler.types.stringLiteral(classId), _marko_compiler.types.identifier(tagExpression.name)))) && registration) getCompatBoundaryCalls().set(classId, registration);
}
if (!preserveBoundary) {
const emitted = getCompatBoundaryCalls().get(classId);
if (emitted) emitted.arguments.length = 2;
}
} else {
const rendererName = tagExpression.name;
pushCompatRegistration(rendererName, _marko_compiler.types.markoScriptlet([_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("??=", _marko_compiler.types.memberExpression(_marko_compiler.types.identifier(rendererName), _marko_compiler.types.identifier("_")), _marko_compiler.types.identifier(rendererName)))], true));
}
} else if (_marko_compiler.types.isStringLiteral(tagExpression)) tagExpression = (0, _marko_compiler_babel_utils.importDefault)((0, _marko_compiler_babel_utils.getFile)(), getTagRelativePath(tag), tagExpression.value);
const { properties, statements } = translateAttrs(tag, void 0, void 0, void 0, isClassAPI ? "renderBody" : "content");
const args = [];
const contentProp = getTranslatedBodyContentProperty(properties);
let hasTagArgs = false;
if (node.arguments) {
hasTagArgs = true;
args.push(...node.arguments);
if (properties.length) args.push(propsToExpression(properties));
} else if (contentProp) {
properties.splice(properties.indexOf(contentProp), 1);
args.push(propsToExpression(properties), contentProp.value);
} else args.push(propsToExpression(properties));
if (isOutputHTML()) {
flushInto(tag);
writeHTMLResumeStatements(tag.get("body"));
const serializeArg = getSerializeGuard(tagSection, serializeReason, true);
const dynamicTagExpr = hasTagArgs ? callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, _marko_compiler.types.arrayExpression(args), contentProp ? contentProp.value : _marko_compiler.types.numericLiteral(0), _marko_compiler.types.numericLiteral(1), serializeArg) : callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, args[0], args[1] || (serializeArg ? _marko_compiler.types.numericLiteral(0) : void 0), serializeArg ? _marko_compiler.types.numericLiteral(0) : void 0, serializeArg);
if (node.var) {
const dynamicScopeIdentifier = generateUidIdentifier(tag.get("name").toString() + "_scope");
const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
statements.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(dynamicScopeIdentifier, callRuntime("_peek_scope_id"))]));
statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(node.var, dynamicTagExpr)]), _marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding]), dynamicScopeIdentifier, _marko_compiler.types.stringLiteral(getResumeRegisterId(tagSection, node.var.extra?.binding, "var")), mutatesTagVar ? getScopeAccessorLiteral(nodeBinding) : void 0)));
} else statements.push(_marko_compiler.types.expressionStatement(dynamicTagExpr));
for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
} else {
const section = getSection(tag);
const bodySection = getSectionForBody(tag.get("body"));
const signal = getSignal(section, nodeBinding, "dynamicTag");
let tagVarSignal;
if (tag.node.var) {
const varBinding = tag.node.var.extra.binding;
tagVarSignal = initValue(varBinding);
tagVarSignal.register = tagVarSignal.referenced = true;
tagVarSignal.buildAssignment = (valueSection, value) => {
const changeArgs = [_marko_compiler.types.memberExpression(getScopeExpression(tagVarSignal.section, valueSection), _marko_compiler.types.stringLiteral(getAccessorPrefix().BranchScopes + getScopeAccessor(nodeBinding)), true), value];
if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
return _marko_compiler.types.callExpression(importRuntime("_var_change"), changeArgs);
};
}
signal.build = () => {
return callRuntime("_dynamic_tag", getScopeAccessorLiteral(nodeBinding, true), bodySection && _marko_compiler.types.identifier(bodySection.name), tagVarSignal ? _marko_compiler.types.arrowFunctionExpression([], tagVarSignal.identifier) : void 0, hasTagArgs && _marko_compiler.types.numericLiteral(1));
};
const directBinding = tagExtra.referencedBindings;
if (directBinding && !Array.isArray(directBinding) && directBinding.directContentExport) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.exportNamedDeclaration(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(directBinding.directContentExport), callRuntime("_dynamic_tag_content", getScopeAccessorLiteral(nodeBinding, true)))])));
if (args.length) {
const argsOrInput = hasTagArgs ? _marko_compiler.types.arrayExpression(args) : args[0];
if (!_marko_compiler.types.isObjectExpression(argsOrInput) || argsOrInput.properties.length) signal.extraArgs = [_marko_compiler.types.arrowFunctionExpression([], statements.length ? _marko_compiler.types.blockStatement(statements.concat(_marko_compiler.types.returnStatement(argsOrInput))) : argsOrInput)];
}
if (!isClassAPI) {
enableDynamicTagResume(tag);
enableDynamicTagVarResume(tag);
enableDynamicTagControllables(tag);
}
addValue(section, tagExtra.referencedBindings, signal, tagExpression);
tag.remove();
}
}
}
};
const controlledAttrs = /^(?:value|checked(?:Value)?|open)(?:Change)?$/;
/** The name resolves at run time, so any control kind is possible. */
function enableDynamicTagControllables(tag) {
if (analyzeTagNameType(tag, true) === 1) return;
for (const attr of tag.node.attributes) if (attr.type === "MarkoSpreadAttribute" || attr.type === "MarkoAttribute" && controlledAttrs.test(attr.name)) {
enableControllable(controllableFeatureFor(void 0));
return;
}
}
function enableDynamicTagVarResume(tag) {
const program = (0, _marko_compiler_babel_utils.getProgram)().node;
if (tag.node.var && !importedDynamicTagVarResume.has(program) && analyzeTagNameType(tag, true) !== 1) {
importedDynamicTagVarResume.add(program);
importRuntimeFeature("dynamic-tag-var");
}
}
function enableDynamicTagResume(tag) {
const program = (0, _marko_compiler_babel_utils.getProgram)().node;
if (!importedDynamicTagResume.has(program) && analyzeTagNameType(tag, true) !== 1) {
for (const attr of tag.node.attributes) if (attr.type === "MarkoSpreadAttribute" || attr.type === "MarkoAttribute" && isEventOrChangeHandler(attr.name)) {
importedDynamicTagResume.add(program);
program.body.push(_marko_compiler.types.expressionStatement(callRuntime("_resume_dynamic_tag")));
return;
}
}
}
//#endregion
//#region src/translator/visitors/tag/index.ts
var tag_default = {
analyze: {
enter(tag) {
try {
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
const type = analyzeTagNameType(tag);
const hook = tagDef?.analyzer?.hook;
if (hook) {
enter$1(hook, tag);
return;
}
if (type === 0) {
native_tag_default.analyze.enter(tag);
return;
}
switch (type) {
case 1:
custom_tag_default.analyze.enter(tag);
break;
case 3:
attribute_tag_default.analyze.enter(tag);
break;
case 2:
dynamic_tag_default.analyze.enter(tag);
break;
}
} catch (err) {
(tag.node.extra ??= {}).analyzeFailed = true;
reportAnalyzeError(tag, err);
tag.skip();
}
},
exit(tag) {
if (tag.node.extra?.analyzeFailed) return;
try {
const hook = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.analyzer?.hook;
if (hook) {
exit$1(hook, tag);
return;
}
if (analyzeTagNameType(tag) === 0) native_tag_default.analyze.exit(tag);
} catch (err) {
(tag.node.extra ??= {}).analyzeFailed = true;
reportAnalyzeError(tag, err);
return;
}
}
},
translate: {
enter(tag) {
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
if (tagDef?.translator) {
if (tagDef.translator.path) (0, _marko_compiler_babel_utils.getFile)().metadata.marko.watchFiles.push(tagDef.translator.path);
enter$1(tagDef.translator.hook, tag);
return;
}
for (const attr of tag.get("attributes")) if (attr.isMarkoAttribute()) {
if (attr.node.arguments) throw attr.buildCodeFrameError(`Unsupported arguments on the \`${attr.node.name}\` attribute.`);
}
switch (analyzeTagNameType(tag)) {
case 0:
native_tag_default.translate.enter(tag);
break;
case 1:
custom_tag_default.translate.enter(tag);
break;
case 2:
dynamic_tag_default.translate.enter(tag);
break;
case 3:
attribute_tag_default.translate.enter(tag);
break;
}
},
exit(tag) {
const translator = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.translator;
if (translator) {
exit$1(translator.hook, tag);
return;
}
switch (analyzeTagNameType(tag)) {
case 0:
native_tag_default.translate.exit(tag);
break;
case 1:
custom_tag_default.translate.exit(tag);
break;
case 2:
dynamic_tag_default.translate.exit(tag);
break;
case 3:
attribute_tag_default.translate.exit(tag);
break;
}
}
}
};
//#endregion
//#region src/translator/visitors/text.ts
var text_default = {
analyze: { exit(text) {
if (isNonHTMLText(text)) return;
writeTextTo(text, text.node.value);
if (!isStaticText(getPrevStaticSibling(text))) enterShallow(text);
} },
translate: { exit(text) {
if (isNonHTMLText(text)) return;
if (isOutputHTML()) writeTo$1(text)`${text.node.value}`;
text.remove();
} }
};
//#endregion
//#region src/translator/interop/build-aggregate-error.ts
function buildAggregateError(file, rootMsg, ...paths) {
const err = /* @__PURE__ */ new SyntaxError();
const fileName = path.default.relative(_marko_compiler_modules.cwd, file.opts.filename);
const finalMsg = `${rootMsg}:\n\n${paths.map(([msg, path$13]) => `\x1b[90m${msg} at ${getFileNameWithLoc(fileName, path$13)}:\x1b[0m\n${getFrame(file, path$13)}`).join("\n\n")}`;
if (!("MARKO_DEBUG" in process.env)) err.stack = finalMsg;
Object.defineProperty(err, "message", {
get() {
return finalMsg;
},
set() {}
});
return err;
}
function getFrame(file, { node: { loc } }) {
return loc ? (0, _marko_compiler_internal_babel.codeFrameColumns)(file.code, {
start: {
line: loc.start.line,
column: loc.start.column + 1
},
end: loc.end && loc.start.line === loc.end.line ? {
line: loc.end.line,
column: loc.end.column + 1
} : void 0
}, { highlightCode: true }) : "";
}
function getFileNameWithLoc(fileName, { node: { loc } }) {
if (loc) return `${fileName}(${loc.start.line},${loc.start.column + 1})`;
return fileName;
}
//#endregion
//#region src/translator/interop/constants/feature-type.ts
const Class = "class";
const Tags = "tags";
//#endregion
//#region src/translator/interop/feature-detection.ts
function isTagsAPI(file = (0, _marko_compiler_babel_utils.getFile)()) {
const program = file.path;
const programExtra = program.node.extra ??= {};
let { featureType } = programExtra;
if (!featureType) {
const lookup = (0, _marko_compiler_babel_utils.getTaglibLookup)(file);
const tagsDir = getTagsDir(lookup, file.opts.filename);
const state = {};
if (tagsDir && !lookup.manualTagsDirs?.has(tagsDir)) addFeature(state, Tags, "Template file within a tags directory", program);
scanBody(state, program.get("body"));
featureType = file.metadata.marko.api = programExtra.featureType = state.feature?.type || (lookup.exclusiveTagDiscoveryDirs === "tags" ? "tags" : "class");
}
return featureType === Tags;
}
function getTagsDir(lookup, filename) {
let nearest;
for (const dir of lookup.discoveryDirs || []) if (filename.startsWith(dir) && (filename[dir.length] === "/" || filename[dir.length] === "\\") && (!nearest || dir.length > nearest.length)) nearest = dir;
return !!nearest && /[/\\]tags$/.test(nearest) && nearest;
}
function scanBody(state, body) {
if (body?.length) for (const child of body) switch (child.type) {
case "MarkoTag":
scanTag(state, child);
break;
case "MarkoComment":
if (/^\s*use tags\s*$/.test(child.node.value)) addFeature(state, Tags, "<!-- use tags -->", child);
else if (/^\s*use class\s*$/.test(child.node.value)) addFeature(state, Class, "<!-- use class -->", child);
break;
case "MarkoScriptlet":
if (!child.node.static) addFeature(state, Class, "Scriptlet", child);
break;
case "MarkoClass":
addFeature(state, Class, "Class block", child.get("body"));
break;
}
}
function scanTag(state, tag) {
if (tag.node.var) addFeature(state, Tags, "Tag variable", tag.get("var"));
const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
if (tagDef) {
if (tagDef.name === "style") {
if (/^style(?:(?:\.[^.\s\\/:*?"<>|({]+)+)?\s*\{/.test(tag.node.rawValue || "")) addFeature(state, Class, `style block`, tag.get("name"));
} else if (tagDef.taglibId === runtime_info_default.taglibId) {
const feature = getFeatureTypeFromCoreTagName(tagDef.name);
if (feature) addFeature(state, feature, `<${tagDef.name}> tag`, tag.get("name"));
}
}
if (!tagDef?.parseOptions?.rawOpenTag) {
for (const attr of tag.get("attributes")) if (attr.isMarkoAttribute()) {
if (attr.node.arguments?.length) {
addFeature(state, Class, "Attribute arguments", attr.get("arguments")[0]);
break;
} else if (attr.node.bound) {
addFeature(state, Tags, "Bound attribute", attr);
break;
}
}
}
scanBody(state, tag.get("body").get("body"));
scanBody(state, tag.get("attributeTags"));
}
function getFeatureTypeFromCoreTagName(tagName) {
switch (tagName) {
case "await-reorderer":
case "class":
case "include-html":
case "include-text":
case "init-components":
case "macro":
case "module-code":
case "while": return Class;
case "attrs":
case "const":
case "debug":
case "define":
case "effect":
case "id":
case "let":
case "lifecycle":
case "log":
case "return":
case "show":
case "try": return Tags;
default: return;
}
}
function addFeature(state, type, name, path) {
if (state.feature) {
if (state.feature.type !== type) throw buildAggregateError((0, _marko_compiler_babel_utils.getFile)(), "Cannot mix Tags API and Class API features in the same file", [state.feature.name, state.feature.path], [name, path]);
} else state.feature = {
name,
path,
type
};
}
//#endregion
//#region src/translator/interop/index.ts
function createInteropTranslator(translate5) {
return {
version: translate5.version ?? "0.0.0",
preferAPI: translate5.preferAPI,
transform: mergeVisitors(translate5.transform, transform),
analyze: mergeVisitors(translate5.analyze, analyze),
translate: patchTranslateProgram(mergeVisitors(translate5.translate, translate)),
tagDiscoveryDirs: [...tagDiscoveryDirs, ...translate5.tagDiscoveryDirs],
taglibs: mergeTaglibs(_marko_compiler.taglib.resolveOptionalTaglibs(translate5.optionalTaglibs).concat(translate5.taglibs), taglibs),
getRuntimeEntryFiles(output, optimize) {
return [...translate5.getRuntimeEntryFiles(output, optimize), ...getRuntimeEntryFiles(output, optimize)];
}
};
function patchTranslateProgram(visitor) {
const { Program } = visitor;
const kState = Symbol();
const entryBuilder = {
build(entryFile) {
const state = entryFile[kState];
if (!state) throw entryFile.path.buildCodeFrameError("Unable to build hydrate code, no files were visited before finalizing the build");
if (state.has5) if (state.has6) {
const filename = entryFile.opts.filename;
const baseName = `./${path.default.basename(filename)}`;
const generatorOpts = {
...entryFile.opts.generatorOpts,
sourceMaps: false
};
const { resolveVirtualDependency } = entryFile.markoOpts;
const importHydrateProgram = (name, statements) => {
return _marko_compiler.types.importDeclaration([_marko_compiler.types.importDefaultSpecifier(_marko_compiler.types.identifier(`init${name}`))], _marko_compiler.types.stringLiteral(resolveVirtualDependency(filename, {
code: (0, _marko_compiler_internal_babel.generator)(_marko_compiler.types.program(statements), generatorOpts).code,
virtualPath: `${baseName}.hydrate-${name}.js`
})));
};
return [
...state.needsCompat ? [_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(getCompatRuntimeFile()))] : [],
...Array.from(state.compatFiles, (compatFile) => _marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(compatFile))),
importHydrateProgram("6", builder.build(entryFile, true)),
importHydrateProgram("5", translate5.internalEntryBuilder.build(entryFile, true)),
_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.identifier("init6"), [])),
_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.identifier("init5"), []))
];
} else return translate5.internalEntryBuilder.build(entryFile);
else return builder.build(entryFile);
},
visit(file, entryFile, visitChild) {
const state = entryFile[kState] ||= {
has5: false,
has6: false,
needsCompat: false,
compatFiles: /* @__PURE__ */ new Set()
};
if (isTagsAPI(file)) {
state.has6 = true;
builder.visit(file, entryFile, visitChild);
} else {
state.has5 = true;
if (file.path.node.extra?.resumesCompat) state.needsCompat = true;
if (file.path.node.extra?.resumesClassFns) state.compatFiles.add((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, file.opts.filename));
translate5.internalEntryBuilder.visit(file, entryFile, visitChild);
}
}
};
const enterProgram = getVisitorEnter(Program);
return {
...visitor,
Program: {
enter(program, state) {
const entryFile = (0, _marko_compiler_babel_utils.getFile)();
const { output, entry } = entryFile.markoOpts;
if (!(output === "dom" && entry === "page" || output === "hydrate")) return enterProgram?.call(this, program, state);
const visitedFiles = /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]]);
entryBuilder.visit(entryFile, entryFile, function visitChild(resolved, bundled = false) {
const seenBundled = visitedFiles.get(resolved);
if (seenBundled === false || seenBundled && bundled) return;
visitedFiles.set(resolved, bundled);
const file = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
if (file) entryBuilder.visit(file, entryFile, (id, childBundled = false) => visitChild(resolveRelativeToEntry(entryFile, file, id), childBundled || bundled));
});
program.node.body = entryBuilder.build(entryFile);
program.skip();
},
exit: getVisitorExit(Program)
}
};
}
}
function mergeVisitors(visitor5, visitor6) {
return mergeObjects(visitor5, visitor6, (_, value5, value6) => mergeVisit(value5, value6));
}
function mergeVisit(visit5, visit6) {
const enter5 = getVisitorEnter(visit5);
const enter6 = getVisitorEnter(visit6);
const enter = (enter5 || enter6) && function enter(path$9, state) {
return (isTagsAPI() ? enter6 : enter5)?.call(this, path$9, state);
};
const exit5 = getVisitorExit(visit5);
const exit6 = getVisitorExit(visit6);
const exit = (exit5 || exit6) && function exit(path$10, state) {
return (isTagsAPI() ? exit6 : exit5)?.call(this, path$10, state);
};
return exit ? enter ? {
enter,
exit
} : { exit } : enter;
}
function mergeTaglibs(libs5, libs6) {
const libs5Map = new Map(libs5);
const libs6Map = new Map(libs6);
const merged = [];
for (const taglibId of /* @__PURE__ */ new Set([...libs5Map.keys(), ...libs6Map.keys()])) merged.push([taglibId, mergeObjects(libs5Map.get(taglibId), libs6Map.get(taglibId), (key, value5, value6) => {
switch (key) {
case "migrate":
case "analyze":
case "transform":
case "translate": return mergeVisitors(normalizeVisitor(value5), normalizeVisitor(value6));
default:
if (key[0] === "<") return mergeTagDef(value5, value6);
return value5 ?? value6;
}
})]);
return merged;
}
function mergeTagDef(def5, def6) {
return mergeObjects(normalizeTagDef(def5), normalizeTagDef(def6), (key, value5, value6) => {
switch (key) {
case "parse":
case "migrate":
case "transform":
case "analyze":
case "translate": return mergeVisit(normalizeVisit(value5), normalizeVisit(value6));
default: return value5 ?? value6;
}
});
}
function mergeObjects(a, b, cb) {
const merged = {};
const assign = (key, aValue, bValue) => {
const value = cb(key, aValue, bValue);
if (value !== void 0) merged[key] = value;
};
if (a) if (b) {
for (const key in a) assign(key, a[key], b[key]);
for (const key in b) if (!(key in a)) assign(key, void 0, b[key]);
} else for (const key in a) assign(key, a[key], void 0);
else if (b) for (const key in b) assign(key, void 0, b[key]);
return merged;
}
function normalizeTagDef(tagDef) {
if (tagDef) {
const normalized = {};
for (const key in tagDef) normalized[normalizeTagDefKey(key)] = tagDef[key];
return normalized;
}
}
function normalizeTagDefKey(key) {
switch (key) {
case "code-generator":
case "codeGenerator": return "translate";
case "migrator": return "migrate";
case "node-factory":
case "nodeFactory": return "parse";
case "parse-options": return "parseOptions";
case "transformer": return "transform";
default: return key;
}
}
function normalizeVisitor(visitor) {
return visitor?.default ?? visitor;
}
function normalizeVisit(visitor) {
if (Array.isArray(visitor)) {
let merged;
for (const entry of visitor) merged = sequenceVisit(merged, normalizeVisit(entry));
return merged;
}
return typeof visitor === "function" ? visitor : normalizeVisitor(visitor);
}
function sequenceVisit(first, second) {
if (!first || !second) return first || second;
const enterFirst = getVisitorEnter(first);
const enterSecond = getVisitorEnter(second);
const enter = (enterFirst || enterSecond) && function enter(path$11, state) {
const { node } = path$11;
enterFirst?.call(this, path$11, state);
if (path$11.node === node) enterSecond?.call(this, path$11, state);
};
const exitFirst = getVisitorExit(first);
const exitSecond = getVisitorExit(second);
const exit = (exitFirst || exitSecond) && function exit(path$12, state) {
const { node } = path$12;
exitFirst?.call(this, path$12, state);
if (path$12.node === node) exitSecond?.call(this, path$12, state);
};
return exit ? enter ? {
enter,
exit
} : { exit } : enter;
}
function getVisitorEnter(visit) {
return typeof visit === "function" ? visit : visit?.enter;
}
function getVisitorExit(visit) {
return typeof visit === "object" ? visit?.exit : void 0;
}
//#endregion
//#region src/translator/index.ts
const version = package_json.default.version;
const cheatsheet = "../../cheatsheet.md";
const visitors = extractVisitors({
Program: program_default,
Function: function_default,
ReferencedIdentifier: referenced_identifier_default,
ImportDeclaration: import_declaration_default,
ExportNamedDeclaration: export_declaration_default,
ExportAllDeclaration: export_declaration_default,
MarkoDocumentType: document_type_default,
MarkoDeclaration: declaration_default,
MarkoCDATA: cdata_default,
MarkoText: text_default,
MarkoTag: tag_default,
MarkoPlaceholder: placeholder_default,
MarkoScriptlet: scriptlet_default,
MarkoComment: comment_default
});
const tagDiscoveryDirs = ["tags"];
const preferAPI = "tags";
const { transform, analyze, translate } = visitors;
const taglibs = [[core_default.taglibId, {
...core_default,
migrate: visitors.migrate
}]];
function getRuntimeEntryFiles(output, optimize) {
return [`${runtime_info_default.name}${optimize ? "" : "/debug"}/${output === "html" ? "html" : "dom"}`];
}
//#endregion
exports.analyze = analyze;
exports.cheatsheet = cheatsheet;
exports.createInteropTranslator = createInteropTranslator;
exports.getRuntimeEntryFiles = getRuntimeEntryFiles;
exports.internalEntryBuilder = builder;
exports.preferAPI = preferAPI;
exports.tagDiscoveryDirs = tagDiscoveryDirs;
exports.taglibs = taglibs;
exports.transform = transform;
exports.translate = translate;
exports.version = version;