solid-js 1.2.2 → 1.3.0-beta.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.
@@ -1,4 +1,4 @@
1
- import { sharedConfig, awaitSuspense, splitProps } from 'solid-js';
1
+ import { sharedConfig, 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"];
@@ -229,111 +229,162 @@ function stringifyString(str) {
229
229
  return result;
230
230
  }
231
231
 
232
+ const REPLACE_SCRIPT = `function $df(e,t){t=document.getElementById(e),document.getElementById("pl"+e).replaceWith(...t.childNodes),_$HY.set(e)}`;
233
+ const SYNC_SCRIPT = `_$HY.sync=!0;for(let e=0;e<_$HY.queue.length;e++)_$HY.queue[e]()`;
232
234
  function renderToString(code, options = {}) {
233
- sharedConfig.context = Object.assign({
235
+ sharedConfig.context = {
234
236
  id: "",
235
237
  count: 0,
236
- assets: []
237
- }, options);
238
+ suspense: {},
239
+ assets: [],
240
+ nonce: options.nonce
241
+ };
238
242
  let html = resolveSSRNode(escape(code()));
239
- return injectAssets(sharedConfig.context.assets, html);
243
+ return injectAssets(sharedConfig.context.assets, html) + `<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>${SYNC_SCRIPT}</script>`;
240
244
  }
241
245
  function renderToStringAsync(code, options = {}) {
242
- options = {
243
- timeoutMs: 30000,
244
- ...options
245
- };
246
- const context = sharedConfig.context = Object.assign({
246
+ const {
247
+ nonce,
248
+ timeoutMs = 30000
249
+ } = options;
250
+ const context = sharedConfig.context = {
247
251
  id: "",
248
252
  count: 0,
249
253
  resources: {},
250
254
  suspense: {},
251
255
  assets: [],
252
- async: true
253
- }, options);
254
- const timeout = new Promise((_, reject) => setTimeout(() => reject("renderToString timed out"), options.timeoutMs));
255
- return Promise.race([awaitSuspense(() => escape(code())), timeout]).then(res => {
256
+ async: true,
257
+ nonce
258
+ };
259
+ let scripts = "";
260
+ sharedConfig.context.writeResource = (id, p) => p.then(d => scripts += `_$HY.set("${id}", ${devalue(d)});`);
261
+ const timeout = new Promise((_, reject) => setTimeout(() => reject("renderToString timed out"), timeoutMs));
262
+ return Promise.race([asyncWrap(() => escape(code())), timeout]).then(res => {
256
263
  let html = resolveSSRNode(res);
264
+ html += `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts.length ? scripts + ";" : ""}${SYNC_SCRIPT}</script>`;
257
265
  return injectAssets(context.assets, html);
258
266
  });
259
267
  }
260
- function pipeToNodeWritable(code, writable, options = {}) {
268
+ function renderToPipeableStream(code, options) {
261
269
  const {
262
270
  nonce,
263
- onReady = ({
264
- startWriting
265
- }) => startWriting(),
266
- onComplete
271
+ onCompleteShell,
272
+ onCompleteAll
267
273
  } = options;
268
274
  const tmp = [];
269
- let count = 0,
270
- completed = 0,
271
- buffer = {
272
- write(payload) {
273
- tmp.push(payload);
275
+ const tasks = [];
276
+ const registry = new Set();
277
+ const checkEnd = () => {
278
+ if (!registry.size && !completed) {
279
+ onCompleteAll && onCompleteAll(result);
280
+ writable && writable.end();
281
+ completed = true;
274
282
  }
275
283
  };
276
- const result = {
277
- startWriting() {
278
- buffer = writable;
279
- tmp.forEach(chunk => buffer.write(chunk));
280
- setTimeout(checkEnd);
281
- },
282
- write(c) {
283
- writable.write(c);
284
- },
285
- abort() {
286
- completed = count;
287
- checkEnd();
284
+ const writeInitialScript = () => {
285
+ if (tasks.length) {
286
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`);
287
+ tasks.length = 0;
288
288
  }
289
+ scheduled = false;
289
290
  };
290
- const checkEnd = () => {
291
- if (completed === count) {
292
- onComplete && onComplete(result);
293
- writable.end();
291
+ let writable;
292
+ let completed = false;
293
+ let scriptFlushed = false;
294
+ let scheduled = true;
295
+ let buffer = {
296
+ write(payload) {
297
+ tmp.push(payload);
294
298
  }
295
299
  };
296
- sharedConfig.context = Object.assign({
300
+ sharedConfig.context = {
297
301
  id: "",
298
302
  count: 0,
303
+ async: true,
299
304
  streaming: true,
305
+ resources: {},
300
306
  suspense: {},
301
- assets: []
302
- }, options);
303
- sharedConfig.context.writeResource = (id, p) => {
304
- count++;
305
- Promise.resolve().then(() => buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`));
306
- p.then(d => {
307
- buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${devalue(d)})</script>`);
308
- ++completed && checkEnd();
309
- });
307
+ assets: [],
308
+ nonce,
309
+ writeResource(id, p) {
310
+ if (!scheduled) {
311
+ Promise.resolve().then(writeInitialScript);
312
+ scheduled = true;
313
+ }
314
+ tasks.push(`_$HY.init("${id}")`);
315
+ p.then(d => {
316
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HY.set("${id}", ${devalue(d)})</script>`);
317
+ });
318
+ },
319
+ registerFragment(key) {
320
+ registry.add(key);
321
+ Promise.resolve().then(() => {
322
+ if (registry.has(key)) {
323
+ if (!scheduled) {
324
+ Promise.resolve().then(writeInitialScript);
325
+ scheduled = true;
326
+ }
327
+ tasks.push(`_$HY.init("${key}")`);
328
+ }
329
+ });
330
+ return value => {
331
+ registry.delete(key);
332
+ if (!value) return;
333
+ Promise.resolve().then(() => {
334
+ buffer.write(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`);
335
+ scriptFlushed = true;
336
+ checkEnd();
337
+ });
338
+ };
339
+ }
310
340
  };
311
341
  let html = resolveSSRNode(escape(code()));
312
342
  html = injectAssets(sharedConfig.context.assets, html);
313
343
  buffer.write(html);
314
- onReady(result);
344
+ Promise.resolve().then(() => {
345
+ writeInitialScript();
346
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${SYNC_SCRIPT}</script>`);
347
+ onCompleteShell && onCompleteShell();
348
+ });
349
+ return {
350
+ pipe(w) {
351
+ buffer = writable = w;
352
+ tmp.forEach(chunk => buffer.write(chunk));
353
+ if (completed) writable.end();else setTimeout(checkEnd);
354
+ }
355
+ };
315
356
  }
316
357
  function pipeToWritable(code, writable, options = {}) {
317
358
  const {
318
359
  nonce,
319
- onReady = ({
360
+ onCompleteShell = ({
320
361
  startWriting
321
362
  }) => startWriting(),
322
- onComplete
363
+ onCompleteAll
323
364
  } = options;
324
365
  const tmp = [];
366
+ const tasks = [];
325
367
  const writer = writable.getWriter();
326
368
  const encoder = new TextEncoder();
327
- sharedConfig.context = Object.assign({
328
- id: "",
329
- count: 0,
330
- streaming: true,
331
- suspense: {},
332
- assets: []
333
- }, options);
334
- let count = 0,
335
- completed = 0,
336
- buffer = {
369
+ const registry = new Set();
370
+ const checkEnd = () => {
371
+ if (!registry.size && !completed) {
372
+ onCompleteAll && onCompleteAll(result);
373
+ writable && writable.close();
374
+ completed = true;
375
+ }
376
+ };
377
+ const writeInitialScript = () => {
378
+ if (tasks.length) {
379
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`));
380
+ tasks.length = 0;
381
+ }
382
+ scheduled = false;
383
+ };
384
+ let completed = false;
385
+ let scriptFlushed = false;
386
+ let scheduled = true;
387
+ let buffer = {
337
388
  write(payload) {
338
389
  tmp.push(payload);
339
390
  }
@@ -348,28 +399,62 @@ function pipeToWritable(code, writable, options = {}) {
348
399
  writer.write(encoder.encode(c));
349
400
  },
350
401
  abort() {
351
- completed = count;
402
+ registry.clear();
352
403
  checkEnd();
353
404
  }
354
405
  };
355
- const checkEnd = () => {
356
- if (completed === count) {
357
- onComplete && onComplete(result);
358
- writable.close();
406
+ sharedConfig.context = {
407
+ id: "",
408
+ count: 0,
409
+ async: true,
410
+ streaming: true,
411
+ resources: {},
412
+ suspense: {},
413
+ assets: [],
414
+ nonce,
415
+ writeResource(id, p) {
416
+ if (!scheduled) {
417
+ Promise.resolve().then(writeInitialScript);
418
+ scheduled = true;
419
+ }
420
+ tasks.push(`_$HY.init("${id}")`);
421
+ p.then(d => {
422
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HY.set("${id}", ${devalue(d)})</script>`));
423
+ });
424
+ },
425
+ registerFragment(key) {
426
+ registry.add(key);
427
+ Promise.resolve().then(() => {
428
+ if (registry.has(key)) {
429
+ if (!scheduled) {
430
+ Promise.resolve().then(writeInitialScript);
431
+ scheduled = true;
432
+ }
433
+ tasks.push(`_$HY.init("${key}")`);
434
+ }
435
+ });
436
+ return value => {
437
+ registry.delete(key);
438
+ if (!value) return;
439
+ Promise.resolve().then(() => {
440
+ buffer.write(encoder.encode(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`));
441
+ scriptFlushed = true;
442
+ checkEnd();
443
+ });
444
+ };
359
445
  }
360
446
  };
361
- sharedConfig.context.writeResource = (id, p) => {
362
- count++;
363
- Promise.resolve().then(() => buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`)));
364
- p.then(d => {
365
- buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${devalue(d)})</script>`));
366
- ++completed && checkEnd();
367
- });
368
- };
369
447
  let html = resolveSSRNode(escape(code()));
370
448
  html = injectAssets(sharedConfig.context.assets, html);
371
449
  buffer.write(encoder.encode(html));
372
- onReady(result);
450
+ Promise.resolve().then(() => {
451
+ writeInitialScript();
452
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>${SYNC_SCRIPT}</script>`));
453
+ onCompleteShell && onCompleteShell(result);
454
+ });
455
+ }
456
+ function pipeToNodeWritable(code, writable, options = {}) {
457
+ renderToPipeableStream(code, options).pipe(writable);
373
458
  }
374
459
  function Assets(props) {
375
460
  sharedConfig.context.assets.push(() => NoHydration({
@@ -379,15 +464,21 @@ function Assets(props) {
379
464
  }));
380
465
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
381
466
  }
382
- function HydrationScript() {
383
- sharedConfig.context.assets.push(generateHydrationScript);
467
+ function HydrationScript(props) {
468
+ const {
469
+ nonce
470
+ } = sharedConfig.context;
471
+ sharedConfig.context.assets.push(() => generateHydrationScript({
472
+ nonce,
473
+ ...props
474
+ }));
384
475
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
385
476
  }
386
477
  function NoHydration(props) {
387
478
  const c = sharedConfig.context;
388
- delete sharedConfig.context;
479
+ c.noHydrate = true;
389
480
  const children = props.children;
390
- sharedConfig.context = c;
481
+ c.noHydrate = false;
391
482
  return children;
392
483
  }
393
484
  function ssr(t, ...nodes) {
@@ -446,6 +537,8 @@ function ssrSpread(props, isSVG, skipChildren) {
446
537
  result += `class="${ssrClassList(value)}"`;
447
538
  } else if (BooleanAttributes.has(prop)) {
448
539
  if (value) result += prop;else continue;
540
+ } else if (prop === "ref" || prop.slice(0, 2) === "on") {
541
+ continue;
449
542
  } else {
450
543
  result += `${Aliases[prop] || prop}="${escape(value, true)}"`;
451
544
  }
@@ -513,26 +606,13 @@ function resolveSSRNode(node) {
513
606
  }
514
607
  function getHydrationKey() {
515
608
  const hydrate = sharedConfig.context;
516
- return hydrate && `${hydrate.id}${hydrate.count++}`;
609
+ return hydrate && !hydrate.noHydrate && `${hydrate.id}${hydrate.count++}`;
517
610
  }
518
- function generateHydrationScript() {
519
- const {
520
- nonce,
521
- streaming,
522
- resources,
523
- eventNames = ["click", "input"]
524
- } = sharedConfig.context;
525
- let s = `<script${nonce ? ` nonce="${nonce}"` : ""}>(()=>{_$HYDRATION={events:[],completed:new WeakSet};const t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")&&e||t(e.host&&e.host instanceof Node?e.host:e.parentNode)),e=e=>{let o=e.composedPath&&e.composedPath()[0]||e.target,s=t(o);s&&!_$HYDRATION.completed.has(s)&&_$HYDRATION.events.push([s,e])};["${eventNames.join('","')}"].forEach(t=>document.addEventListener(t,e))})();`;
526
- if (streaming) {
527
- s += `(()=>{const e=_$HYDRATION,o={};e.startResource=e=>{let r;o[e]=[new Promise(e=>r=e),r]},e.resolveResource=(e,r)=>{const n=o[e];if(!n)return o[e]=[r];n[1](r)},e.loadResource=e=>{const r=o[e];if(r)return r[0]}})();`;
528
- }
529
- if (resources) {
530
- s += `_$HYDRATION.resources = ${devalue(Object.keys(resources).reduce((r, k) => {
531
- r[k] = resources[k].data;
532
- return r;
533
- }, {}))};`;
534
- }
535
- return s + `</script>`;
611
+ function generateHydrationScript({
612
+ eventNames = ["click", "input"],
613
+ nonce
614
+ }) {
615
+ return `<script${nonce ? ` nonce="${nonce}"` : ""}>((e,t,o={})=>{t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")?e:t(e.host&&e.host instanceof Node?e.host:e.parentNode)),["${eventNames.join('","')}"].forEach((o=>document.addEventListener(o,(o=>{let n=o.composedPath&&o.composedPath()[0]||o.target,s=t(n);s&&!e.completed.has(s)&&e.events.push([s,o])})))),e.init=(e,t)=>{o[e]=[new Promise((e=>t=e)),t]},e.set=(e,t,n)=>{if(!(n=o[e]))return o[e]=[t];n[1](t)},e.load=(e,t)=>{if(t=o[e])return t[0]}})(window._$HY||(_$HY={events:[],completed:new WeakSet,queue:[]}));</script>`;
536
616
  }
537
617
  function injectAssets(assets, html) {
538
618
  for (let i = 0; i < assets.length; i++) {
@@ -540,6 +620,33 @@ function injectAssets(assets, html) {
540
620
  }
541
621
  return html;
542
622
  }
623
+ const FRAGMENT_REPLACE = /<!\[([\d.]+)\]>/;
624
+ function asyncWrap(fn) {
625
+ return new Promise(resolve => {
626
+ const registry = new Set();
627
+ const cache = Object.create(null);
628
+ sharedConfig.context.registerFragment = register;
629
+ const rendered = fn();
630
+ if (!registry.size) resolve(rendered);
631
+ function register(key) {
632
+ registry.add(key);
633
+ return value => {
634
+ if (value) cache[key] = value;
635
+ registry.delete(key);
636
+ if (!registry.size) Promise.resolve().then(() => {
637
+ let source = resolveSSRNode(rendered);
638
+ let final = "";
639
+ let match;
640
+ while (match = source.match(FRAGMENT_REPLACE)) {
641
+ final += source.substring(0, match.index);
642
+ source = cache[match[1]] + source.substring(match.index + match[0].length);
643
+ }
644
+ resolve(final + source);
645
+ });
646
+ };
647
+ }
648
+ });
649
+ }
543
650
 
544
651
  const isServer = true;
545
652
  function spread() {}
@@ -558,4 +665,4 @@ function Portal(props) {
558
665
  return "";
559
666
  }
560
667
 
561
- export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
668
+ export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToPipeableStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
package/web/dist/web.cjs CHANGED
@@ -202,60 +202,41 @@ function insert(parent, accessor, marker, initial) {
202
202
  solidJs.createRenderEffect(current => insertExpression(parent, accessor(), current, marker), initial);
203
203
  }
204
204
  function assign(node, props, isSVG, skipChildren, prevProps = {}) {
205
- let isCE, isProp, isChildProp;
205
+ for (const prop in prevProps) {
206
+ if (!(prop in props)) {
207
+ if (prop === "children") continue;
208
+ assignProp(node, prop, null, prevProps[prop], isSVG);
209
+ }
210
+ }
206
211
  for (const prop in props) {
207
212
  if (prop === "children") {
208
213
  if (!skipChildren) insertExpression(node, props.children);
209
214
  continue;
210
215
  }
211
216
  const value = props[prop];
212
- if (value === prevProps[prop]) continue;
213
- if (prop === "style") {
214
- style(node, value, prevProps[prop]);
215
- } else if (prop === "classList") {
216
- classList(node, value, prevProps[prop]);
217
- } else if (prop === "ref") {
218
- value(node);
219
- } else if (prop.slice(0, 3) === "on:") {
220
- node.addEventListener(prop.slice(3), value);
221
- } else if (prop.slice(0, 10) === "oncapture:") {
222
- node.addEventListener(prop.slice(10), value, true);
223
- } else if (prop.slice(0, 2) === "on") {
224
- const name = prop.slice(2).toLowerCase();
225
- const delegate = DelegatedEvents.has(name);
226
- addEventListener(node, name, value, delegate);
227
- delegate && delegateEvents([name]);
228
- } else if ((isChildProp = ChildProperties.has(prop)) || !isSVG && (PropAliases[prop] || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes("-"))) {
229
- if (isCE && !isProp && !isChildProp) node[toPropertyName(prop)] = value;else node[PropAliases[prop] || prop] = value;
230
- } else {
231
- const ns = isSVG && prop.indexOf(":") > -1 && SVGNamespace[prop.split(":")[0]];
232
- if (ns) setAttributeNS(node, ns, prop, value);else setAttribute(node, Aliases[prop] || prop, value);
233
- }
234
- prevProps[prop] = value;
217
+ prevProps[prop] = assignProp(node, prop, value, prevProps[prop], isSVG);
235
218
  }
236
219
  }
237
220
  function hydrate(code, element) {
238
- solidJs.sharedConfig.resources = globalThis._$HYDRATION.resources;
239
- solidJs.sharedConfig.completed = globalThis._$HYDRATION.completed;
240
- solidJs.sharedConfig.events = globalThis._$HYDRATION.events;
221
+ if (!globalThis._$HY.sync) {
222
+ let dispose;
223
+ globalThis._$HY.queue.push(() => dispose = hydrate(code, element));
224
+ return () => dispose();
225
+ }
226
+ solidJs.sharedConfig.completed = globalThis._$HY.completed;
227
+ solidJs.sharedConfig.events = globalThis._$HY.events;
228
+ solidJs.sharedConfig.load = globalThis._$HY.load;
229
+ solidJs.sharedConfig.gather = root => gatherHydratable(element, root);
230
+ solidJs.sharedConfig.registry = new Map();
241
231
  solidJs.sharedConfig.context = {
242
232
  id: "",
243
- count: 0,
244
- loadResource: globalThis._$HYDRATION.loadResource
233
+ count: 0
245
234
  };
246
- solidJs.sharedConfig.registry = new Map();
247
235
  gatherHydratable(element);
248
236
  const dispose = render(code, element, [...element.childNodes]);
249
237
  solidJs.sharedConfig.context = null;
250
238
  return dispose;
251
239
  }
252
- function gatherHydratable(element) {
253
- const templates = element.querySelectorAll(`*[data-hk]`);
254
- for (let i = 0; i < templates.length; i++) {
255
- const node = templates[i];
256
- solidJs.sharedConfig.registry.set(node.getAttribute("data-hk"), node);
257
- }
258
- }
259
240
  function getNextElement(template) {
260
241
  let node, key;
261
242
  if (!solidJs.sharedConfig.context || !(node = solidJs.sharedConfig.registry.get(key = getHydrationKey()))) {
@@ -313,6 +294,30 @@ function toggleClassKey(node, key, value) {
313
294
  const classNames = key.trim().split(/\s+/);
314
295
  for (let i = 0, nameLen = classNames.length; i < nameLen; i++) node.classList.toggle(classNames[i], value);
315
296
  }
297
+ function assignProp(node, prop, value, prev, isSVG) {
298
+ let isCE, isProp, isChildProp;
299
+ if (prop === "style") return style(node, value, prev);
300
+ if (prop === "classList") return classList(node, value, prev);
301
+ if (value === prev) return prev;
302
+ if (prop === "ref") {
303
+ value(node);
304
+ } else if (prop.slice(0, 3) === "on:") {
305
+ node.addEventListener(prop.slice(3), value);
306
+ } else if (prop.slice(0, 10) === "oncapture:") {
307
+ node.addEventListener(prop.slice(10), value, true);
308
+ } else if (prop.slice(0, 2) === "on") {
309
+ const name = prop.slice(2).toLowerCase();
310
+ const delegate = DelegatedEvents.has(name);
311
+ addEventListener(node, name, value, delegate);
312
+ delegate && delegateEvents([name]);
313
+ } else if ((isChildProp = ChildProperties.has(prop)) || !isSVG && (PropAliases[prop] || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes("-"))) {
314
+ if (isCE && !isProp && !isChildProp) node[toPropertyName(prop)] = value;else node[PropAliases[prop] || prop] = value;
315
+ } else {
316
+ const ns = isSVG && prop.indexOf(":") > -1 && SVGNamespace[prop.split(":")[0]];
317
+ if (ns) setAttributeNS(node, ns, prop, value);else setAttribute(node, Aliases[prop] || prop, value);
318
+ }
319
+ return value;
320
+ }
316
321
  function eventHandler(e) {
317
322
  const key = `$$${e.type}`;
318
323
  let node = e.composedPath && e.composedPath()[0] || e.target;
@@ -325,7 +330,7 @@ function eventHandler(e) {
325
330
  Object.defineProperty(e, "currentTarget", {
326
331
  configurable: true,
327
332
  get() {
328
- return node;
333
+ return node || document;
329
334
  }
330
335
  });
331
336
  while (node !== null) {
@@ -380,7 +385,12 @@ function insertExpression(parent, value, current, marker, unwrapArray) {
380
385
  solidJs.createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
381
386
  return () => current;
382
387
  }
383
- if (solidJs.sharedConfig.context && current && current.length) return current;
388
+ if (solidJs.sharedConfig.context && current && current.length) {
389
+ for (let i; i < array.length; i++) {
390
+ if (array[i].parentNode) return array;
391
+ }
392
+ return current;
393
+ }
384
394
  if (array.length === 0) {
385
395
  current = cleanChildren(parent, current, marker);
386
396
  if (multi) return current;
@@ -448,6 +458,14 @@ function cleanChildren(parent, current, marker, replacement) {
448
458
  } else parent.insertBefore(node, marker);
449
459
  return [node];
450
460
  }
461
+ function gatherHydratable(element, root) {
462
+ const templates = element.querySelectorAll(`*[data-hk]`);
463
+ for (let i = 0; i < templates.length; i++) {
464
+ const node = templates[i];
465
+ const key = node.getAttribute("data-hk");
466
+ if (!root || key.startsWith(root)) solidJs.sharedConfig.registry.set(key, node);
467
+ }
468
+ }
451
469
  function getHydrationKey() {
452
470
  const hydrate = solidJs.sharedConfig.context;
453
471
  return `${hydrate.id}${hydrate.count++}`;
@@ -622,7 +640,6 @@ exports.clearDelegatedEvents = clearDelegatedEvents;
622
640
  exports.delegateEvents = delegateEvents;
623
641
  exports.dynamicProperty = dynamicProperty;
624
642
  exports.escape = escape;
625
- exports.gatherHydratable = gatherHydratable;
626
643
  exports.generateHydrationScript = generateHydrationScript;
627
644
  exports.getHydrationKey = getHydrationKey;
628
645
  exports.getNextElement = getNextElement;