solid-js 1.2.3 → 1.3.0-beta.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.
@@ -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,160 @@ 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
+ buffer.write(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`);
334
+ scriptFlushed = true;
335
+ checkEnd();
336
+ };
337
+ }
310
338
  };
311
339
  let html = resolveSSRNode(escape(code()));
312
340
  html = injectAssets(sharedConfig.context.assets, html);
313
- buffer.write(html);
314
- onReady(result);
341
+ Promise.resolve().then(() => {
342
+ buffer.write(html + `<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.length ? tasks.join(";") + ";" : ""}${SYNC_SCRIPT}</script>`);
343
+ tasks.length = 0;
344
+ scheduled = false;
345
+ onCompleteShell && onCompleteShell();
346
+ });
347
+ return {
348
+ pipe(w) {
349
+ buffer = writable = w;
350
+ tmp.forEach(chunk => buffer.write(chunk));
351
+ if (completed) writable.end();else setTimeout(checkEnd);
352
+ }
353
+ };
315
354
  }
316
355
  function pipeToWritable(code, writable, options = {}) {
317
356
  const {
318
357
  nonce,
319
- onReady = ({
358
+ onCompleteShell = ({
320
359
  startWriting
321
360
  }) => startWriting(),
322
- onComplete
361
+ onCompleteAll
323
362
  } = options;
324
363
  const tmp = [];
364
+ const tasks = [];
325
365
  const writer = writable.getWriter();
326
366
  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 = {
367
+ const registry = new Set();
368
+ const checkEnd = () => {
369
+ if (!registry.size && !completed) {
370
+ onCompleteAll && onCompleteAll(result);
371
+ writable && writable.close();
372
+ completed = true;
373
+ }
374
+ };
375
+ const writeInitialScript = () => {
376
+ if (tasks.length) {
377
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`));
378
+ tasks.length = 0;
379
+ }
380
+ scheduled = false;
381
+ };
382
+ let completed = false;
383
+ let scriptFlushed = false;
384
+ let scheduled = true;
385
+ let buffer = {
337
386
  write(payload) {
338
387
  tmp.push(payload);
339
388
  }
@@ -348,28 +397,60 @@ function pipeToWritable(code, writable, options = {}) {
348
397
  writer.write(encoder.encode(c));
349
398
  },
350
399
  abort() {
351
- completed = count;
400
+ registry.clear();
352
401
  checkEnd();
353
402
  }
354
403
  };
355
- const checkEnd = () => {
356
- if (completed === count) {
357
- onComplete && onComplete(result);
358
- writable.close();
404
+ sharedConfig.context = {
405
+ id: "",
406
+ count: 0,
407
+ async: true,
408
+ streaming: true,
409
+ resources: {},
410
+ suspense: {},
411
+ assets: [],
412
+ nonce,
413
+ writeResource(id, p) {
414
+ if (!scheduled) {
415
+ Promise.resolve().then(writeInitialScript);
416
+ scheduled = true;
417
+ }
418
+ tasks.push(`_$HY.init("${id}")`);
419
+ p.then(d => {
420
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HY.set("${id}", ${devalue(d)})</script>`));
421
+ });
422
+ },
423
+ registerFragment(key) {
424
+ registry.add(key);
425
+ Promise.resolve().then(() => {
426
+ if (registry.has(key)) {
427
+ if (!scheduled) {
428
+ Promise.resolve().then(writeInitialScript);
429
+ scheduled = true;
430
+ }
431
+ tasks.push(`_$HY.init("${key}")`);
432
+ }
433
+ });
434
+ return value => {
435
+ registry.delete(key);
436
+ if (!value) return;
437
+ buffer.write(encoder.encode(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`));
438
+ scriptFlushed = true;
439
+ checkEnd();
440
+ };
359
441
  }
360
442
  };
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
443
  let html = resolveSSRNode(escape(code()));
370
444
  html = injectAssets(sharedConfig.context.assets, html);
371
- buffer.write(encoder.encode(html));
372
- onReady(result);
445
+ Promise.resolve().then(() => {
446
+ buffer.write(encoder.encode(html + `<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.length ? tasks.join(";") + ";" : ""}${SYNC_SCRIPT}</script>`));
447
+ tasks.length = 0;
448
+ scheduled = false;
449
+ onCompleteShell && onCompleteShell(result);
450
+ });
451
+ }
452
+ function pipeToNodeWritable(code, writable, options = {}) {
453
+ renderToPipeableStream(code, options).pipe(writable);
373
454
  }
374
455
  function Assets(props) {
375
456
  sharedConfig.context.assets.push(() => NoHydration({
@@ -379,15 +460,21 @@ function Assets(props) {
379
460
  }));
380
461
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
381
462
  }
382
- function HydrationScript() {
383
- sharedConfig.context.assets.push(generateHydrationScript);
463
+ function HydrationScript(props) {
464
+ const {
465
+ nonce
466
+ } = sharedConfig.context;
467
+ sharedConfig.context.assets.push(() => generateHydrationScript({
468
+ nonce,
469
+ ...props
470
+ }));
384
471
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
385
472
  }
386
473
  function NoHydration(props) {
387
474
  const c = sharedConfig.context;
388
- delete sharedConfig.context;
475
+ c.noHydrate = true;
389
476
  const children = props.children;
390
- sharedConfig.context = c;
477
+ c.noHydrate = false;
391
478
  return children;
392
479
  }
393
480
  function ssr(t, ...nodes) {
@@ -446,6 +533,8 @@ function ssrSpread(props, isSVG, skipChildren) {
446
533
  result += `class="${ssrClassList(value)}"`;
447
534
  } else if (BooleanAttributes.has(prop)) {
448
535
  if (value) result += prop;else continue;
536
+ } else if (prop === "ref" || prop.slice(0, 2) === "on") {
537
+ continue;
449
538
  } else {
450
539
  result += `${Aliases[prop] || prop}="${escape(value, true)}"`;
451
540
  }
@@ -513,26 +602,13 @@ function resolveSSRNode(node) {
513
602
  }
514
603
  function getHydrationKey() {
515
604
  const hydrate = sharedConfig.context;
516
- return hydrate && `${hydrate.id}${hydrate.count++}`;
605
+ return hydrate && !hydrate.noHydrate && `${hydrate.id}${hydrate.count++}`;
517
606
  }
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>`;
607
+ function generateHydrationScript({
608
+ eventNames = ["click", "input"],
609
+ nonce
610
+ }) {
611
+ 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
612
  }
537
613
  function injectAssets(assets, html) {
538
614
  for (let i = 0; i < assets.length; i++) {
@@ -540,6 +616,33 @@ function injectAssets(assets, html) {
540
616
  }
541
617
  return html;
542
618
  }
619
+ const FRAGMENT_REPLACE = /<!\[([\d.]+)\]>/;
620
+ function asyncWrap(fn) {
621
+ return new Promise(resolve => {
622
+ const registry = new Set();
623
+ const cache = Object.create(null);
624
+ sharedConfig.context.registerFragment = register;
625
+ const rendered = fn();
626
+ if (!registry.size) resolve(rendered);
627
+ function register(key) {
628
+ registry.add(key);
629
+ return value => {
630
+ if (value) cache[key] = value;
631
+ registry.delete(key);
632
+ if (!registry.size) Promise.resolve().then(() => {
633
+ let source = resolveSSRNode(rendered);
634
+ let final = "";
635
+ let match;
636
+ while (match = source.match(FRAGMENT_REPLACE)) {
637
+ final += source.substring(0, match.index);
638
+ source = cache[match[1]] + source.substring(match.index + match[0].length);
639
+ }
640
+ resolve(final + source);
641
+ });
642
+ };
643
+ }
644
+ });
645
+ }
543
646
 
544
647
  const isServer = true;
545
648
  function spread() {}
@@ -558,4 +661,4 @@ function Portal(props) {
558
661
  return "";
559
662
  }
560
663
 
561
- export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
664
+ 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;