solid-js 1.6.11 → 1.6.13

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2016-2019 Ryan Carniato
3
+ Copyright (c) 2016-2023 Ryan Carniato
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/dev.cjs CHANGED
@@ -676,7 +676,7 @@ function writeSignal(node, value, isComp) {
676
676
  }
677
677
  if (Updates.length > 10e5) {
678
678
  Updates = [];
679
- if ("_SOLID_DEV_") throw new Error("Potential Infinite Loop Detected.");
679
+ if (true) throw new Error("Potential Infinite Loop Detected.");
680
680
  throw new Error();
681
681
  }
682
682
  }, false);
@@ -721,7 +721,8 @@ function runComputation(node, value, time) {
721
721
  node.owned = null;
722
722
  }
723
723
  }
724
- handleError(err);
724
+ node.updatedAt = time + 1;
725
+ return handleError(err);
725
726
  }
726
727
  if (!node.updatedAt || node.updatedAt <= time) {
727
728
  if (node.updatedAt != null && "observers" in node) {
@@ -901,7 +902,7 @@ function lookUpstream(node, ignore) {
901
902
  const source = node.sources[i];
902
903
  if (source.sources) {
903
904
  if (!runningTransition && source.state === STALE || runningTransition && source.tState === STALE) {
904
- if (source !== ignore) runTop(source);
905
+ if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
905
906
  } else if (!runningTransition && source.state === PENDING || runningTransition && source.tState === PENDING) lookUpstream(source, ignore);
906
907
  }
907
908
  }
@@ -1413,7 +1414,7 @@ function lazy(fn) {
1413
1414
  }
1414
1415
  let Comp;
1415
1416
  return createMemo(() => (Comp = comp()) && untrack(() => {
1416
- if ("_SOLID_DEV_") Object.assign(Comp, {
1417
+ if (true) Object.assign(Comp, {
1417
1418
  [$DEVCOMP]: true
1418
1419
  });
1419
1420
  if (!ctx) return Comp(props);
package/dist/dev.js CHANGED
@@ -674,7 +674,7 @@ function writeSignal(node, value, isComp) {
674
674
  }
675
675
  if (Updates.length > 10e5) {
676
676
  Updates = [];
677
- if ("_SOLID_DEV_") throw new Error("Potential Infinite Loop Detected.");
677
+ if (true) throw new Error("Potential Infinite Loop Detected.");
678
678
  throw new Error();
679
679
  }
680
680
  }, false);
@@ -719,7 +719,8 @@ function runComputation(node, value, time) {
719
719
  node.owned = null;
720
720
  }
721
721
  }
722
- handleError(err);
722
+ node.updatedAt = time + 1;
723
+ return handleError(err);
723
724
  }
724
725
  if (!node.updatedAt || node.updatedAt <= time) {
725
726
  if (node.updatedAt != null && "observers" in node) {
@@ -899,7 +900,7 @@ function lookUpstream(node, ignore) {
899
900
  const source = node.sources[i];
900
901
  if (source.sources) {
901
902
  if (!runningTransition && source.state === STALE || runningTransition && source.tState === STALE) {
902
- if (source !== ignore) runTop(source);
903
+ if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
903
904
  } else if (!runningTransition && source.state === PENDING || runningTransition && source.tState === PENDING) lookUpstream(source, ignore);
904
905
  }
905
906
  }
@@ -1411,7 +1412,7 @@ function lazy(fn) {
1411
1412
  }
1412
1413
  let Comp;
1413
1414
  return createMemo(() => (Comp = comp()) && untrack(() => {
1414
- if ("_SOLID_DEV_") Object.assign(Comp, {
1415
+ if (true) Object.assign(Comp, {
1415
1416
  [$DEVCOMP]: true
1416
1417
  });
1417
1418
  if (!ctx) return Comp(props);
package/dist/server.cjs CHANGED
@@ -6,7 +6,6 @@ const $TRACK = Symbol("solid-track");
6
6
  const $DEVCOMP = Symbol("solid-dev-component");
7
7
  const DEV = {};
8
8
  const ERROR = Symbol("error");
9
- const BRANCH = Symbol("branch");
10
9
  function castError(err) {
11
10
  if (err instanceof Error || typeof err === "string") return err;
12
11
  return new Error("Unknown error");
@@ -19,19 +18,35 @@ function handleError(err) {
19
18
  }
20
19
  const UNOWNED = {
21
20
  context: null,
22
- owner: null
21
+ owner: null,
22
+ owned: null,
23
+ cleanups: null
23
24
  };
24
25
  let Owner = null;
26
+ function createOwner() {
27
+ const o = {
28
+ owner: Owner,
29
+ context: null,
30
+ owned: null,
31
+ cleanups: null
32
+ };
33
+ if (Owner) {
34
+ if (!Owner.owned) Owner.owned = [o];else Owner.owned.push(o);
35
+ }
36
+ return o;
37
+ }
25
38
  function createRoot(fn, detachedOwner) {
26
39
  const owner = Owner,
27
40
  root = fn.length === 0 ? UNOWNED : {
28
41
  context: null,
29
- owner: detachedOwner === undefined ? owner : detachedOwner
42
+ owner: detachedOwner === undefined ? owner : detachedOwner,
43
+ owned: null,
44
+ cleanups: null
30
45
  };
31
46
  Owner = root;
32
47
  let result;
33
48
  try {
34
- result = fn(() => {});
49
+ result = fn(fn.length === 0 ? () => {} : () => cleanNode(root));
35
50
  } catch (err) {
36
51
  handleError(err);
37
52
  } finally {
@@ -45,10 +60,7 @@ function createSignal(value, options) {
45
60
  }];
46
61
  }
47
62
  function createComputed(fn, value) {
48
- Owner = {
49
- owner: Owner,
50
- context: null
51
- };
63
+ Owner = createOwner();
52
64
  try {
53
65
  fn(value);
54
66
  } catch (err) {
@@ -65,10 +77,7 @@ function createReaction(fn) {
65
77
  };
66
78
  }
67
79
  function createMemo(fn, value) {
68
- Owner = {
69
- owner: Owner,
70
- context: null
71
- };
80
+ Owner = createOwner();
72
81
  let v;
73
82
  try {
74
83
  v = fn(value);
@@ -104,16 +113,19 @@ function on(deps, fn, options = {}) {
104
113
  }
105
114
  function onMount(fn) {}
106
115
  function onCleanup(fn) {
107
- let node;
108
- if (Owner && (node = lookup(Owner, BRANCH))) {
109
- if (!node.cleanups) node.cleanups = [fn];else node.cleanups.push(fn);
116
+ if (Owner) {
117
+ if (!Owner.cleanups) Owner.cleanups = [fn];else Owner.cleanups.push(fn);
110
118
  }
111
119
  return fn;
112
120
  }
113
121
  function cleanNode(node) {
122
+ if (node.owned) {
123
+ for (let i = 0; i < node.owned.length; i++) cleanNode(node.owned[i]);
124
+ node.owned = null;
125
+ }
114
126
  if (node.cleanups) {
115
127
  for (let i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
116
- node.cleanups = undefined;
128
+ node.cleanups = null;
117
129
  }
118
130
  }
119
131
  function onError(fn) {
@@ -383,11 +395,8 @@ function ErrorBoundary(props) {
383
395
  !sync && ctx.replace("e" + id, displayFallback);
384
396
  sync = true;
385
397
  });
386
- onCleanup(() => cleanNode(clean));
387
398
  createMemo(() => {
388
- Owner.context = {
389
- [BRANCH]: clean = {}
390
- };
399
+ clean = Owner;
391
400
  return res = props.children;
392
401
  });
393
402
  if (error) return displayFallback();
@@ -437,7 +446,7 @@ function createResource(source, fetcher, options = {}) {
437
446
  };
438
447
  read.loading = false;
439
448
  read.error = undefined;
440
- read.state = "initialValue" in options ? "resolved" : "unresolved";
449
+ read.state = "initialValue" in options ? "ready" : "unresolved";
441
450
  Object.defineProperty(read, "latest", {
442
451
  get() {
443
452
  return read();
@@ -470,7 +479,7 @@ function createResource(source, fetcher, options = {}) {
470
479
  if (ctx.writeResource) ctx.writeResource(id, p, undefined, options.deferStream);
471
480
  return p.then(res => {
472
481
  read.loading = false;
473
- read.state = "resolved";
482
+ read.state = "ready";
474
483
  ctx.resources[id].data = res;
475
484
  p = null;
476
485
  notifySuspense(contexts);
@@ -560,15 +569,9 @@ function SuspenseList(props) {
560
569
  }
561
570
  function Suspense(props) {
562
571
  let done;
563
- let clean;
564
572
  const ctx = sharedConfig.context;
565
573
  const id = ctx.id + ctx.count;
566
- const o = Owner;
567
- if (o) {
568
- if (o.context) o.context[BRANCH] = clean = {};else o.context = {
569
- [BRANCH]: clean = {}
570
- };
571
- }
574
+ const o = createOwner();
572
575
  const value = ctx.suspense[id] || (ctx.suspense[id] = {
573
576
  resources: new Map(),
574
577
  completed: () => {
@@ -583,11 +586,11 @@ function Suspense(props) {
583
586
  ...ctx,
584
587
  count: 0
585
588
  });
589
+ o && cleanNode(o);
586
590
  return runWithOwner(o, () => {
587
591
  return createComponent(SuspenseContext.Provider, {
588
592
  value,
589
593
  get children() {
590
- clean && cleanNode(clean);
591
594
  return props.children;
592
595
  }
593
596
  });
@@ -607,7 +610,7 @@ function Suspense(props) {
607
610
  setHydrateContext({
608
611
  ...ctx,
609
612
  count: 0,
610
- id: ctx.id + "0.f",
613
+ id: ctx.id + "0-f",
611
614
  noHydrate: true
612
615
  });
613
616
  const res = {
@@ -619,7 +622,7 @@ function Suspense(props) {
619
622
  setHydrateContext({
620
623
  ...ctx,
621
624
  count: 0,
622
- id: ctx.id + "0.f"
625
+ id: ctx.id + "0-f"
623
626
  });
624
627
  ctx.writeResource(id, "$$f");
625
628
  return props.fallback;
package/dist/server.js CHANGED
@@ -4,7 +4,6 @@ const $TRACK = Symbol("solid-track");
4
4
  const $DEVCOMP = Symbol("solid-dev-component");
5
5
  const DEV = {};
6
6
  const ERROR = Symbol("error");
7
- const BRANCH = Symbol("branch");
8
7
  function castError(err) {
9
8
  if (err instanceof Error || typeof err === "string") return err;
10
9
  return new Error("Unknown error");
@@ -17,19 +16,35 @@ function handleError(err) {
17
16
  }
18
17
  const UNOWNED = {
19
18
  context: null,
20
- owner: null
19
+ owner: null,
20
+ owned: null,
21
+ cleanups: null
21
22
  };
22
23
  let Owner = null;
24
+ function createOwner() {
25
+ const o = {
26
+ owner: Owner,
27
+ context: null,
28
+ owned: null,
29
+ cleanups: null
30
+ };
31
+ if (Owner) {
32
+ if (!Owner.owned) Owner.owned = [o];else Owner.owned.push(o);
33
+ }
34
+ return o;
35
+ }
23
36
  function createRoot(fn, detachedOwner) {
24
37
  const owner = Owner,
25
38
  root = fn.length === 0 ? UNOWNED : {
26
39
  context: null,
27
- owner: detachedOwner === undefined ? owner : detachedOwner
40
+ owner: detachedOwner === undefined ? owner : detachedOwner,
41
+ owned: null,
42
+ cleanups: null
28
43
  };
29
44
  Owner = root;
30
45
  let result;
31
46
  try {
32
- result = fn(() => {});
47
+ result = fn(fn.length === 0 ? () => {} : () => cleanNode(root));
33
48
  } catch (err) {
34
49
  handleError(err);
35
50
  } finally {
@@ -43,10 +58,7 @@ function createSignal(value, options) {
43
58
  }];
44
59
  }
45
60
  function createComputed(fn, value) {
46
- Owner = {
47
- owner: Owner,
48
- context: null
49
- };
61
+ Owner = createOwner();
50
62
  try {
51
63
  fn(value);
52
64
  } catch (err) {
@@ -63,10 +75,7 @@ function createReaction(fn) {
63
75
  };
64
76
  }
65
77
  function createMemo(fn, value) {
66
- Owner = {
67
- owner: Owner,
68
- context: null
69
- };
78
+ Owner = createOwner();
70
79
  let v;
71
80
  try {
72
81
  v = fn(value);
@@ -102,16 +111,19 @@ function on(deps, fn, options = {}) {
102
111
  }
103
112
  function onMount(fn) {}
104
113
  function onCleanup(fn) {
105
- let node;
106
- if (Owner && (node = lookup(Owner, BRANCH))) {
107
- if (!node.cleanups) node.cleanups = [fn];else node.cleanups.push(fn);
114
+ if (Owner) {
115
+ if (!Owner.cleanups) Owner.cleanups = [fn];else Owner.cleanups.push(fn);
108
116
  }
109
117
  return fn;
110
118
  }
111
119
  function cleanNode(node) {
120
+ if (node.owned) {
121
+ for (let i = 0; i < node.owned.length; i++) cleanNode(node.owned[i]);
122
+ node.owned = null;
123
+ }
112
124
  if (node.cleanups) {
113
125
  for (let i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
114
- node.cleanups = undefined;
126
+ node.cleanups = null;
115
127
  }
116
128
  }
117
129
  function onError(fn) {
@@ -381,11 +393,8 @@ function ErrorBoundary(props) {
381
393
  !sync && ctx.replace("e" + id, displayFallback);
382
394
  sync = true;
383
395
  });
384
- onCleanup(() => cleanNode(clean));
385
396
  createMemo(() => {
386
- Owner.context = {
387
- [BRANCH]: clean = {}
388
- };
397
+ clean = Owner;
389
398
  return res = props.children;
390
399
  });
391
400
  if (error) return displayFallback();
@@ -435,7 +444,7 @@ function createResource(source, fetcher, options = {}) {
435
444
  };
436
445
  read.loading = false;
437
446
  read.error = undefined;
438
- read.state = "initialValue" in options ? "resolved" : "unresolved";
447
+ read.state = "initialValue" in options ? "ready" : "unresolved";
439
448
  Object.defineProperty(read, "latest", {
440
449
  get() {
441
450
  return read();
@@ -468,7 +477,7 @@ function createResource(source, fetcher, options = {}) {
468
477
  if (ctx.writeResource) ctx.writeResource(id, p, undefined, options.deferStream);
469
478
  return p.then(res => {
470
479
  read.loading = false;
471
- read.state = "resolved";
480
+ read.state = "ready";
472
481
  ctx.resources[id].data = res;
473
482
  p = null;
474
483
  notifySuspense(contexts);
@@ -558,15 +567,9 @@ function SuspenseList(props) {
558
567
  }
559
568
  function Suspense(props) {
560
569
  let done;
561
- let clean;
562
570
  const ctx = sharedConfig.context;
563
571
  const id = ctx.id + ctx.count;
564
- const o = Owner;
565
- if (o) {
566
- if (o.context) o.context[BRANCH] = clean = {};else o.context = {
567
- [BRANCH]: clean = {}
568
- };
569
- }
572
+ const o = createOwner();
570
573
  const value = ctx.suspense[id] || (ctx.suspense[id] = {
571
574
  resources: new Map(),
572
575
  completed: () => {
@@ -581,11 +584,11 @@ function Suspense(props) {
581
584
  ...ctx,
582
585
  count: 0
583
586
  });
587
+ o && cleanNode(o);
584
588
  return runWithOwner(o, () => {
585
589
  return createComponent(SuspenseContext.Provider, {
586
590
  value,
587
591
  get children() {
588
- clean && cleanNode(clean);
589
592
  return props.children;
590
593
  }
591
594
  });
@@ -605,7 +608,7 @@ function Suspense(props) {
605
608
  setHydrateContext({
606
609
  ...ctx,
607
610
  count: 0,
608
- id: ctx.id + "0.f",
611
+ id: ctx.id + "0-f",
609
612
  noHydrate: true
610
613
  });
611
614
  const res = {
@@ -617,7 +620,7 @@ function Suspense(props) {
617
620
  setHydrateContext({
618
621
  ...ctx,
619
622
  count: 0,
620
- id: ctx.id + "0.f"
623
+ id: ctx.id + "0-f"
621
624
  });
622
625
  ctx.writeResource(id, "$$f");
623
626
  return props.fallback;
package/dist/solid.cjs CHANGED
@@ -652,7 +652,8 @@ function runComputation(node, value, time) {
652
652
  node.owned = null;
653
653
  }
654
654
  }
655
- handleError(err);
655
+ node.updatedAt = time + 1;
656
+ return handleError(err);
656
657
  }
657
658
  if (!node.updatedAt || node.updatedAt <= time) {
658
659
  if (node.updatedAt != null && "observers" in node) {
@@ -831,7 +832,7 @@ function lookUpstream(node, ignore) {
831
832
  const source = node.sources[i];
832
833
  if (source.sources) {
833
834
  if (!runningTransition && source.state === STALE || runningTransition && source.tState === STALE) {
834
- if (source !== ignore) runTop(source);
835
+ if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
835
836
  } else if (!runningTransition && source.state === PENDING || runningTransition && source.tState === PENDING) lookUpstream(source, ignore);
836
837
  }
837
838
  }
package/dist/solid.js CHANGED
@@ -650,7 +650,8 @@ function runComputation(node, value, time) {
650
650
  node.owned = null;
651
651
  }
652
652
  }
653
- handleError(err);
653
+ node.updatedAt = time + 1;
654
+ return handleError(err);
654
655
  }
655
656
  if (!node.updatedAt || node.updatedAt <= time) {
656
657
  if (node.updatedAt != null && "observers" in node) {
@@ -829,7 +830,7 @@ function lookUpstream(node, ignore) {
829
830
  const source = node.sources[i];
830
831
  if (source.sources) {
831
832
  if (!runningTransition && source.state === STALE || runningTransition && source.tState === STALE) {
832
- if (source !== ignore) runTop(source);
833
+ if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
833
834
  } else if (!runningTransition && source.state === PENDING || runningTransition && source.tState === PENDING) lookUpstream(source, ignore);
834
835
  }
835
836
  }
@@ -1291,6 +1291,7 @@ export namespace JSX {
1291
1291
  gradientUnits?: FunctionMaybe<SVGUnits>;
1292
1292
  gradientTransform?: FunctionMaybe<string>;
1293
1293
  spreadMethod?: FunctionMaybe<"pad" | "reflect" | "repeat">;
1294
+ href?: FunctionMaybe<string>
1294
1295
  }
1295
1296
  interface GraphicsElementSVGAttributes<T>
1296
1297
  extends CoreSVGAttributes<T>,
@@ -300,7 +300,7 @@ function createHTML(r, {
300
300
  continue;
301
301
  }
302
302
  parseNode(child, childOptions);
303
- i++;
303
+ if (!childOptions.multi && child.type === "comment" && child.content === "#") node.children.splice(i, 1);else i++;
304
304
  }
305
305
  options.counter = childOptions.counter;
306
306
  options.templateId = childOptions.templateId;
@@ -390,8 +390,12 @@ function createHTML(r, {
390
390
  options.templateId = childOptions.templateId;
391
391
  } else if (child.type === "text") {
392
392
  parts.push(`"${child.content}"`);
393
- } else if (child.type === "comment" && child.content === "#") {
394
- parts.push(`exprs[${options.counter++}]`);
393
+ } else if (child.type === "comment") {
394
+ if (child.content === "#") parts.push(`exprs[${options.counter++}]`);else if (child.content) {
395
+ for (let i = 0; i < child.content.split("###").length - 1; i++) {
396
+ parts.push(`exprs[${options.counter++}]`);
397
+ }
398
+ }
395
399
  }
396
400
  });
397
401
  options.exprs.push(`return [${parts.join(", \n")}]`);
package/html/dist/html.js CHANGED
@@ -298,7 +298,7 @@ function createHTML(r, {
298
298
  continue;
299
299
  }
300
300
  parseNode(child, childOptions);
301
- i++;
301
+ if (!childOptions.multi && child.type === "comment" && child.content === "#") node.children.splice(i, 1);else i++;
302
302
  }
303
303
  options.counter = childOptions.counter;
304
304
  options.templateId = childOptions.templateId;
@@ -388,8 +388,12 @@ function createHTML(r, {
388
388
  options.templateId = childOptions.templateId;
389
389
  } else if (child.type === "text") {
390
390
  parts.push(`"${child.content}"`);
391
- } else if (child.type === "comment" && child.content === "#") {
392
- parts.push(`exprs[${options.counter++}]`);
391
+ } else if (child.type === "comment") {
392
+ if (child.content === "#") parts.push(`exprs[${options.counter++}]`);else if (child.content) {
393
+ for (let i = 0; i < child.content.split("###").length - 1; i++) {
394
+ parts.push(`exprs[${options.counter++}]`);
395
+ }
396
+ }
393
397
  }
394
398
  });
395
399
  options.exprs.push(`return [${parts.join(", \n")}]`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "solid-js",
3
3
  "description": "A declarative JavaScript library for building user interfaces.",
4
- "version": "1.6.11",
4
+ "version": "1.6.13",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -320,11 +320,8 @@ const $ROOT = Symbol("store-root");
320
320
  function applyState(target, parent, property, merge, key) {
321
321
  const previous = parent[property];
322
322
  if (target === previous) return;
323
- if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
324
- if (target !== previous) {
325
- if (property === $ROOT) return target;
326
- setProperty(parent, property, target);
327
- }
323
+ if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key])) {
324
+ setProperty(parent, property, target);
328
325
  return;
329
326
  }
330
327
  if (Array.isArray(target)) {
package/store/dist/dev.js CHANGED
@@ -318,11 +318,8 @@ const $ROOT = Symbol("store-root");
318
318
  function applyState(target, parent, property, merge, key) {
319
319
  const previous = parent[property];
320
320
  if (target === previous) return;
321
- if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
322
- if (target !== previous) {
323
- if (property === $ROOT) return target;
324
- setProperty(parent, property, target);
325
- }
321
+ if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key])) {
322
+ setProperty(parent, property, target);
326
323
  return;
327
324
  }
328
325
  if (Array.isArray(target)) {
@@ -297,11 +297,8 @@ const $ROOT = Symbol("store-root");
297
297
  function applyState(target, parent, property, merge, key) {
298
298
  const previous = parent[property];
299
299
  if (target === previous) return;
300
- if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
301
- if (target !== previous) {
302
- if (property === $ROOT) return target;
303
- setProperty(parent, property, target);
304
- }
300
+ if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key])) {
301
+ setProperty(parent, property, target);
305
302
  return;
306
303
  }
307
304
  if (Array.isArray(target)) {
@@ -295,11 +295,8 @@ const $ROOT = Symbol("store-root");
295
295
  function applyState(target, parent, property, merge, key) {
296
296
  const previous = parent[property];
297
297
  if (target === previous) return;
298
- if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
299
- if (target !== previous) {
300
- if (property === $ROOT) return target;
301
- setProperty(parent, property, target);
302
- }
298
+ if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key])) {
299
+ setProperty(parent, property, target);
303
300
  return;
304
301
  }
305
302
  if (Array.isArray(target)) {
@@ -68,7 +68,9 @@ export type ArrayFilterFn<T> = (item: T, index: number) => boolean;
68
68
  export type StoreSetter<T, U extends PropertyKey[] = []> = T | CustomPartial<T> | ((prevState: T, traversed: U) => T | CustomPartial<T>);
69
69
  export type Part<T, K extends KeyOf<T> = KeyOf<T>> = K | ([K] extends [never] ? never : readonly K[]) | ([T] extends [readonly unknown[]] ? ArrayFilterFn<T[number]> | StorePathRange : never);
70
70
  type W<T> = Exclude<T, NotWrappable>;
71
- type KeyOf<T> = number extends keyof T ? 0 extends 1 & T ? keyof T : [T] extends [readonly unknown[]] ? number : [T] extends [never] ? never : keyof T : keyof T;
71
+ type KeyOf<T> = number extends keyof T ? 0 extends 1 & T ? keyof T : [T] extends [never] ? never : [
72
+ T
73
+ ] extends [readonly unknown[]] ? number : keyof T : keyof T;
72
74
  type MutableKeyOf<T> = KeyOf<T> & keyof PickMutable<T>;
73
75
  type Rest<T, U extends PropertyKey[], K extends KeyOf<T> = KeyOf<T>> = [T] extends [never] ? never : K extends MutableKeyOf<T> ? [Part<T, K>, ...RestSetterOrContinue<T[K], [K, ...U]>] : K extends KeyOf<T> ? [Part<T, K>, ...RestContinue<T[K], [K, ...U]>] : never;
74
76
  type RestContinue<T, U extends PropertyKey[]> = 0 extends 1 & T ? [...Part<any>[], StoreSetter<any, PropertyKey[]>] : Rest<W<T>, U>;
package/types/jsx.d.ts CHANGED
@@ -1301,6 +1301,7 @@ export namespace JSX {
1301
1301
  gradientUnits?: SVGUnits;
1302
1302
  gradientTransform?: string;
1303
1303
  spreadMethod?: "pad" | "reflect" | "repeat";
1304
+ href?: string
1304
1305
  }
1305
1306
  interface GraphicsElementSVGAttributes<T>
1306
1307
  extends CoreSVGAttributes<T>,
@@ -1,4 +1,27 @@
1
1
  import { Accessor } from "./signal.js";
2
+ /**
3
+ The MIT License (MIT)
4
+
5
+ Copyright (c) 2017 Adam Haile
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
2
25
  /**
3
26
  * reactively transforms an array with a callback function - underlying helper for the `<For>` control flow
4
27
  *
@@ -1,3 +1,26 @@
1
+ /**
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2017 Adam Haile
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ */
1
24
  import { requestCallback } from "./scheduler.js";
2
25
  import type { JSX } from "../jsx.js";
3
26
  import type { FlowComponent } from "../render/index.js";
@@ -6,13 +6,15 @@ export declare const DEV: {};
6
6
  export type Accessor<T> = () => T;
7
7
  export type Setter<T> = undefined extends T ? <U extends T>(value?: (U extends Function ? never : U) | ((prev?: T) => U)) => U : <U extends T>(value: (U extends Function ? never : U) | ((prev: T) => U)) => U;
8
8
  export type Signal<T> = [get: Accessor<T>, set: Setter<T>];
9
- export declare const BRANCH: unique symbol;
10
9
  export declare function castError(err: any): string | Error;
11
10
  export declare let Owner: Owner | null;
12
11
  interface Owner {
13
12
  owner: Owner | null;
14
13
  context: any | null;
14
+ owned: Owner[] | null;
15
+ cleanups: (() => void)[] | null;
15
16
  }
17
+ export declare function createOwner(): Owner;
16
18
  export declare function createRoot<T>(fn: (dispose: () => void) => T, detachedOwner?: typeof Owner): T;
17
19
  export declare function createSignal<T>(value: T, options?: {
18
20
  equals?: false | ((prev: T, next: T) => boolean);
@@ -32,9 +34,7 @@ export declare function on<T, U>(deps: Array<() => T> | (() => T), fn: (value: A
32
34
  }): (prev?: U) => U | undefined;
33
35
  export declare function onMount(fn: () => void): void;
34
36
  export declare function onCleanup(fn: () => void): () => void;
35
- export declare function cleanNode(node: {
36
- cleanups?: Function[] | null;
37
- }): void;
37
+ export declare function cleanNode(node: Owner): void;
38
38
  export declare function onError(fn: (err: any) => void): void;
39
39
  export declare function getListener(): null;
40
40
  export interface Context<T> {
package/web/dist/dev.cjs CHANGED
@@ -460,7 +460,10 @@ function normalizeIncomingArray(normalized, array, current, unwrap) {
460
460
  }
461
461
  } else {
462
462
  const value = String(item);
463
- if (prev && prev.nodeType === 3 && prev.data === value) {
463
+ if (value === "<!>") {
464
+ if (prev && prev.nodeType === 8) normalized.push(prev);
465
+ } else if (prev && prev.nodeType === 3) {
466
+ prev.data = value;
464
467
  normalized.push(prev);
465
468
  } else normalized.push(document.createTextNode(value));
466
469
  }
@@ -529,6 +532,7 @@ function escape(html) {}
529
532
  function ssrSpread(props, isSVG, skipChildren) {}
530
533
 
531
534
  const isServer = false;
535
+ const isDev = true;
532
536
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
533
537
  function createElement(tagName, isSVG = false) {
534
538
  return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
@@ -542,37 +546,41 @@ function Portal(props) {
542
546
  useShadow
543
547
  } = props,
544
548
  marker = document.createTextNode(""),
545
- mount = props.mount || document.body;
549
+ mount = () => props.mount || document.body,
550
+ content = solidJs.createMemo(renderPortal());
546
551
  function renderPortal() {
547
552
  if (solidJs.sharedConfig.context) {
548
553
  const [s, set] = solidJs.createSignal(false);
549
- queueMicrotask(() => set(true));
554
+ solidJs.onMount(() => set(true));
550
555
  return () => s() && props.children;
551
556
  } else return () => props.children;
552
557
  }
553
- if (mount instanceof HTMLHeadElement) {
554
- const [clean, setClean] = solidJs.createSignal(false);
555
- const cleanup = () => setClean(true);
556
- solidJs.createRoot(dispose => insert(mount, () => !clean() ? renderPortal()() : dispose(), null));
557
- solidJs.onCleanup(() => {
558
- if (solidJs.sharedConfig.context) queueMicrotask(cleanup);else cleanup();
559
- });
560
- } else {
561
- const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
562
- renderRoot = useShadow && container.attachShadow ? container.attachShadow({
563
- mode: "open"
564
- }) : container;
565
- Object.defineProperty(container, "_$host", {
566
- get() {
567
- return marker.parentNode;
568
- },
569
- configurable: true
570
- });
571
- insert(renderRoot, renderPortal());
572
- mount.appendChild(container);
573
- props.ref && props.ref(container);
574
- solidJs.onCleanup(() => mount.removeChild(container));
575
- }
558
+ solidJs.createRenderEffect(() => {
559
+ const el = mount();
560
+ if (el instanceof HTMLHeadElement) {
561
+ const [clean, setClean] = solidJs.createSignal(false);
562
+ const cleanup = () => setClean(true);
563
+ solidJs.createRoot(dispose => insert(el, () => !clean() ? content() : dispose(), null));
564
+ solidJs.onCleanup(() => {
565
+ if (solidJs.sharedConfig.context) queueMicrotask(cleanup);else cleanup();
566
+ });
567
+ } else {
568
+ const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
569
+ renderRoot = useShadow && container.attachShadow ? container.attachShadow({
570
+ mode: "open"
571
+ }) : container;
572
+ Object.defineProperty(container, "_$host", {
573
+ get() {
574
+ return marker.parentNode;
575
+ },
576
+ configurable: true
577
+ });
578
+ insert(renderRoot, content);
579
+ el.appendChild(container);
580
+ props.ref && props.ref(container);
581
+ solidJs.onCleanup(() => el.removeChild(container));
582
+ }
583
+ });
576
584
  return marker;
577
585
  }
578
586
  function Dynamic(props) {
@@ -682,6 +690,7 @@ exports.getNextMatch = getNextMatch;
682
690
  exports.hydrate = hydrate;
683
691
  exports.innerHTML = innerHTML;
684
692
  exports.insert = insert;
693
+ exports.isDev = isDev;
685
694
  exports.isServer = isServer;
686
695
  exports.render = render;
687
696
  exports.renderToStream = renderToStream;
package/web/dist/dev.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRoot, createRenderEffect, sharedConfig, untrack, enableHydration, createSignal, onCleanup, splitProps, createMemo, $DEVCOMP } from 'solid-js';
1
+ import { createRoot, createRenderEffect, sharedConfig, untrack, enableHydration, createMemo, createSignal, onMount, onCleanup, splitProps, $DEVCOMP } from 'solid-js';
2
2
  export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, createRenderEffect as effect, getOwner, createMemo as memo, mergeProps, untrack } from 'solid-js';
3
3
 
4
4
  const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
@@ -459,7 +459,10 @@ function normalizeIncomingArray(normalized, array, current, unwrap) {
459
459
  }
460
460
  } else {
461
461
  const value = String(item);
462
- if (prev && prev.nodeType === 3 && prev.data === value) {
462
+ if (value === "<!>") {
463
+ if (prev && prev.nodeType === 8) normalized.push(prev);
464
+ } else if (prev && prev.nodeType === 3) {
465
+ prev.data = value;
463
466
  normalized.push(prev);
464
467
  } else normalized.push(document.createTextNode(value));
465
468
  }
@@ -528,6 +531,7 @@ function escape(html) {}
528
531
  function ssrSpread(props, isSVG, skipChildren) {}
529
532
 
530
533
  const isServer = false;
534
+ const isDev = true;
531
535
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
532
536
  function createElement(tagName, isSVG = false) {
533
537
  return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
@@ -541,37 +545,41 @@ function Portal(props) {
541
545
  useShadow
542
546
  } = props,
543
547
  marker = document.createTextNode(""),
544
- mount = props.mount || document.body;
548
+ mount = () => props.mount || document.body,
549
+ content = createMemo(renderPortal());
545
550
  function renderPortal() {
546
551
  if (sharedConfig.context) {
547
552
  const [s, set] = createSignal(false);
548
- queueMicrotask(() => set(true));
553
+ onMount(() => set(true));
549
554
  return () => s() && props.children;
550
555
  } else return () => props.children;
551
556
  }
552
- if (mount instanceof HTMLHeadElement) {
553
- const [clean, setClean] = createSignal(false);
554
- const cleanup = () => setClean(true);
555
- createRoot(dispose => insert(mount, () => !clean() ? renderPortal()() : dispose(), null));
556
- onCleanup(() => {
557
- if (sharedConfig.context) queueMicrotask(cleanup);else cleanup();
558
- });
559
- } else {
560
- const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
561
- renderRoot = useShadow && container.attachShadow ? container.attachShadow({
562
- mode: "open"
563
- }) : container;
564
- Object.defineProperty(container, "_$host", {
565
- get() {
566
- return marker.parentNode;
567
- },
568
- configurable: true
569
- });
570
- insert(renderRoot, renderPortal());
571
- mount.appendChild(container);
572
- props.ref && props.ref(container);
573
- onCleanup(() => mount.removeChild(container));
574
- }
557
+ createRenderEffect(() => {
558
+ const el = mount();
559
+ if (el instanceof HTMLHeadElement) {
560
+ const [clean, setClean] = createSignal(false);
561
+ const cleanup = () => setClean(true);
562
+ createRoot(dispose => insert(el, () => !clean() ? content() : dispose(), null));
563
+ onCleanup(() => {
564
+ if (sharedConfig.context) queueMicrotask(cleanup);else cleanup();
565
+ });
566
+ } else {
567
+ const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
568
+ renderRoot = useShadow && container.attachShadow ? container.attachShadow({
569
+ mode: "open"
570
+ }) : container;
571
+ Object.defineProperty(container, "_$host", {
572
+ get() {
573
+ return marker.parentNode;
574
+ },
575
+ configurable: true
576
+ });
577
+ insert(renderRoot, content);
578
+ el.appendChild(container);
579
+ props.ref && props.ref(container);
580
+ onCleanup(() => el.removeChild(container));
581
+ }
582
+ });
575
583
  return marker;
576
584
  }
577
585
  function Dynamic(props) {
@@ -594,4 +602,4 @@ function Dynamic(props) {
594
602
  });
595
603
  }
596
604
 
597
- export { Aliases, voidFn as Assets, ChildProperties, DOMElements, DelegatedEvents, Dynamic, Hydration, voidFn as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, className, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, voidFn as generateHydrationScript, voidFn as getAssets, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, innerHTML, insert, isServer, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, style, template, use, voidFn as useAssets };
605
+ export { Aliases, voidFn as Assets, ChildProperties, DOMElements, DelegatedEvents, Dynamic, Hydration, voidFn as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, className, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, voidFn as generateHydrationScript, voidFn as getAssets, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, innerHTML, insert, isDev, isServer, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, style, template, use, voidFn as useAssets };
@@ -278,7 +278,11 @@ function renderToString(code, options = {}) {
278
278
  scripts += `_$HY.set("${id}", ${stringify(p)});`;
279
279
  }
280
280
  };
281
- let html = resolveSSRNode(escape(code()));
281
+ let html = solidJs.createRoot(d => {
282
+ resolveSSRNode(escape(code()));
283
+ d();
284
+ return r;
285
+ });
282
286
  solidJs.sharedConfig.context.noHydrate = true;
283
287
  html = injectAssets(solidJs.sharedConfig.context.assets, html);
284
288
  if (scripts.length) html = injectScripts(html, scripts, options.nonce);
@@ -304,6 +308,7 @@ function renderToStream(code, options = {}) {
304
308
  onCompleteAll,
305
309
  renderId
306
310
  } = options;
311
+ let dispose;
307
312
  const blockingResources = [];
308
313
  const registry = new Map();
309
314
  const dedupe = new WeakMap();
@@ -317,6 +322,7 @@ function renderToStream(code, options = {}) {
317
322
  });
318
323
  writable && writable.end();
319
324
  completed = true;
325
+ dispose();
320
326
  }
321
327
  };
322
328
  const pushTask = task => {
@@ -404,7 +410,10 @@ function renderToStream(code, options = {}) {
404
410
  };
405
411
  }
406
412
  };
407
- let html = resolveSSRNode(escape(code()));
413
+ let html = solidJs.createRoot(d => {
414
+ dispose = d;
415
+ return resolveSSRNode(escape(code()));
416
+ });
408
417
  function doShell() {
409
418
  solidJs.sharedConfig.context = context;
410
419
  context.noHydrate = true;
@@ -784,6 +793,7 @@ function ssrSpread(props, isSVG, skipChildren) {
784
793
  }
785
794
 
786
795
  const isServer = true;
796
+ const isDev = false;
787
797
  function render() {}
788
798
  function hydrate() {}
789
799
  function insert() {}
@@ -858,6 +868,7 @@ exports.getAssets = getAssets;
858
868
  exports.getHydrationKey = getHydrationKey;
859
869
  exports.hydrate = hydrate;
860
870
  exports.insert = insert;
871
+ exports.isDev = isDev;
861
872
  exports.isServer = isServer;
862
873
  exports.pipeToNodeWritable = pipeToNodeWritable;
863
874
  exports.pipeToWritable = pipeToWritable;
@@ -1,4 +1,4 @@
1
- import { sharedConfig, splitProps } from 'solid-js';
1
+ import { sharedConfig, createRoot, splitProps } from 'solid-js';
2
2
  export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, mergeProps } from 'solid-js';
3
3
 
4
4
  const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
@@ -277,7 +277,11 @@ function renderToString(code, options = {}) {
277
277
  scripts += `_$HY.set("${id}", ${stringify(p)});`;
278
278
  }
279
279
  };
280
- let html = resolveSSRNode(escape(code()));
280
+ let html = createRoot(d => {
281
+ resolveSSRNode(escape(code()));
282
+ d();
283
+ return r;
284
+ });
281
285
  sharedConfig.context.noHydrate = true;
282
286
  html = injectAssets(sharedConfig.context.assets, html);
283
287
  if (scripts.length) html = injectScripts(html, scripts, options.nonce);
@@ -303,6 +307,7 @@ function renderToStream(code, options = {}) {
303
307
  onCompleteAll,
304
308
  renderId
305
309
  } = options;
310
+ let dispose;
306
311
  const blockingResources = [];
307
312
  const registry = new Map();
308
313
  const dedupe = new WeakMap();
@@ -316,6 +321,7 @@ function renderToStream(code, options = {}) {
316
321
  });
317
322
  writable && writable.end();
318
323
  completed = true;
324
+ dispose();
319
325
  }
320
326
  };
321
327
  const pushTask = task => {
@@ -403,7 +409,10 @@ function renderToStream(code, options = {}) {
403
409
  };
404
410
  }
405
411
  };
406
- let html = resolveSSRNode(escape(code()));
412
+ let html = createRoot(d => {
413
+ dispose = d;
414
+ return resolveSSRNode(escape(code()));
415
+ });
407
416
  function doShell() {
408
417
  sharedConfig.context = context;
409
418
  context.noHydrate = true;
@@ -783,6 +792,7 @@ function ssrSpread(props, isSVG, skipChildren) {
783
792
  }
784
793
 
785
794
  const isServer = true;
795
+ const isDev = false;
786
796
  function render() {}
787
797
  function hydrate() {}
788
798
  function insert() {}
@@ -803,4 +813,4 @@ function Portal(props) {
803
813
  return "";
804
814
  }
805
815
 
806
- export { Assets, Dynamic, Hydration, HydrationScript, NoHydration, Portal, addEventListener, delegateEvents, escape, generateHydrationScript, getAssets, getHydrationKey, hydrate, insert, isServer, pipeToNodeWritable, pipeToWritable, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, stringify, useAssets };
816
+ export { Assets, Dynamic, Hydration, HydrationScript, NoHydration, Portal, addEventListener, delegateEvents, escape, generateHydrationScript, getAssets, getHydrationKey, hydrate, insert, isDev, isServer, pipeToNodeWritable, pipeToWritable, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, stringify, useAssets };
package/web/dist/web.cjs CHANGED
@@ -101,6 +101,7 @@ function render(code, element, init, options = {}) {
101
101
  function template(html, check, isSVG) {
102
102
  const t = document.createElement("template");
103
103
  t.innerHTML = html;
104
+ if (check && t.innerHTML.split("<").length - 1 !== check) throw `The browser resolved template HTML does not match JSX input:\n${t.innerHTML}\n\n${html}. Is your HTML properly formed?`;
104
105
  let node = t.content.firstChild;
105
106
  if (isSVG) node = node.firstChild;
106
107
  return node;
@@ -246,6 +247,8 @@ function hydrate$1(code, element, options = {}) {
246
247
  function getNextElement(template) {
247
248
  let node, key;
248
249
  if (!solidJs.sharedConfig.context || !(node = solidJs.sharedConfig.registry.get(key = getHydrationKey()))) {
250
+ if (solidJs.sharedConfig.context) console.warn("Unable to find DOM nodes for hydration key:", key);
251
+ if (!template) throw new Error("Unrecoverable Hydration Mismatch. No template for key: " + key);
249
252
  return template.cloneNode(true);
250
253
  }
251
254
  if (solidJs.sharedConfig.completed) solidJs.sharedConfig.completed.add(node);
@@ -435,7 +438,7 @@ function insertExpression(parent, value, current, marker, unwrapArray) {
435
438
  parent.appendChild(value);
436
439
  } else parent.replaceChild(value, parent.firstChild);
437
440
  current = value;
438
- } else ;
441
+ } else console.warn(`Unrecognized value. Skipped inserting`, value);
439
442
  return current;
440
443
  }
441
444
  function normalizeIncomingArray(normalized, array, current, unwrap) {
@@ -457,7 +460,10 @@ function normalizeIncomingArray(normalized, array, current, unwrap) {
457
460
  }
458
461
  } else {
459
462
  const value = String(item);
460
- if (prev && prev.nodeType === 3 && prev.data === value) {
463
+ if (value === "<!>") {
464
+ if (prev && prev.nodeType === 8) normalized.push(prev);
465
+ } else if (prev && prev.nodeType === 3) {
466
+ prev.data = value;
461
467
  normalized.push(prev);
462
468
  } else normalized.push(document.createTextNode(value));
463
469
  }
@@ -526,6 +532,7 @@ function escape(html) {}
526
532
  function ssrSpread(props, isSVG, skipChildren) {}
527
533
 
528
534
  const isServer = false;
535
+ const isDev = false;
529
536
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
530
537
  function createElement(tagName, isSVG = false) {
531
538
  return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
@@ -539,37 +546,41 @@ function Portal(props) {
539
546
  useShadow
540
547
  } = props,
541
548
  marker = document.createTextNode(""),
542
- mount = props.mount || document.body;
549
+ mount = () => props.mount || document.body,
550
+ content = solidJs.createMemo(renderPortal());
543
551
  function renderPortal() {
544
552
  if (solidJs.sharedConfig.context) {
545
553
  const [s, set] = solidJs.createSignal(false);
546
- queueMicrotask(() => set(true));
554
+ solidJs.onMount(() => set(true));
547
555
  return () => s() && props.children;
548
556
  } else return () => props.children;
549
557
  }
550
- if (mount instanceof HTMLHeadElement) {
551
- const [clean, setClean] = solidJs.createSignal(false);
552
- const cleanup = () => setClean(true);
553
- solidJs.createRoot(dispose => insert(mount, () => !clean() ? renderPortal()() : dispose(), null));
554
- solidJs.onCleanup(() => {
555
- if (solidJs.sharedConfig.context) queueMicrotask(cleanup);else cleanup();
556
- });
557
- } else {
558
- const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
559
- renderRoot = useShadow && container.attachShadow ? container.attachShadow({
560
- mode: "open"
561
- }) : container;
562
- Object.defineProperty(container, "_$host", {
563
- get() {
564
- return marker.parentNode;
565
- },
566
- configurable: true
567
- });
568
- insert(renderRoot, renderPortal());
569
- mount.appendChild(container);
570
- props.ref && props.ref(container);
571
- solidJs.onCleanup(() => mount.removeChild(container));
572
- }
558
+ solidJs.createRenderEffect(() => {
559
+ const el = mount();
560
+ if (el instanceof HTMLHeadElement) {
561
+ const [clean, setClean] = solidJs.createSignal(false);
562
+ const cleanup = () => setClean(true);
563
+ solidJs.createRoot(dispose => insert(el, () => !clean() ? content() : dispose(), null));
564
+ solidJs.onCleanup(() => {
565
+ if (solidJs.sharedConfig.context) queueMicrotask(cleanup);else cleanup();
566
+ });
567
+ } else {
568
+ const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
569
+ renderRoot = useShadow && container.attachShadow ? container.attachShadow({
570
+ mode: "open"
571
+ }) : container;
572
+ Object.defineProperty(container, "_$host", {
573
+ get() {
574
+ return marker.parentNode;
575
+ },
576
+ configurable: true
577
+ });
578
+ insert(renderRoot, content);
579
+ el.appendChild(container);
580
+ props.ref && props.ref(container);
581
+ solidJs.onCleanup(() => el.removeChild(container));
582
+ }
583
+ });
573
584
  return marker;
574
585
  }
575
586
  function Dynamic(props) {
@@ -579,6 +590,9 @@ function Dynamic(props) {
579
590
  const component = cached();
580
591
  switch (typeof component) {
581
592
  case "function":
593
+ Object.assign(component, {
594
+ [solidJs.$DEVCOMP]: true
595
+ });
582
596
  return solidJs.untrack(() => component(others));
583
597
  case "string":
584
598
  const isSvg = SVGElements.has(component);
@@ -676,6 +690,7 @@ exports.getNextMatch = getNextMatch;
676
690
  exports.hydrate = hydrate;
677
691
  exports.innerHTML = innerHTML;
678
692
  exports.insert = insert;
693
+ exports.isDev = isDev;
679
694
  exports.isServer = isServer;
680
695
  exports.render = render;
681
696
  exports.renderToStream = renderToStream;
package/web/dist/web.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRoot, createRenderEffect, sharedConfig, untrack, enableHydration, createSignal, onCleanup, splitProps, createMemo } from 'solid-js';
1
+ import { createRoot, createRenderEffect, sharedConfig, untrack, enableHydration, createMemo, createSignal, onMount, onCleanup, splitProps, $DEVCOMP } from 'solid-js';
2
2
  export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, createRenderEffect as effect, getOwner, createMemo as memo, mergeProps, untrack } from 'solid-js';
3
3
 
4
4
  const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
@@ -100,6 +100,7 @@ function render(code, element, init, options = {}) {
100
100
  function template(html, check, isSVG) {
101
101
  const t = document.createElement("template");
102
102
  t.innerHTML = html;
103
+ if (check && t.innerHTML.split("<").length - 1 !== check) throw `The browser resolved template HTML does not match JSX input:\n${t.innerHTML}\n\n${html}. Is your HTML properly formed?`;
103
104
  let node = t.content.firstChild;
104
105
  if (isSVG) node = node.firstChild;
105
106
  return node;
@@ -245,6 +246,8 @@ function hydrate$1(code, element, options = {}) {
245
246
  function getNextElement(template) {
246
247
  let node, key;
247
248
  if (!sharedConfig.context || !(node = sharedConfig.registry.get(key = getHydrationKey()))) {
249
+ if (sharedConfig.context) console.warn("Unable to find DOM nodes for hydration key:", key);
250
+ if (!template) throw new Error("Unrecoverable Hydration Mismatch. No template for key: " + key);
248
251
  return template.cloneNode(true);
249
252
  }
250
253
  if (sharedConfig.completed) sharedConfig.completed.add(node);
@@ -434,7 +437,7 @@ function insertExpression(parent, value, current, marker, unwrapArray) {
434
437
  parent.appendChild(value);
435
438
  } else parent.replaceChild(value, parent.firstChild);
436
439
  current = value;
437
- } else ;
440
+ } else console.warn(`Unrecognized value. Skipped inserting`, value);
438
441
  return current;
439
442
  }
440
443
  function normalizeIncomingArray(normalized, array, current, unwrap) {
@@ -456,7 +459,10 @@ function normalizeIncomingArray(normalized, array, current, unwrap) {
456
459
  }
457
460
  } else {
458
461
  const value = String(item);
459
- if (prev && prev.nodeType === 3 && prev.data === value) {
462
+ if (value === "<!>") {
463
+ if (prev && prev.nodeType === 8) normalized.push(prev);
464
+ } else if (prev && prev.nodeType === 3) {
465
+ prev.data = value;
460
466
  normalized.push(prev);
461
467
  } else normalized.push(document.createTextNode(value));
462
468
  }
@@ -525,6 +531,7 @@ function escape(html) {}
525
531
  function ssrSpread(props, isSVG, skipChildren) {}
526
532
 
527
533
  const isServer = false;
534
+ const isDev = false;
528
535
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
529
536
  function createElement(tagName, isSVG = false) {
530
537
  return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
@@ -538,37 +545,41 @@ function Portal(props) {
538
545
  useShadow
539
546
  } = props,
540
547
  marker = document.createTextNode(""),
541
- mount = props.mount || document.body;
548
+ mount = () => props.mount || document.body,
549
+ content = createMemo(renderPortal());
542
550
  function renderPortal() {
543
551
  if (sharedConfig.context) {
544
552
  const [s, set] = createSignal(false);
545
- queueMicrotask(() => set(true));
553
+ onMount(() => set(true));
546
554
  return () => s() && props.children;
547
555
  } else return () => props.children;
548
556
  }
549
- if (mount instanceof HTMLHeadElement) {
550
- const [clean, setClean] = createSignal(false);
551
- const cleanup = () => setClean(true);
552
- createRoot(dispose => insert(mount, () => !clean() ? renderPortal()() : dispose(), null));
553
- onCleanup(() => {
554
- if (sharedConfig.context) queueMicrotask(cleanup);else cleanup();
555
- });
556
- } else {
557
- const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
558
- renderRoot = useShadow && container.attachShadow ? container.attachShadow({
559
- mode: "open"
560
- }) : container;
561
- Object.defineProperty(container, "_$host", {
562
- get() {
563
- return marker.parentNode;
564
- },
565
- configurable: true
566
- });
567
- insert(renderRoot, renderPortal());
568
- mount.appendChild(container);
569
- props.ref && props.ref(container);
570
- onCleanup(() => mount.removeChild(container));
571
- }
557
+ createRenderEffect(() => {
558
+ const el = mount();
559
+ if (el instanceof HTMLHeadElement) {
560
+ const [clean, setClean] = createSignal(false);
561
+ const cleanup = () => setClean(true);
562
+ createRoot(dispose => insert(el, () => !clean() ? content() : dispose(), null));
563
+ onCleanup(() => {
564
+ if (sharedConfig.context) queueMicrotask(cleanup);else cleanup();
565
+ });
566
+ } else {
567
+ const container = createElement(props.isSVG ? "g" : "div", props.isSVG),
568
+ renderRoot = useShadow && container.attachShadow ? container.attachShadow({
569
+ mode: "open"
570
+ }) : container;
571
+ Object.defineProperty(container, "_$host", {
572
+ get() {
573
+ return marker.parentNode;
574
+ },
575
+ configurable: true
576
+ });
577
+ insert(renderRoot, content);
578
+ el.appendChild(container);
579
+ props.ref && props.ref(container);
580
+ onCleanup(() => el.removeChild(container));
581
+ }
582
+ });
572
583
  return marker;
573
584
  }
574
585
  function Dynamic(props) {
@@ -578,6 +589,9 @@ function Dynamic(props) {
578
589
  const component = cached();
579
590
  switch (typeof component) {
580
591
  case "function":
592
+ Object.assign(component, {
593
+ [$DEVCOMP]: true
594
+ });
581
595
  return untrack(() => component(others));
582
596
  case "string":
583
597
  const isSvg = SVGElements.has(component);
@@ -588,4 +602,4 @@ function Dynamic(props) {
588
602
  });
589
603
  }
590
604
 
591
- export { Aliases, voidFn as Assets, ChildProperties, DOMElements, DelegatedEvents, Dynamic, Hydration, voidFn as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, className, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, voidFn as generateHydrationScript, voidFn as getAssets, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, innerHTML, insert, isServer, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, style, template, use, voidFn as useAssets };
605
+ export { Aliases, voidFn as Assets, ChildProperties, DOMElements, DelegatedEvents, Dynamic, Hydration, voidFn as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, className, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, voidFn as generateHydrationScript, voidFn as getAssets, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, innerHTML, insert, isDev, isServer, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, style, template, use, voidFn as useAssets };
@@ -3,7 +3,8 @@ import { JSX, Accessor, ComponentProps, ValidComponent } from "solid-js";
3
3
  export * from "./client.js";
4
4
  export { For, Show, Suspense, SuspenseList, Switch, Match, Index, ErrorBoundary, mergeProps } from "solid-js";
5
5
  export * from "./server-mock.js";
6
- export declare const isServer = false;
6
+ export declare const isServer: boolean;
7
+ export declare const isDev: boolean;
7
8
  export declare const hydrate: typeof hydrateCore;
8
9
  /**
9
10
  * renders components somewhere else in the DOM