@getforma/core 0.3.1 → 0.6.1

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.
Files changed (42) hide show
  1. package/README.md +190 -16
  2. package/dist/{chunk-KX5WRZH7.js → chunk-DPSAVBCP.js} +3 -4
  3. package/dist/chunk-DPSAVBCP.js.map +1 -0
  4. package/dist/{chunk-FPSLC62A.cjs → chunk-KH3F5NRU.cjs} +2 -4
  5. package/dist/chunk-KH3F5NRU.cjs.map +1 -0
  6. package/dist/{chunk-5H52PKGF.js → chunk-TKGUHASG.js} +20 -10
  7. package/dist/chunk-TKGUHASG.js.map +1 -0
  8. package/dist/{chunk-TSQ7AKFT.cjs → chunk-YSKF3VRA.cjs} +27 -17
  9. package/dist/chunk-YSKF3VRA.cjs.map +1 -0
  10. package/dist/forma-runtime-csp.js +1 -1
  11. package/dist/forma-runtime.js +1 -1
  12. package/dist/formajs-runtime-hardened.global.js +1 -1
  13. package/dist/formajs-runtime-hardened.global.js.map +1 -1
  14. package/dist/formajs-runtime.global.js +1 -1
  15. package/dist/formajs-runtime.global.js.map +1 -1
  16. package/dist/formajs.global.js +1 -1
  17. package/dist/formajs.global.js.map +1 -1
  18. package/dist/index.cjs +102 -75
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +41 -9
  21. package/dist/index.d.ts +41 -9
  22. package/dist/index.js +46 -17
  23. package/dist/index.js.map +1 -1
  24. package/dist/runtime-hardened.cjs +61 -13
  25. package/dist/runtime-hardened.cjs.map +1 -1
  26. package/dist/runtime-hardened.js +62 -14
  27. package/dist/runtime-hardened.js.map +1 -1
  28. package/dist/runtime.cjs +85 -36
  29. package/dist/runtime.cjs.map +1 -1
  30. package/dist/runtime.js +63 -14
  31. package/dist/runtime.js.map +1 -1
  32. package/dist/ssr/index.cjs +18 -10
  33. package/dist/ssr/index.cjs.map +1 -1
  34. package/dist/ssr/index.js +18 -10
  35. package/dist/ssr/index.js.map +1 -1
  36. package/dist/tc39-compat.cjs +3 -3
  37. package/dist/tc39-compat.js +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-5H52PKGF.js.map +0 -1
  40. package/dist/chunk-FPSLC62A.cjs.map +0 -1
  41. package/dist/chunk-KX5WRZH7.js.map +0 -1
  42. package/dist/chunk-TSQ7AKFT.cjs.map +0 -1
package/dist/runtime.js CHANGED
@@ -1,5 +1,5 @@
1
- import { internalEffect, reconcileList, batch } from './chunk-5H52PKGF.js';
2
- import { createValueSignal, createComputed } from './chunk-KX5WRZH7.js';
1
+ import { internalEffect, reconcileList, batch } from './chunk-TKGUHASG.js';
2
+ import { createSignal, createComputed } from './chunk-DPSAVBCP.js';
3
3
 
4
4
  // src/dom/reconcile.ts
5
5
  function getBindTargets(el) {
@@ -576,12 +576,11 @@ var RE_TOGGLE = /^(\w+)\s*=\s*!(\w+)$/;
576
576
  var RE_ASSIGN = /^(\w+)\s*=\s*(.+)$/;
577
577
  var RE_COMPOUND = /^(\w+)\s*(\+=|-=|\*=|\/=)\s*(.+)$/;
578
578
  var RE_IF_PREFIX = /^if\b/;
579
- var RE_UNQUOTED_KEYS = /(\w+)\s*:/g;
580
579
  var RE_COMPUTED = /^(\w+)\s*=\s*(.+)$/;
581
580
  var RE_FETCH = /^(.+?)(?:→|->)\s*(\S+)(.*)$/;
582
581
  var RE_FETCH_METHOD = /^(GET|POST|PUT|PATCH|DELETE)\s+(.+)$/i;
583
582
  var RE_STRIP_ITEM_BRACES = /^\{item\.?|\}$/g;
584
- var RE_EVENT_REF = /\bevent\b|\$event\b/;
583
+ var RE_EVENT_REF = /\bevent\s*[.([]|\$event\b/;
585
584
  var RE_REFETCH_CALL = /^\$refetch\(\s*['"]([^'"]+)['"]\s*\)$/;
586
585
  var TRANSITION_STATE_SYM = /* @__PURE__ */ Symbol.for("forma-transition-state");
587
586
  var EXPRESSION_CACHE_MAX = 2048;
@@ -596,6 +595,14 @@ function cacheExpression(key, factory) {
596
595
  var scopeExpressionCache = /* @__PURE__ */ new WeakMap();
597
596
  var scopeHandlerCache = /* @__PURE__ */ new WeakMap();
598
597
  var compiledTemplateCache = /* @__PURE__ */ new Map();
598
+ var COMPILED_TEMPLATE_CACHE_MAX = 2048;
599
+ function cacheCompiledTemplate(key, template) {
600
+ if (compiledTemplateCache.size >= COMPILED_TEMPLATE_CACHE_MAX) {
601
+ const first = compiledTemplateCache.keys().next().value;
602
+ if (first !== void 0) compiledTemplateCache.delete(first);
603
+ }
604
+ compiledTemplateCache.set(key, template);
605
+ }
599
606
  var UNSAFE_METHOD_NAMES = /* @__PURE__ */ new Set([
600
607
  "constructor",
601
608
  "__proto__",
@@ -604,7 +611,8 @@ var UNSAFE_METHOD_NAMES = /* @__PURE__ */ new Set([
604
611
  "__defineSetter__",
605
612
  "__lookupGetter__",
606
613
  "__lookupSetter__",
607
- "eval"
614
+ "eval",
615
+ "Function"
608
616
  ]);
609
617
  var BLOCKED_METHOD_REGEXES = (() => {
610
618
  const result = [];
@@ -628,8 +636,36 @@ function findBlockedMethod(expr) {
628
636
  if (dotRe.test(cleaned)) return name;
629
637
  if (bracketRe.test(cleaned)) return name;
630
638
  }
639
+ if (cleaned.includes("[")) {
640
+ const bracketContents = extractBracketContents(cleaned);
641
+ for (const content of bracketContents) {
642
+ if (!content.includes("+")) continue;
643
+ const fragments = content.match(/['"`]([^'"`]*?)['"`]/g);
644
+ if (!fragments) continue;
645
+ const joined = fragments.map((f) => f.slice(1, -1)).join("");
646
+ if (UNSAFE_METHOD_NAMES.has(joined)) return joined;
647
+ }
648
+ }
631
649
  return null;
632
650
  }
651
+ function extractBracketContents(expr) {
652
+ const results = [];
653
+ let depth = 0;
654
+ let start = -1;
655
+ for (let i = 0; i < expr.length; i++) {
656
+ if (expr[i] === "[") {
657
+ if (depth === 0) start = i + 1;
658
+ depth++;
659
+ } else if (expr[i] === "]") {
660
+ depth--;
661
+ if (depth === 0 && start >= 0) {
662
+ results.push(expr.slice(start, i));
663
+ start = -1;
664
+ }
665
+ }
666
+ }
667
+ return results;
668
+ }
633
669
  var TEXT_BINDING_SYM = /* @__PURE__ */ Symbol.for("forma-text-binding-cache");
634
670
  function toTextValue(value) {
635
671
  if (value == null) return "";
@@ -965,7 +1001,7 @@ function compileTemplate(text) {
965
1001
  dynamics,
966
1002
  hasItemRef: dynamics.length > 0
967
1003
  };
968
- compiledTemplateCache.set(text, result);
1004
+ cacheCompiledTemplate(text, result);
969
1005
  return result;
970
1006
  }
971
1007
  var templateTexts = /* @__PURE__ */ new WeakMap();
@@ -1653,6 +1689,7 @@ function buildEvaluator(expr, scope) {
1653
1689
  return key in scope.getters;
1654
1690
  },
1655
1691
  get(_, key) {
1692
+ if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
1656
1693
  const g = scope.getters[key];
1657
1694
  return g ? g() : void 0;
1658
1695
  }
@@ -1808,6 +1845,7 @@ function buildHandler(expr, scope) {
1808
1845
  return key in scope.getters || key in scope.setters;
1809
1846
  },
1810
1847
  get(_, key) {
1848
+ if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
1811
1849
  const g = scope.getters[key];
1812
1850
  return g ? g() : void 0;
1813
1851
  },
@@ -1843,11 +1881,10 @@ function parseState(raw) {
1843
1881
  try {
1844
1882
  parsed = JSON.parse(raw);
1845
1883
  } catch {
1846
- try {
1847
- parsed = JSON.parse(raw.replace(RE_UNQUOTED_KEYS, '"$1":'));
1848
- } catch {
1849
- return {};
1884
+ if (_debug) {
1885
+ dbg("parseState: Invalid JSON in data-forma-state \u2014 use valid JSON with quoted keys. Got:", raw.slice(0, 200));
1850
1886
  }
1887
+ return {};
1851
1888
  }
1852
1889
  for (const key of FORBIDDEN_STATE_KEYS) {
1853
1890
  if (key in parsed) delete parsed[key];
@@ -1867,7 +1904,7 @@ function initScope(stateEl) {
1867
1904
  const getters = {};
1868
1905
  const setters = {};
1869
1906
  for (const [key, initial] of Object.entries(state)) {
1870
- const [get, set] = createValueSignal(initial);
1907
+ const [get, set] = createSignal(initial);
1871
1908
  getters[key] = get;
1872
1909
  setters[key] = set;
1873
1910
  }
@@ -1875,6 +1912,18 @@ function initScope(stateEl) {
1875
1912
  return { getters, setters };
1876
1913
  }
1877
1914
  function bindElement(el, scope, disposers) {
1915
+ const elMagics = {
1916
+ $el: el,
1917
+ $dispatch: (name, detail) => {
1918
+ el.dispatchEvent(new CustomEvent(name, {
1919
+ bubbles: true,
1920
+ composed: true,
1921
+ // crosses Shadow DOM boundaries (important for <forma-stage>)
1922
+ detail
1923
+ }));
1924
+ }
1925
+ };
1926
+ scope = createChildScope(scope, elMagics);
1878
1927
  const known = getDirectives(el);
1879
1928
  const computedAttr = !known || known.has("data-computed") ? el.getAttribute("data-computed") : null;
1880
1929
  if (computedAttr) {
@@ -2254,16 +2303,16 @@ function bindElement(el, scope, disposers) {
2254
2303
  else if (k === "error") errorTarget = v;
2255
2304
  else if (k === "poll") interval = parseInt(v ?? "0", 10);
2256
2305
  }
2257
- const [getTarget, setTarget] = createValueSignal(null);
2306
+ const [getTarget, setTarget] = createSignal(null);
2258
2307
  scope.getters[target] = getTarget;
2259
2308
  scope.setters[target] = setTarget;
2260
2309
  if (loadingTarget) {
2261
- const [gl, sl] = createValueSignal(false);
2310
+ const [gl, sl] = createSignal(false);
2262
2311
  scope.getters[loadingTarget] = gl;
2263
2312
  scope.setters[loadingTarget] = sl;
2264
2313
  }
2265
2314
  if (errorTarget) {
2266
- const [ge, se] = createValueSignal(null);
2315
+ const [ge, se] = createSignal(null);
2267
2316
  scope.getters[errorTarget] = ge;
2268
2317
  scope.setters[errorTarget] = se;
2269
2318
  }