@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
@@ -19,7 +19,6 @@ function createSignal(initialValue) {
19
19
  const setter = (v) => applySignalSet(s, v);
20
20
  return [getter, setter];
21
21
  }
22
- var createValueSignal = createSignal;
23
22
  function internalEffect(fn) {
24
23
  const dispose = alienSignals.effect(fn);
25
24
  return dispose;
@@ -852,12 +851,11 @@ var RE_TOGGLE = /^(\w+)\s*=\s*!(\w+)$/;
852
851
  var RE_ASSIGN = /^(\w+)\s*=\s*(.+)$/;
853
852
  var RE_COMPOUND = /^(\w+)\s*(\+=|-=|\*=|\/=)\s*(.+)$/;
854
853
  var RE_IF_PREFIX = /^if\b/;
855
- var RE_UNQUOTED_KEYS = /(\w+)\s*:/g;
856
854
  var RE_COMPUTED = /^(\w+)\s*=\s*(.+)$/;
857
855
  var RE_FETCH = /^(.+?)(?:→|->)\s*(\S+)(.*)$/;
858
856
  var RE_FETCH_METHOD = /^(GET|POST|PUT|PATCH|DELETE)\s+(.+)$/i;
859
857
  var RE_STRIP_ITEM_BRACES = /^\{item\.?|\}$/g;
860
- var RE_EVENT_REF = /\bevent\b|\$event\b/;
858
+ var RE_EVENT_REF = /\bevent\s*[.([]|\$event\b/;
861
859
  var RE_REFETCH_CALL = /^\$refetch\(\s*['"]([^'"]+)['"]\s*\)$/;
862
860
  var TRANSITION_STATE_SYM = /* @__PURE__ */ Symbol.for("forma-transition-state");
863
861
  var EXPRESSION_CACHE_MAX = 2048;
@@ -872,6 +870,14 @@ function cacheExpression(key, factory) {
872
870
  var scopeExpressionCache = /* @__PURE__ */ new WeakMap();
873
871
  var scopeHandlerCache = /* @__PURE__ */ new WeakMap();
874
872
  var compiledTemplateCache = /* @__PURE__ */ new Map();
873
+ var COMPILED_TEMPLATE_CACHE_MAX = 2048;
874
+ function cacheCompiledTemplate(key, template) {
875
+ if (compiledTemplateCache.size >= COMPILED_TEMPLATE_CACHE_MAX) {
876
+ const first = compiledTemplateCache.keys().next().value;
877
+ if (first !== void 0) compiledTemplateCache.delete(first);
878
+ }
879
+ compiledTemplateCache.set(key, template);
880
+ }
875
881
  var UNSAFE_METHOD_NAMES = /* @__PURE__ */ new Set([
876
882
  "constructor",
877
883
  "__proto__",
@@ -880,7 +886,8 @@ var UNSAFE_METHOD_NAMES = /* @__PURE__ */ new Set([
880
886
  "__defineSetter__",
881
887
  "__lookupGetter__",
882
888
  "__lookupSetter__",
883
- "eval"
889
+ "eval",
890
+ "Function"
884
891
  ]);
885
892
  var BLOCKED_METHOD_REGEXES = (() => {
886
893
  const result = [];
@@ -904,8 +911,36 @@ function findBlockedMethod(expr) {
904
911
  if (dotRe.test(cleaned)) return name;
905
912
  if (bracketRe.test(cleaned)) return name;
906
913
  }
914
+ if (cleaned.includes("[")) {
915
+ const bracketContents = extractBracketContents(cleaned);
916
+ for (const content of bracketContents) {
917
+ if (!content.includes("+")) continue;
918
+ const fragments = content.match(/['"`]([^'"`]*?)['"`]/g);
919
+ if (!fragments) continue;
920
+ const joined = fragments.map((f) => f.slice(1, -1)).join("");
921
+ if (UNSAFE_METHOD_NAMES.has(joined)) return joined;
922
+ }
923
+ }
907
924
  return null;
908
925
  }
926
+ function extractBracketContents(expr) {
927
+ const results = [];
928
+ let depth = 0;
929
+ let start = -1;
930
+ for (let i = 0; i < expr.length; i++) {
931
+ if (expr[i] === "[") {
932
+ if (depth === 0) start = i + 1;
933
+ depth++;
934
+ } else if (expr[i] === "]") {
935
+ depth--;
936
+ if (depth === 0 && start >= 0) {
937
+ results.push(expr.slice(start, i));
938
+ start = -1;
939
+ }
940
+ }
941
+ }
942
+ return results;
943
+ }
909
944
  var TEXT_BINDING_SYM = /* @__PURE__ */ Symbol.for("forma-text-binding-cache");
910
945
  function toTextValue(value2) {
911
946
  if (value2 == null) return "";
@@ -1241,7 +1276,7 @@ function compileTemplate(text) {
1241
1276
  dynamics,
1242
1277
  hasItemRef: dynamics.length > 0
1243
1278
  };
1244
- compiledTemplateCache.set(text, result);
1279
+ cacheCompiledTemplate(text, result);
1245
1280
  return result;
1246
1281
  }
1247
1282
  var templateTexts = /* @__PURE__ */ new WeakMap();
@@ -1929,6 +1964,7 @@ function buildEvaluator(expr, scope) {
1929
1964
  return key in scope.getters;
1930
1965
  },
1931
1966
  get(_, key) {
1967
+ if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
1932
1968
  const g = scope.getters[key];
1933
1969
  return g ? g() : void 0;
1934
1970
  }
@@ -2084,6 +2120,7 @@ function buildHandler(expr, scope) {
2084
2120
  return key in scope.getters || key in scope.setters;
2085
2121
  },
2086
2122
  get(_, key) {
2123
+ if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
2087
2124
  const g = scope.getters[key];
2088
2125
  return g ? g() : void 0;
2089
2126
  },
@@ -2119,11 +2156,10 @@ function parseState(raw) {
2119
2156
  try {
2120
2157
  parsed = JSON.parse(raw);
2121
2158
  } catch {
2122
- try {
2123
- parsed = JSON.parse(raw.replace(RE_UNQUOTED_KEYS, '"$1":'));
2124
- } catch {
2125
- return {};
2159
+ if (_debug) {
2160
+ dbg("parseState: Invalid JSON in data-forma-state \u2014 use valid JSON with quoted keys. Got:", raw.slice(0, 200));
2126
2161
  }
2162
+ return {};
2127
2163
  }
2128
2164
  for (const key of FORBIDDEN_STATE_KEYS) {
2129
2165
  if (key in parsed) delete parsed[key];
@@ -2143,7 +2179,7 @@ function initScope(stateEl) {
2143
2179
  const getters = {};
2144
2180
  const setters = {};
2145
2181
  for (const [key, initial] of Object.entries(state)) {
2146
- const [get, set] = createValueSignal(initial);
2182
+ const [get, set] = createSignal(initial);
2147
2183
  getters[key] = get;
2148
2184
  setters[key] = set;
2149
2185
  }
@@ -2151,6 +2187,18 @@ function initScope(stateEl) {
2151
2187
  return { getters, setters };
2152
2188
  }
2153
2189
  function bindElement(el, scope, disposers) {
2190
+ const elMagics = {
2191
+ $el: el,
2192
+ $dispatch: (name, detail) => {
2193
+ el.dispatchEvent(new CustomEvent(name, {
2194
+ bubbles: true,
2195
+ composed: true,
2196
+ // crosses Shadow DOM boundaries (important for <forma-stage>)
2197
+ detail
2198
+ }));
2199
+ }
2200
+ };
2201
+ scope = createChildScope(scope, elMagics);
2154
2202
  const known = getDirectives(el);
2155
2203
  const computedAttr = !known || known.has("data-computed") ? el.getAttribute("data-computed") : null;
2156
2204
  if (computedAttr) {
@@ -2530,16 +2578,16 @@ function bindElement(el, scope, disposers) {
2530
2578
  else if (k === "error") errorTarget = v;
2531
2579
  else if (k === "poll") interval = parseInt(v ?? "0", 10);
2532
2580
  }
2533
- const [getTarget, setTarget] = createValueSignal(null);
2581
+ const [getTarget, setTarget] = createSignal(null);
2534
2582
  scope.getters[target] = getTarget;
2535
2583
  scope.setters[target] = setTarget;
2536
2584
  if (loadingTarget) {
2537
- const [gl, sl] = createValueSignal(false);
2585
+ const [gl, sl] = createSignal(false);
2538
2586
  scope.getters[loadingTarget] = gl;
2539
2587
  scope.setters[loadingTarget] = sl;
2540
2588
  }
2541
2589
  if (errorTarget) {
2542
- const [ge, se] = createValueSignal(null);
2590
+ const [ge, se] = createSignal(null);
2543
2591
  scope.getters[errorTarget] = ge;
2544
2592
  scope.setters[errorTarget] = se;
2545
2593
  }