@getforma/core 1.0.9 → 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.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-263HW3KN.cjs +35 -0
  3. package/dist/chunk-263HW3KN.cjs.map +1 -0
  4. package/dist/chunk-2QQBKQIF.js +30 -0
  5. package/dist/chunk-2QQBKQIF.js.map +1 -0
  6. package/dist/{chunk-6FW5E54W.cjs → chunk-2Y5US35K.cjs} +127 -103
  7. package/dist/chunk-2Y5US35K.cjs.map +1 -0
  8. package/dist/{chunk-3G7ET4O5.js → chunk-INNOI6TG.js} +121 -94
  9. package/dist/chunk-INNOI6TG.js.map +1 -0
  10. package/dist/{chunk-T33QUD2Y.cjs → chunk-JRQNDXX7.cjs} +43 -43
  11. package/dist/{chunk-T33QUD2Y.cjs.map → chunk-JRQNDXX7.cjs.map} +1 -1
  12. package/dist/{chunk-AFRFF7XL.js → chunk-MIOMT2CB.js} +4 -4
  13. package/dist/{chunk-AFRFF7XL.js.map → chunk-MIOMT2CB.js.map} +1 -1
  14. package/dist/chunk-W7OUWVRA.cjs +106 -0
  15. package/dist/chunk-W7OUWVRA.cjs.map +1 -0
  16. package/dist/chunk-XLVBYXOU.js +100 -0
  17. package/dist/chunk-XLVBYXOU.js.map +1 -0
  18. package/dist/forma-runtime-csp.js +92 -6
  19. package/dist/forma-runtime.js +138 -12
  20. package/dist/formajs-runtime-hardened.global.js +92 -6
  21. package/dist/formajs-runtime-hardened.global.js.map +1 -1
  22. package/dist/formajs-runtime.global.js +138 -12
  23. package/dist/formajs-runtime.global.js.map +1 -1
  24. package/dist/formajs.global.js +192 -95
  25. package/dist/formajs.global.js.map +1 -1
  26. package/dist/http.cjs +11 -11
  27. package/dist/http.js +2 -2
  28. package/dist/index.cjs +66 -66
  29. package/dist/index.d.cts +11 -25
  30. package/dist/index.d.ts +11 -25
  31. package/dist/index.js +6 -6
  32. package/dist/{resource-DeEzxUz6.d.cts → resource-D6HfVgiA.d.cts} +7 -2
  33. package/dist/{resource-BHsgURy0.d.ts → resource-ljs2X5NM.d.ts} +7 -2
  34. package/dist/runtime-hardened.cjs +93 -5
  35. package/dist/runtime-hardened.cjs.map +1 -1
  36. package/dist/runtime-hardened.js +93 -5
  37. package/dist/runtime-hardened.js.map +1 -1
  38. package/dist/runtime.cjs +47 -31
  39. package/dist/runtime.cjs.map +1 -1
  40. package/dist/runtime.js +21 -5
  41. package/dist/runtime.js.map +1 -1
  42. package/dist/server.cjs +7 -7
  43. package/dist/server.d.cts +2 -2
  44. package/dist/server.d.ts +2 -2
  45. package/dist/server.js +2 -2
  46. package/dist/{signal-C9v4akyJ.d.cts → signal-CRBJYQ6B.d.cts} +0 -8
  47. package/dist/{signal-C9v4akyJ.d.ts → signal-CRBJYQ6B.d.ts} +0 -8
  48. package/dist/ssr/index.cjs +23 -42
  49. package/dist/ssr/index.cjs.map +1 -1
  50. package/dist/ssr/index.js +23 -42
  51. package/dist/ssr/index.js.map +1 -1
  52. package/dist/tc39-compat.cjs +3 -6
  53. package/dist/tc39-compat.cjs.map +1 -1
  54. package/dist/tc39-compat.d.cts +1 -1
  55. package/dist/tc39-compat.d.ts +1 -1
  56. package/dist/tc39-compat.js +1 -4
  57. package/dist/tc39-compat.js.map +1 -1
  58. package/package.json +2 -2
  59. package/dist/chunk-3G7ET4O5.js.map +0 -1
  60. package/dist/chunk-6FW5E54W.cjs.map +0 -1
  61. package/dist/chunk-HLM5BZZQ.js +0 -35
  62. package/dist/chunk-HLM5BZZQ.js.map +0 -1
  63. package/dist/chunk-QLPCVK7C.cjs +0 -38
  64. package/dist/chunk-QLPCVK7C.cjs.map +0 -1
@@ -348,6 +348,33 @@ var FormaRuntime = (() => {
348
348
  }
349
349
  return effectOper.bind(e);
350
350
  }
351
+ function trigger(fn) {
352
+ const sub = {
353
+ deps: void 0,
354
+ depsTail: void 0,
355
+ flags: 2
356
+ };
357
+ const prevSub = setActiveSub(sub);
358
+ try {
359
+ fn();
360
+ } finally {
361
+ activeSub = prevSub;
362
+ let link2 = sub.deps;
363
+ while (link2 !== void 0) {
364
+ const dep = link2.dep;
365
+ link2 = unlink(link2, sub);
366
+ const subs = dep.subs;
367
+ if (subs !== void 0) {
368
+ sub.flags = 0;
369
+ propagate(subs);
370
+ shallowPropagate(subs);
371
+ }
372
+ }
373
+ if (!batchDepth) {
374
+ flush();
375
+ }
376
+ }
377
+ }
351
378
  function updateComputed(c) {
352
379
  ++cycle;
353
380
  c.depsTail = void 0;
@@ -478,16 +505,41 @@ var FormaRuntime = (() => {
478
505
  }
479
506
  }
480
507
 
508
+ // src/reactive/dev.ts
509
+ function isDev() {
510
+ if (typeof process !== "undefined") {
511
+ return process.env?.NODE_ENV !== "production";
512
+ }
513
+ return typeof __FORMA_DEV__ !== "undefined" ? !!__FORMA_DEV__ : false;
514
+ }
515
+ var __DEV__ = isDev();
516
+ var _errorHandlers = /* @__PURE__ */ new Set();
517
+ function reportError(error, source) {
518
+ for (const handler of _errorHandlers) {
519
+ try {
520
+ handler(error, source ? { source } : {});
521
+ } catch {
522
+ }
523
+ }
524
+ if (isDev()) {
525
+ console.error(`[forma] ${source ?? "Unknown"} error:`, error);
526
+ }
527
+ }
528
+
481
529
  // src/reactive/signal.ts
530
+ var signalNames = /* @__PURE__ */ new WeakMap();
482
531
  function applySignalSet(s, v, equals) {
483
532
  if (typeof v !== "function") {
484
- if (equals) {
485
- const prevSub2 = setActiveSub(void 0);
486
- const prev2 = s();
487
- setActiveSub(prevSub2);
488
- if (equals(prev2, v)) return;
533
+ if (!equals) {
534
+ s(v);
535
+ return;
489
536
  }
537
+ const prevSub2 = setActiveSub(void 0);
538
+ const prev2 = s();
539
+ setActiveSub(prevSub2);
540
+ if (equals(prev2, v)) return;
490
541
  s(v);
542
+ if (Object.is(prev2, v)) forceNotify(s);
491
543
  return;
492
544
  }
493
545
  const prevSub = setActiveSub(void 0);
@@ -496,24 +548,33 @@ var FormaRuntime = (() => {
496
548
  const next = v(prev);
497
549
  if (equals && equals(prev, next)) return;
498
550
  s(next);
551
+ if (equals && Object.is(prev, next)) forceNotify(s);
552
+ }
553
+ function forceNotify(s) {
554
+ trigger(() => {
555
+ s();
556
+ });
499
557
  }
500
558
  function createSignal(initialValue, options) {
501
559
  const s = signal(initialValue);
502
560
  const getter = s;
561
+ if (__DEV__ && options?.name) {
562
+ signalNames.set(getter, options.name);
563
+ }
503
564
  const eq = options?.equals;
504
565
  const setter = (v) => applySignalSet(s, v, eq);
505
566
  return [getter, setter];
506
567
  }
507
568
 
508
569
  // src/reactive/root.ts
509
- var currentRoot = null;
570
+ var currentOwner = null;
510
571
  function registerDisposer(dispose) {
511
- if (currentRoot) {
512
- currentRoot.disposers.push(dispose);
572
+ if (currentOwner) {
573
+ currentOwner.disposers.push(dispose);
513
574
  }
514
575
  }
515
576
  function hasActiveRoot() {
516
- return currentRoot !== null;
577
+ return currentOwner !== null;
517
578
  }
518
579
 
519
580
  // src/reactive/effect.ts
@@ -529,8 +590,35 @@ var FormaRuntime = (() => {
529
590
  }
530
591
 
531
592
  // src/reactive/computed.ts
593
+ var ERR = /* @__PURE__ */ Symbol("formaComputedError");
594
+ function isErrBox(v) {
595
+ return typeof v === "object" && v !== null && ERR in v;
596
+ }
532
597
  function createComputed(fn) {
533
- return computed(fn);
598
+ let errored = false;
599
+ let error;
600
+ let lastGood;
601
+ const raw = computed(() => {
602
+ try {
603
+ const v = fn(lastGood);
604
+ errored = false;
605
+ error = void 0;
606
+ lastGood = v;
607
+ return v;
608
+ } catch (e) {
609
+ errored = true;
610
+ error = e;
611
+ reportError(e, "computed");
612
+ return { [ERR]: e };
613
+ }
614
+ });
615
+ const reader = () => {
616
+ const v = raw();
617
+ if (errored || isErrBox(v)) throw error;
618
+ return v;
619
+ };
620
+ Object.defineProperty(reader, "name", { value: raw.name, configurable: true });
621
+ return reader;
534
622
  }
535
623
 
536
624
  // src/reactive/batch.ts
@@ -1116,7 +1204,35 @@ var FormaRuntime = (() => {
1116
1204
  };
1117
1205
  }
1118
1206
 
1207
+ // src/security/url-safety.ts
1208
+ var URL_IGNORED_CHARS_RE = /[\u0000-\u0020\u007F-\u009F]/g;
1209
+ var DANGEROUS_SCHEME_RE = /^(?:javascript|vbscript|data:text\/html)/i;
1210
+ var URL_ATTRS = /* @__PURE__ */ new Set([
1211
+ "href",
1212
+ "src",
1213
+ "action",
1214
+ "formaction",
1215
+ "xlink:href",
1216
+ "poster",
1217
+ "background"
1218
+ ]);
1219
+ function isUrlAttr(name) {
1220
+ return URL_ATTRS.has(name.toLowerCase());
1221
+ }
1222
+ function isDangerousUrl(value2) {
1223
+ const normalized = value2.replace(URL_IGNORED_CHARS_RE, "");
1224
+ return DANGEROUS_SCHEME_RE.test(normalized);
1225
+ }
1226
+ function isEventHandlerAttr(name) {
1227
+ return /^on/i.test(name);
1228
+ }
1229
+
1119
1230
  // src/runtime.ts
1231
+ function isUnsafeAttrBinding(name, value2) {
1232
+ if (isEventHandlerAttr(name)) return true;
1233
+ if (isUrlAttr(name) && isDangerousUrl(value2)) return true;
1234
+ return false;
1235
+ }
1120
1236
  var _refetchRegistry = /* @__PURE__ */ new Map();
1121
1237
  function $refetch(id) {
1122
1238
  const fn = _refetchRegistry.get(id);
@@ -2120,7 +2236,12 @@ var FormaRuntime = (() => {
2120
2236
  if (attr.value.includes("{item")) {
2121
2237
  const compiled = compileTemplate(attr.value);
2122
2238
  entries.push({ attr: attr.name, compiled });
2123
- node.setAttribute(attr.name, evaluateCompiledTemplate(compiled, item));
2239
+ const value2 = evaluateCompiledTemplate(compiled, item);
2240
+ if (isUnsafeAttrBinding(attr.name, value2)) {
2241
+ node.removeAttribute(attr.name);
2242
+ } else {
2243
+ node.setAttribute(attr.name, value2);
2244
+ }
2124
2245
  }
2125
2246
  }
2126
2247
  if (entries.length > 0) {
@@ -2962,7 +3083,12 @@ var FormaRuntime = (() => {
2962
3083
  if (val == null || val === false) {
2963
3084
  el.removeAttribute(attrName);
2964
3085
  } else {
2965
- el.setAttribute(attrName, String(val));
3086
+ const str = String(val);
3087
+ if (isUnsafeAttrBinding(attrName, str)) {
3088
+ el.removeAttribute(attrName);
3089
+ } else {
3090
+ el.setAttribute(attrName, str);
3091
+ }
2966
3092
  }
2967
3093
  });
2968
3094
  disposers.push(dispose);