@jxsuite/runtime 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runtime.js CHANGED
@@ -80,8 +80,9 @@ class EffectScope {
80
80
  this._isPaused = true;
81
81
  let i, l;
82
82
  if (this.scopes) {
83
- for (i = 0, l = this.scopes.length;i < l; i++) {
84
- this.scopes[i].pause();
83
+ const scopes = this.scopes.slice();
84
+ for (i = 0, l = scopes.length;i < l; i++) {
85
+ scopes[i].pause();
85
86
  }
86
87
  }
87
88
  for (i = 0, l = this.effects.length;i < l; i++) {
@@ -95,12 +96,14 @@ class EffectScope {
95
96
  this._isPaused = false;
96
97
  let i, l;
97
98
  if (this.scopes) {
98
- for (i = 0, l = this.scopes.length;i < l; i++) {
99
- this.scopes[i].resume();
99
+ const scopes = this.scopes.slice();
100
+ for (i = 0, l = scopes.length;i < l; i++) {
101
+ scopes[i].resume();
100
102
  }
101
103
  }
102
- for (i = 0, l = this.effects.length;i < l; i++) {
103
- this.effects[i].resume();
104
+ const effects = this.effects.slice();
105
+ for (i = 0, l = effects.length;i < l; i++) {
106
+ effects[i].resume();
104
107
  }
105
108
  }
106
109
  }
@@ -154,8 +157,9 @@ class EffectScope {
154
157
  }
155
158
  this.cleanups.length = 0;
156
159
  if (this.scopes) {
157
- for (i = 0, l = this.scopes.length;i < l; i++) {
158
- this.scopes[i].stop(true);
160
+ const scopes = this.scopes.slice();
161
+ for (i = 0, l = scopes.length;i < l; i++) {
162
+ scopes[i].stop(true);
159
163
  }
160
164
  this.scopes.length = 0;
161
165
  }
@@ -1411,33 +1415,142 @@ var BINARY_OPS = new Set([
1411
1415
  ">",
1412
1416
  ">=",
1413
1417
  "&&",
1414
- "||"
1418
+ "||",
1419
+ "??"
1415
1420
  ]);
1416
1421
  var ASSIGNMENT_OPS = new Set(["=", "+=", "-=", "*=", "/="]);
1417
1422
  var ARRAY_METHOD_OPS = new Set(["push", "pop", "shift", "unshift", "splice"]);
1418
1423
  var AGGREGATE_OPS = new Set(["reduce", "map", "filter"]);
1424
+ var CONDITIONAL_OPS = new Set(["?:", "switch"]);
1425
+ var PURE_METHOD_OPS = new Set([
1426
+ "includes",
1427
+ "indexOf",
1428
+ "lastIndexOf",
1429
+ "join",
1430
+ "slice",
1431
+ "concat",
1432
+ "at",
1433
+ "flat",
1434
+ "toSorted",
1435
+ "toReversed",
1436
+ "toSpliced",
1437
+ "with",
1438
+ "toUpperCase",
1439
+ "toLowerCase",
1440
+ "trim",
1441
+ "trimStart",
1442
+ "trimEnd",
1443
+ "split",
1444
+ "startsWith",
1445
+ "endsWith",
1446
+ "padStart",
1447
+ "padEnd",
1448
+ "replaceAll",
1449
+ "repeat",
1450
+ "charAt",
1451
+ "normalize",
1452
+ "toLocaleUpperCase",
1453
+ "toLocaleLowerCase",
1454
+ "toFixed",
1455
+ "toPrecision",
1456
+ "toLocaleString"
1457
+ ]);
1419
1458
  var BLESSED_OPERATORS = new Set([
1420
1459
  ...MUTATING_OPS,
1421
1460
  ...UNARY_OPS,
1422
1461
  ...BINARY_OPS,
1423
- ...AGGREGATE_OPS
1462
+ ...AGGREGATE_OPS,
1463
+ ...CONDITIONAL_OPS,
1464
+ ...PURE_METHOD_OPS,
1465
+ "call"
1466
+ ]);
1467
+ var BLESSED_GLOBALS = new Set([
1468
+ "isNaN",
1469
+ "isFinite",
1470
+ "parseFloat",
1471
+ "parseInt",
1472
+ "encodeURIComponent",
1473
+ "decodeURIComponent",
1474
+ "structuredClone",
1475
+ "Math/abs",
1476
+ "Math/ceil",
1477
+ "Math/floor",
1478
+ "Math/round",
1479
+ "Math/trunc",
1480
+ "Math/sign",
1481
+ "Math/sqrt",
1482
+ "Math/cbrt",
1483
+ "Math/pow",
1484
+ "Math/exp",
1485
+ "Math/log",
1486
+ "Math/log2",
1487
+ "Math/log10",
1488
+ "Math/min",
1489
+ "Math/max",
1490
+ "Math/hypot",
1491
+ "Number/isInteger",
1492
+ "Number/isFinite",
1493
+ "Number/isNaN",
1494
+ "Number/parseFloat",
1495
+ "Number/parseInt",
1496
+ "JSON/parse",
1497
+ "JSON/stringify",
1498
+ "Object/keys",
1499
+ "Object/values",
1500
+ "Object/entries",
1501
+ "Object/fromEntries",
1502
+ "Array/from",
1503
+ "Array/isArray",
1504
+ "Array/of",
1505
+ "String/fromCharCode",
1506
+ "String/fromCodePoint",
1507
+ "Intl/formatNumber",
1508
+ "Intl/formatDate",
1509
+ "Intl/formatRelativeTime"
1424
1510
  ]);
1511
+ var BLESSED_HELPERS = {
1512
+ "Intl/formatDate": (value, locale, options) => new Intl.DateTimeFormat(locale, options).format(new Date(value)),
1513
+ "Intl/formatNumber": (value, locale, options) => new Intl.NumberFormat(locale, options).format(value),
1514
+ "Intl/formatRelativeTime": (value, unit, locale, options) => new Intl.RelativeTimeFormat(locale, options).format(value, unit)
1515
+ };
1516
+ function isBlessedGlobal(ref2) {
1517
+ return ref2.startsWith("window#/") && BLESSED_GLOBALS.has(ref2.slice("window#/".length));
1518
+ }
1425
1519
  function isMutating(op) {
1426
1520
  return MUTATING_OPS.has(op);
1427
1521
  }
1428
- function resolveOperand(operand, state, event, iterCtx) {
1522
+ var MAX_CALL_DEPTH = 64;
1523
+ var MAX_REPORT_DEPTH = 64;
1524
+ function subTrace(trace, seg) {
1525
+ if (!trace) {
1526
+ return;
1527
+ }
1528
+ const depth = (trace.depth ?? 0) + 1;
1529
+ if (depth > MAX_REPORT_DEPTH) {
1530
+ return;
1531
+ }
1532
+ return {
1533
+ depth,
1534
+ path: [...trace.path ?? [], ...Array.isArray(seg) ? seg : [seg]],
1535
+ report: trace.report
1536
+ };
1537
+ }
1538
+ function resolveOperand(operand, state, event, iterCtx, trace) {
1429
1539
  if (operand === null || operand === undefined) {
1430
1540
  return operand;
1431
1541
  }
1432
1542
  if (typeof operand === "object" && !Array.isArray(operand) && "operator" in operand) {
1433
- return evaluateExpression(operand, state, event, iterCtx);
1543
+ return evaluateExpression(operand, state, event, iterCtx, trace);
1434
1544
  }
1435
1545
  if (typeof operand === "object" && !Array.isArray(operand) && "$ref" in operand) {
1436
- return resolveExprRef(operand.$ref, state, event, iterCtx);
1546
+ const resolved = resolveExprRef(operand.$ref, state, event, iterCtx);
1547
+ trace?.report(trace.path ?? [], resolved);
1548
+ return resolved;
1437
1549
  }
1438
1550
  if (Array.isArray(operand)) {
1439
- return operand.map((o) => resolveOperand(o, state, event, iterCtx));
1551
+ return operand.map((o, i) => resolveOperand(o, state, event, iterCtx, subTrace(trace, i)));
1440
1552
  }
1553
+ trace?.report(trace.path ?? [], operand);
1441
1554
  return operand;
1442
1555
  }
1443
1556
  function resolveExprRef(ref2, state, event, iterCtx) {
@@ -1447,6 +1560,11 @@ function resolveExprRef(ref2, state, event, iterCtx) {
1447
1560
  if (ref2.startsWith("$reduce/")) {
1448
1561
  return iterCtx?.acc;
1449
1562
  }
1563
+ if (ref2.startsWith("$args/")) {
1564
+ const parts = ref2.slice("$args/".length).split("/");
1565
+ const base = iterCtx?.args?.[parts[0]];
1566
+ return parts.length > 1 ? getPath(base, parts.slice(1).join("/")) : base;
1567
+ }
1450
1568
  if (ref2.startsWith("event#/")) {
1451
1569
  const path = ref2.slice("event#/".length);
1452
1570
  return getPath(event, path);
@@ -1524,13 +1642,18 @@ function resolveWritableRef(ref2, state, _event, iterCtx) {
1524
1642
  }
1525
1643
  return { key: ref2, obj: state };
1526
1644
  }
1527
- function evaluateExpression(node, state, event, iterCtx) {
1645
+ function evaluateExpression(node, state, event, iterCtx, trace) {
1646
+ const result = evaluateNode(node, state, event, iterCtx, trace);
1647
+ trace?.report(trace.path ?? [], result);
1648
+ return result;
1649
+ }
1650
+ function evaluateNode(node, state, event, iterCtx, trace) {
1528
1651
  const { operator, target, value, initial } = node;
1529
1652
  if (!BLESSED_OPERATORS.has(operator)) {
1530
1653
  throw new Error(`$expression: unknown operator "${operator}"`);
1531
1654
  }
1532
1655
  if (UNARY_OPS.has(operator) && !("value" in node)) {
1533
- const operand = resolveOperand(target, state, event, iterCtx);
1656
+ const operand = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1534
1657
  if (operator === "!") {
1535
1658
  return !operand;
1536
1659
  }
@@ -1538,9 +1661,78 @@ function evaluateExpression(node, state, event, iterCtx) {
1538
1661
  return -operand;
1539
1662
  }
1540
1663
  }
1664
+ if (operator === "call") {
1665
+ const calleeRef = target?.$ref;
1666
+ if (typeof calleeRef !== "string") {
1667
+ throw new TypeError("$expression: call target must be a $ref pointer");
1668
+ }
1669
+ const callDepth = (iterCtx?.callDepth ?? 0) + 1;
1670
+ if (callDepth > MAX_CALL_DEPTH) {
1671
+ throw new Error(`$expression: call depth exceeded (${MAX_CALL_DEPTH})`);
1672
+ }
1673
+ const argValues = Array.isArray(value) ? value.map((o, i) => resolveOperand(o, state, event, iterCtx, subTrace(trace, ["value", i]))) : [];
1674
+ if (calleeRef.startsWith("window#/")) {
1675
+ if (!isBlessedGlobal(calleeRef)) {
1676
+ throw new Error(`$expression: "${calleeRef}" is not a blessed pure global`);
1677
+ }
1678
+ const globalPath = calleeRef.slice("window#/".length);
1679
+ const helper = BLESSED_HELPERS[globalPath];
1680
+ if (helper) {
1681
+ return helper(...argValues);
1682
+ }
1683
+ const fn = getPath(globalThis.window, globalPath);
1684
+ const lastSlash = globalPath.lastIndexOf("/");
1685
+ const thisArg = lastSlash === -1 ? globalThis.window : getPath(globalThis.window, globalPath.slice(0, lastSlash));
1686
+ return fn.apply(thisArg, argValues);
1687
+ }
1688
+ const callee = resolveExprRef(calleeRef, state, event, iterCtx);
1689
+ if (typeof callee === "function") {
1690
+ return callee(...argValues);
1691
+ }
1692
+ if (callee && typeof callee === "object" && "$expression" in callee) {
1693
+ const def2 = callee;
1694
+ const args = {};
1695
+ for (const [i, p] of (def2.parameters ?? []).entries()) {
1696
+ const name = typeof p === "string" ? p : p?.name ?? "";
1697
+ if (!name) {
1698
+ continue;
1699
+ }
1700
+ args[name] = argValues[i] === undefined && typeof p === "object" && p !== null && "default" in p ? p.default : argValues[i];
1701
+ }
1702
+ return evaluateExpression(def2.$expression, state, event, { args, callDepth });
1703
+ }
1704
+ throw new TypeError(`$expression: call target "${calleeRef}" is not callable`);
1705
+ }
1706
+ if (CONDITIONAL_OPS.has(operator)) {
1707
+ if (operator === "?:") {
1708
+ const test = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1709
+ if (trace) {
1710
+ const consequent = resolveOperand(value, state, event, iterCtx, subTrace(trace, "value"));
1711
+ const alternate = resolveOperand(initial, state, event, iterCtx, subTrace(trace, "initial"));
1712
+ return test ? consequent : alternate;
1713
+ }
1714
+ return test ? resolveOperand(value, state, event, iterCtx) : resolveOperand(initial, state, event, iterCtx);
1715
+ }
1716
+ const discriminant = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1717
+ const key = String(discriminant);
1718
+ const cases = node.cases ?? {};
1719
+ const matched = Object.hasOwn(cases, key);
1720
+ if (trace) {
1721
+ let result;
1722
+ for (const [k, caseOperand] of Object.entries(cases)) {
1723
+ const v = resolveOperand(caseOperand, state, event, iterCtx, subTrace(trace, ["cases", k]));
1724
+ if (k === key) {
1725
+ result = v;
1726
+ }
1727
+ }
1728
+ const fallback = resolveOperand(node.default, state, event, iterCtx, subTrace(trace, "default"));
1729
+ return matched ? result : fallback;
1730
+ }
1731
+ return matched ? resolveOperand(cases[key], state, event, iterCtx) : resolveOperand(node.default, state, event, iterCtx);
1732
+ }
1541
1733
  if (BINARY_OPS.has(operator)) {
1542
- const left = resolveOperand(target, state, event, iterCtx);
1543
- const right = resolveOperand(value, state, event, iterCtx);
1734
+ const left = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1735
+ const right = resolveOperand(value, state, event, iterCtx, subTrace(trace, "value"));
1544
1736
  switch (operator) {
1545
1737
  case "+": {
1546
1738
  return left + right;
@@ -1581,13 +1773,16 @@ function evaluateExpression(node, state, event, iterCtx) {
1581
1773
  case "||": {
1582
1774
  return left || right;
1583
1775
  }
1776
+ case "??": {
1777
+ return left ?? right;
1778
+ }
1584
1779
  default: {
1585
1780
  break;
1586
1781
  }
1587
1782
  }
1588
1783
  }
1589
1784
  if (ASSIGNMENT_OPS.has(operator)) {
1590
- const rhs = resolveOperand(value, state, event, iterCtx);
1785
+ const rhs = resolveOperand(value, state, event, iterCtx, subTrace(trace, "value"));
1591
1786
  const { obj, key } = resolveWritableRef(target.$ref, state, event, iterCtx);
1592
1787
  switch (operator) {
1593
1788
  case "=": {
@@ -1621,13 +1816,13 @@ function evaluateExpression(node, state, event, iterCtx) {
1621
1816
  return;
1622
1817
  }
1623
1818
  if (ARRAY_METHOD_OPS.has(operator)) {
1624
- const arr = resolveOperand(target, state, event, iterCtx);
1819
+ const arr = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1625
1820
  switch (operator) {
1626
1821
  case "push": {
1627
- return arr.push(resolveOperand(value, state, event, iterCtx));
1822
+ return arr.push(resolveOperand(value, state, event, iterCtx, subTrace(trace, "value")));
1628
1823
  }
1629
1824
  case "unshift": {
1630
- return arr.unshift(resolveOperand(value, state, event, iterCtx));
1825
+ return arr.unshift(resolveOperand(value, state, event, iterCtx, subTrace(trace, "value")));
1631
1826
  }
1632
1827
  case "pop": {
1633
1828
  return arr.pop();
@@ -1636,7 +1831,7 @@ function evaluateExpression(node, state, event, iterCtx) {
1636
1831
  return arr.shift();
1637
1832
  }
1638
1833
  case "splice": {
1639
- const args = resolveOperand(value, state, event, iterCtx);
1834
+ const args = resolveOperand(value, state, event, iterCtx, subTrace(trace, "value"));
1640
1835
  return arr.splice(...args);
1641
1836
  }
1642
1837
  default: {
@@ -1644,32 +1839,29 @@ function evaluateExpression(node, state, event, iterCtx) {
1644
1839
  }
1645
1840
  }
1646
1841
  }
1842
+ if (PURE_METHOD_OPS.has(operator)) {
1843
+ const receiver = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1844
+ const args = value === undefined ? [] : Array.isArray(value) ? resolveOperand(value, state, event, iterCtx, subTrace(trace, "value")) : [resolveOperand(value, state, event, iterCtx, subTrace(trace, "value"))];
1845
+ const method = receiver?.[operator];
1846
+ if (typeof method !== "function") {
1847
+ return;
1848
+ }
1849
+ return method.apply(receiver, args);
1850
+ }
1647
1851
  if (AGGREGATE_OPS.has(operator)) {
1648
- const arr = resolveOperand(target, state, event, iterCtx);
1852
+ const arr = resolveOperand(target, state, event, iterCtx, subTrace(trace, "target"));
1649
1853
  if (operator === "reduce") {
1650
- let acc = resolveOperand(initial, state, event, iterCtx);
1854
+ let acc = resolveOperand(initial, state, event, iterCtx, subTrace(trace, "initial"));
1651
1855
  for (const [index, item] of arr.entries()) {
1652
- acc = evaluateExpression(value, state, event, {
1653
- acc,
1654
- index,
1655
- item
1656
- });
1856
+ acc = evaluateExpression(value, state, event, { acc, index, item }, index === 0 ? subTrace(trace, "value") : undefined);
1657
1857
  }
1658
1858
  return acc;
1659
1859
  }
1660
1860
  if (operator === "map") {
1661
- return arr.map((item, index) => evaluateExpression(value, state, event, {
1662
- ...iterCtx,
1663
- index,
1664
- item
1665
- }));
1861
+ return arr.map((item, index) => evaluateExpression(value, state, event, { ...iterCtx, index, item }, index === 0 ? subTrace(trace, "value") : undefined));
1666
1862
  }
1667
1863
  if (operator === "filter") {
1668
- return arr.filter((item, index) => evaluateExpression(value, state, event, {
1669
- ...iterCtx,
1670
- index,
1671
- item
1672
- }));
1864
+ return arr.filter((item, index) => evaluateExpression(value, state, event, { ...iterCtx, index, item }, index === 0 ? subTrace(trace, "value") : undefined));
1673
1865
  }
1674
1866
  }
1675
1867
  return;
@@ -1681,6 +1873,9 @@ function getPath(obj, path) {
1681
1873
  }
1682
1874
  return current;
1683
1875
  }
1876
+ function evaluateOperand(operand, state, event, iterCtx) {
1877
+ return resolveOperand(operand, state, event, iterCtx);
1878
+ }
1684
1879
 
1685
1880
  // ../schema/src/guards.ts
1686
1881
  function isJsonObject(value) {
@@ -1695,6 +1890,12 @@ function isFunctionDef(value) {
1695
1890
  function isExpressionDef(value) {
1696
1891
  return isJsonObject(value) && isJsonObject(value.$expression);
1697
1892
  }
1893
+ function isNamedFormulaDef(value) {
1894
+ return isExpressionDef(value) && Array.isArray(value.parameters) && value.parameters.length > 0;
1895
+ }
1896
+ function hasStructuredBody(value) {
1897
+ return isFunctionDef(value) && Array.isArray(value.body);
1898
+ }
1698
1899
  function isPrototypeDef(value) {
1699
1900
  return isJsonObject(value) && typeof value.$prototype === "string" && value.$prototype !== "Function";
1700
1901
  }
@@ -1727,6 +1928,74 @@ function paramNames(parameters) {
1727
1928
  return parameters.map((p) => typeof p === "string" ? p : p.name);
1728
1929
  }
1729
1930
 
1931
+ // src/statements.ts
1932
+ function statementKind(statement) {
1933
+ if ("operator" in statement) {
1934
+ return "expression";
1935
+ }
1936
+ if ("if" in statement) {
1937
+ return "if";
1938
+ }
1939
+ if ("$switch" in statement) {
1940
+ return "switch";
1941
+ }
1942
+ return "dispatch";
1943
+ }
1944
+ async function runStatements(statements, state, event, opts = {}) {
1945
+ const iterCtx = opts.args ? { args: opts.args } : undefined;
1946
+ for (const statement of statements) {
1947
+ switch (statementKind(statement)) {
1948
+ case "expression": {
1949
+ const result = evaluateExpression(statement, state, event, iterCtx);
1950
+ if (result && typeof result.then === "function") {
1951
+ await result;
1952
+ }
1953
+ break;
1954
+ }
1955
+ case "if": {
1956
+ const branch = statement;
1957
+ const taken = evaluateOperand(branch.if, state, event, iterCtx) ? branch.then : branch.else;
1958
+ if (Array.isArray(taken)) {
1959
+ await runStatements(taken, state, event, opts);
1960
+ }
1961
+ break;
1962
+ }
1963
+ case "switch": {
1964
+ const branch = statement;
1965
+ const key = String(evaluateOperand(branch.$switch, state, event, iterCtx));
1966
+ const cases = branch.cases ?? {};
1967
+ const taken = Object.hasOwn(cases, key) ? cases[key] : branch.default;
1968
+ if (Array.isArray(taken)) {
1969
+ await runStatements(taken, state, event, opts);
1970
+ }
1971
+ break;
1972
+ }
1973
+ case "dispatch": {
1974
+ const dispatch = statement;
1975
+ const target = opts.target ?? event?.currentTarget;
1976
+ if (!target) {
1977
+ break;
1978
+ }
1979
+ const init = {};
1980
+ if ("detail" in dispatch) {
1981
+ init.detail = evaluateOperand(dispatch.detail, state, event, iterCtx);
1982
+ }
1983
+ if (dispatch.bubbles !== undefined) {
1984
+ init.bubbles = dispatch.bubbles;
1985
+ }
1986
+ if (dispatch.composed !== undefined) {
1987
+ init.composed = dispatch.composed;
1988
+ }
1989
+ target.dispatchEvent(new CustomEvent(dispatch.dispatchEvent, init));
1990
+ break;
1991
+ }
1992
+ default: {
1993
+ break;
1994
+ }
1995
+ }
1996
+ }
1997
+ }
1998
+
1730
1999
  // src/runtime.ts
1731
2000
  async function Jx(source, target = document.body, options) {
1732
2001
  const base = typeof source === "string" ? new URL(source, location.href).href : location.href;
@@ -1835,6 +2104,37 @@ function canvasAttrName(el, key) {
1835
2104
  }
1836
2105
  return key;
1837
2106
  }
2107
+ var _stampPropBindings = false;
2108
+ function setStampPropBindings(on) {
2109
+ _stampPropBindings = on;
2110
+ }
2111
+ var PURE_STATE_TEMPLATE = /^\s*\$\{\s*state\.(\w+)\s*\}\s*$/;
2112
+ function boundPropKey(key, val, state) {
2113
+ if (!_stampPropBindings || key !== "textContent") {
2114
+ return null;
2115
+ }
2116
+ let sub = null;
2117
+ if (isRefObj(val)) {
2118
+ if (!val.$ref.startsWith("#/state/")) {
2119
+ return null;
2120
+ }
2121
+ const rest = val.$ref.slice("#/state/".length);
2122
+ sub = rest && !rest.includes("/") ? rest : null;
2123
+ } else if (typeof val === "string") {
2124
+ sub = PURE_STATE_TEMPLATE.exec(val)?.[1] ?? null;
2125
+ }
2126
+ if (!sub) {
2127
+ return null;
2128
+ }
2129
+ const stored = toRaw(state)[sub];
2130
+ if (isRef(stored) || typeof stored === "function") {
2131
+ return null;
2132
+ }
2133
+ if (typeof stored === "object" && stored !== null) {
2134
+ return null;
2135
+ }
2136
+ return sub;
2137
+ }
1838
2138
  async function buildScope(doc, parentScope = {}, base = location.href) {
1839
2139
  const raw = {};
1840
2140
  for (const [key, val] of Object.entries(parentScope)) {
@@ -1898,7 +2198,20 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1898
2198
  for (const [key, def2] of Object.entries(defs)) {
1899
2199
  if (isExpressionDef(def2)) {
1900
2200
  const node = def2.$expression;
1901
- if (isMutating(node.operator)) {
2201
+ if (isNamedFormulaDef(def2)) {
2202
+ const params = def2.parameters;
2203
+ state[key] = (...argValues) => {
2204
+ const args = {};
2205
+ for (const [i, p] of params.entries()) {
2206
+ const name = typeof p === "string" ? p : p?.name ?? "";
2207
+ if (!name) {
2208
+ continue;
2209
+ }
2210
+ args[name] = argValues[i] === undefined && typeof p === "object" && p !== null && "default" in p ? p.default : argValues[i];
2211
+ }
2212
+ return evaluateExpression(node, state, null, { args });
2213
+ };
2214
+ } else if (isMutating(node.operator)) {
1902
2215
  const handler = (s, event) => evaluateExpression(node, s, event);
1903
2216
  state[key] = handler;
1904
2217
  } else {
@@ -1907,7 +2220,28 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1907
2220
  }
1908
2221
  }
1909
2222
  for (const [key, def2] of Object.entries(defs)) {
1910
- if (isFunctionDef(def2)) {
2223
+ if (hasStructuredBody(def2)) {
2224
+ const { body } = def2;
2225
+ if (Array.isArray(def2.parameters) && def2.parameters.length > 0) {
2226
+ const params = def2.parameters;
2227
+ state[key] = (...argValues) => {
2228
+ const args = {};
2229
+ for (const [i, p] of params.entries()) {
2230
+ const name = typeof p === "string" ? p : p?.name ?? "";
2231
+ if (!name) {
2232
+ continue;
2233
+ }
2234
+ args[name] = argValues[i] === undefined && typeof p === "object" && p !== null && "default" in p ? p.default : argValues[i];
2235
+ }
2236
+ return runStatements(body, state, null, { args });
2237
+ };
2238
+ } else {
2239
+ const handler = (s, event) => {
2240
+ runStatements(body, s, event ?? null);
2241
+ };
2242
+ state[key] = handler;
2243
+ }
2244
+ } else if (isFunctionDef(def2)) {
1911
2245
  state[key] = await resolveFunction(def2, state, key, base);
1912
2246
  }
1913
2247
  }
@@ -1958,7 +2292,7 @@ async function resolveFunction(def2, state, key, base) {
1958
2292
  return noop;
1959
2293
  }
1960
2294
  let fn;
1961
- if (def2.body) {
2295
+ if (typeof def2.body === "string") {
1962
2296
  const params = resolveParamNames(def2);
1963
2297
  fn = new Function(...params, def2.body);
1964
2298
  Object.defineProperty(fn, "name", {
@@ -1996,7 +2330,7 @@ async function resolveFunction(def2, state, key, base) {
1996
2330
  const hasParams = (def2.parameters ?? def2.arguments ?? []).length > 0;
1997
2331
  let isComputed = false;
1998
2332
  if (!hasParams) {
1999
- if (def2.body) {
2333
+ if (typeof def2.body === "string") {
2000
2334
  isComputed = /\breturn\b/.test(def2.body);
2001
2335
  } else if (fn) {
2002
2336
  isComputed = fn.length <= 1 && /\breturn\b/.test(fn.toString());
@@ -2122,7 +2456,15 @@ function applyProperties(el, def2, state) {
2122
2456
  }
2123
2457
  continue;
2124
2458
  }
2125
- if (isFunctionDef(val) && val.body) {
2459
+ if (hasStructuredBody(val)) {
2460
+ const { body } = val;
2461
+ const scope = state;
2462
+ el.addEventListener(key.slice(2), (e) => {
2463
+ runStatements(body, scope, e);
2464
+ });
2465
+ continue;
2466
+ }
2467
+ if (isFunctionDef(val) && typeof val.body === "string") {
2126
2468
  const params = resolveParamNames(val);
2127
2469
  const fn = new Function(...params, val.body);
2128
2470
  const scope = state;
@@ -2141,6 +2483,10 @@ function applyProperties(el, def2, state) {
2141
2483
  }
2142
2484
  function bindProperty(el, key, val, state) {
2143
2485
  const target = el;
2486
+ const boundProp = boundPropKey(key, val, state);
2487
+ if (boundProp) {
2488
+ el.dataset.jxBoundProp = boundProp;
2489
+ }
2144
2490
  if (isRefObj(val)) {
2145
2491
  const refVal = val;
2146
2492
  if (key === "id") {
@@ -3207,6 +3553,7 @@ function distributeSlots(host, slottedChildren) {
3207
3553
  export {
3208
3554
  transposeCanvasUnits,
3209
3555
  toCSSText,
3556
+ setStampPropBindings,
3210
3557
  setSkipServerFunctions,
3211
3558
  setSkipContentResolution,
3212
3559
  setRootMedia,
@@ -3231,5 +3578,5 @@ export {
3231
3578
  Jx
3232
3579
  };
3233
3580
 
3234
- //# debugId=242E5668DE62643A64756E2164756E21
3581
+ //# debugId=B1BA44E09A6FC37E64756E2164756E21
3235
3582
  //# sourceMappingURL=runtime.js.map