@jxsuite/runtime 4.0.0 → 4.0.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.
package/dist/runtime.js CHANGED
@@ -3675,6 +3675,7 @@ function renderMappedArrayInto(parentEl, arrayDef, state, options) {
3675
3675
  parentEl.append(anchor);
3676
3676
  const { items: itemsSrc, map: mapDef, filter: filterRef, sort: sortRef, key: keyRef } = arrayDef;
3677
3677
  const keyPointer = isRefObj(keyRef) ? keyRef.$ref : null;
3678
+ const instancePath = _instancePath;
3678
3679
  let warned = false;
3679
3680
  const warnOnce = (message) => {
3680
3681
  if (!warned) {
@@ -3762,7 +3763,7 @@ function renderMappedArrayInto(parentEl, arrayDef, state, options) {
3762
3763
  }
3763
3764
  pauseTracking();
3764
3765
  try {
3765
- reconcile(list, keys);
3766
+ underInstancePath(reexpand(instancePath), () => reconcile(list, keys));
3766
3767
  } finally {
3767
3768
  resetTracking();
3768
3769
  }
@@ -3826,6 +3827,7 @@ function resolveTagName(tagName, scope) {
3826
3827
  function renderSwitch(def, state, options) {
3827
3828
  const path = options?._path ?? [];
3828
3829
  const container = document.createElement(resolveTagName(def.tagName, state));
3830
+ const instancePath = _instancePath;
3829
3831
  if (options?.onNodeCreated) {
3830
3832
  options.onNodeCreated(container, path, def, state);
3831
3833
  }
@@ -3873,13 +3875,13 @@ function renderSwitch(def, state, options) {
3873
3875
  return;
3874
3876
  }
3875
3877
  container.replaceChildren();
3876
- scope.run(() => container.append(renderNode(doc, childScope, childOpts)));
3878
+ underInstancePath(reexpand(instancePath), () => scope.run(() => container.append(renderNode(doc, childScope, childOpts))));
3877
3879
  }).catch((error) => console.error("Jx $switch: failed to load external case", caseDef.$ref, error));
3878
3880
  return;
3879
3881
  }
3880
3882
  pauseTracking();
3881
3883
  try {
3882
- scope.run(() => container.append(renderNode(caseDef, state, childOpts)));
3884
+ underInstancePath(reexpand(instancePath), () => scope.run(() => container.append(renderNode(caseDef, state, childOpts))));
3883
3885
  } finally {
3884
3886
  resetTracking();
3885
3887
  }
@@ -4583,6 +4585,65 @@ function injectHead(entries, _base) {
4583
4585
  document.head.append(el);
4584
4586
  }
4585
4587
  }
4588
+ var MAX_COMPONENT_NESTING = 32;
4589
+ var ROOT_INSTANCE_PATH = { expansion: 0, frames: [] };
4590
+ var _instancePath = ROOT_INSTANCE_PATH;
4591
+ function underInstancePath(path, fn) {
4592
+ const was = _instancePath;
4593
+ _instancePath = path;
4594
+ try {
4595
+ return fn();
4596
+ } finally {
4597
+ _instancePath = was;
4598
+ }
4599
+ }
4600
+ function reexpand(path) {
4601
+ return { expansion: path.frames.length, frames: path.frames };
4602
+ }
4603
+ function samePropValue(a, b) {
4604
+ if (Object.is(a, b)) {
4605
+ return true;
4606
+ }
4607
+ if (!isPlainData(a) || !isPlainData(b)) {
4608
+ return false;
4609
+ }
4610
+ try {
4611
+ return JSON.stringify(a) === JSON.stringify(b);
4612
+ } catch {
4613
+ return false;
4614
+ }
4615
+ }
4616
+ function isPlainData(value) {
4617
+ if (typeof value !== "object" || value === null) {
4618
+ return false;
4619
+ }
4620
+ const raw = toRaw(value);
4621
+ if (Array.isArray(raw)) {
4622
+ return true;
4623
+ }
4624
+ const proto = Object.getPrototypeOf(raw);
4625
+ return proto === Object.prototype || proto === null;
4626
+ }
4627
+ function sameFrame(a, b) {
4628
+ if (a.tag !== b.tag) {
4629
+ return false;
4630
+ }
4631
+ const keys = Object.keys(a.props);
4632
+ if (keys.length !== Object.keys(b.props).length) {
4633
+ return false;
4634
+ }
4635
+ return keys.every((key) => Object.hasOwn(b.props, key) && samePropValue(a.props[key], b.props[key]));
4636
+ }
4637
+ function extendInstancePath(path, frame) {
4638
+ const chain = [...path.frames.map((f) => f.tag), frame.tag].join(" → ");
4639
+ if (path.frames.slice(path.expansion).some((f) => sameFrame(f, frame))) {
4640
+ throw new Error(`Component <${frame.tag}> renders itself: ${chain}. A component cannot appear inside its own ` + `definition with the same props — the expansion would never end.`);
4641
+ }
4642
+ if (path.frames.length >= MAX_COMPONENT_NESTING) {
4643
+ throw new Error(`Component nesting exceeds ${MAX_COMPONENT_NESTING} levels: ${chain}. A component that renders itself with changing props needs a case that stops.`);
4644
+ }
4645
+ return { expansion: path.expansion, frames: [...path.frames, frame] };
4646
+ }
4586
4647
  var _definedSources = new Set;
4587
4648
  async function defineElement(source, baseUrl) {
4588
4649
  let base = baseUrl;
@@ -4625,6 +4686,8 @@ async function defineElement(source, baseUrl) {
4625
4686
  return;
4626
4687
  }
4627
4688
  this._jxInitialized = true;
4689
+ const enclosingPath = _instancePath;
4690
+ const supplied = {};
4628
4691
  const live = _elementDefs.get(tagName) ?? { base: initialBase, doc: initialDef };
4629
4692
  const def = live.doc;
4630
4693
  const defBase = live.base;
@@ -4632,6 +4695,7 @@ async function defineElement(source, baseUrl) {
4632
4695
  for (const attr of observedAttrs) {
4633
4696
  if (this.hasAttribute(attr)) {
4634
4697
  absorbAttribute(state, attr, this.getAttribute(attr));
4698
+ supplied[attr] = this.getAttribute(attr);
4635
4699
  }
4636
4700
  }
4637
4701
  const propsAttr = this.dataset.jxProps;
@@ -4644,6 +4708,7 @@ async function defineElement(source, baseUrl) {
4644
4708
  }
4645
4709
  if (key in (def.state ?? {})) {
4646
4710
  state[key] = val;
4711
+ supplied[key] = val;
4647
4712
  }
4648
4713
  }
4649
4714
  } catch {}
@@ -4658,6 +4723,7 @@ async function defineElement(source, baseUrl) {
4658
4723
  }
4659
4724
  if (key in (def.state ?? {})) {
4660
4725
  state[key] = this.getAttribute(name);
4726
+ supplied[key] = this.getAttribute(name);
4661
4727
  this.removeAttribute(name);
4662
4728
  }
4663
4729
  }
@@ -4667,8 +4733,26 @@ async function defineElement(source, baseUrl) {
4667
4733
  }
4668
4734
  if (key in this && this[key] !== undefined && instanceSupplies(this, key)) {
4669
4735
  state[key] = this[key];
4736
+ supplied[key] = this[key];
4670
4737
  }
4671
4738
  }
4739
+ let ownPath;
4740
+ try {
4741
+ ownPath = extendInstancePath(enclosingPath, { props: supplied, tag: tagName });
4742
+ } catch (error) {
4743
+ this.replaceChildren();
4744
+ if (!this.isConnected) {
4745
+ return;
4746
+ }
4747
+ console.error(`Jx: <${tagName}> was not rendered:`, error);
4748
+ this.dispatchEvent(new ErrorEvent("jx-error", {
4749
+ bubbles: true,
4750
+ composed: true,
4751
+ error,
4752
+ message: error instanceof Error ? error.message : String(error)
4753
+ }));
4754
+ return;
4755
+ }
4672
4756
  for (const key of Object.keys(def.state ?? {})) {
4673
4757
  if (isPrivateStateKey(key)) {
4674
4758
  continue;
@@ -4698,9 +4782,11 @@ async function defineElement(source, baseUrl) {
4698
4782
  const wasInside = _canvasInsideStampedHost;
4699
4783
  _canvasInsideStampedHost ||= this.dataset.jxPath !== undefined;
4700
4784
  try {
4701
- for (const childDef of children) {
4702
- this.append(renderNode(childDef, state));
4703
- }
4785
+ underInstancePath(ownPath, () => {
4786
+ for (const childDef of children) {
4787
+ this.append(renderNode(childDef, state));
4788
+ }
4789
+ });
4704
4790
  } finally {
4705
4791
  _canvasInsideStampedHost = wasInside;
4706
4792
  }
@@ -4801,6 +4887,7 @@ export {
4801
4887
  COLOR_SCHEME_ATTR,
4802
4888
  COLOR_SCHEME_STORAGE_KEY,
4803
4889
  Jx,
4890
+ MAX_COMPONENT_NESTING,
4804
4891
  RESERVED_KEYS,
4805
4892
  SUPPORTED_SCHEMA_VERSION,
4806
4893
  _resetPrivatePropWarnings,
@@ -4859,5 +4946,5 @@ export {
4859
4946
  transposeCanvasUnits
4860
4947
  };
4861
4948
 
4862
- //# debugId=A89AF23A7F8742C664756E2164756E21
4949
+ //# debugId=52C255A4DA099CA964756E2164756E21
4863
4950
  //# sourceMappingURL=runtime.js.map