@solidjs/web 2.0.0-beta.23 → 2.0.0-beta.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.cjs +30 -12
- package/dist/server.js +30 -12
- package/frames/dist/client.cjs +52 -8
- package/frames/dist/client.js +52 -8
- package/frames/dist/server.cjs +31 -13
- package/frames/dist/server.js +31 -13
- package/package.json +7 -6
- package/server-functions/dist/server.cjs +8 -4
- package/server-functions/dist/server.js +8 -4
- package/types/frames/client.d.ts +13 -49
- package/types/frames/frame-client.d.ts +17 -0
- package/types/frames/frame-transport.d.ts +5 -4
- package/types/frames/server.d.ts +1 -20
- package/types/server-functions/server.d.ts +17 -0
- package/types/server-functions/shared.d.ts +17 -0
- package/types-cjs/frames/client.d.cts +13 -49
- package/types-cjs/frames/frame-client.d.cts +17 -0
- package/types-cjs/frames/frame-transport.d.cts +5 -4
- package/types-cjs/frames/server.d.cts +1 -20
- package/types-cjs/server-functions/server.d.cts +17 -0
- package/types-cjs/server-functions/shared.d.cts +17 -0
package/dist/server.cjs
CHANGED
|
@@ -313,7 +313,8 @@ function renderToStream(code, options = {}) {
|
|
|
313
313
|
}
|
|
314
314
|
tasks += task + ";";
|
|
315
315
|
if (!timer && firstFlushed) {
|
|
316
|
-
timer =
|
|
316
|
+
timer = true;
|
|
317
|
+
queue(() => queue(writeTasks));
|
|
317
318
|
}
|
|
318
319
|
};
|
|
319
320
|
const onDone = () => {
|
|
@@ -396,7 +397,6 @@ function renderToStream(code, options = {}) {
|
|
|
396
397
|
buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
|
|
397
398
|
tasks = "";
|
|
398
399
|
}
|
|
399
|
-
timer && clearTimeout(timer);
|
|
400
400
|
timer = null;
|
|
401
401
|
};
|
|
402
402
|
let context;
|
|
@@ -648,6 +648,26 @@ function renderToStream(code, options = {}) {
|
|
|
648
648
|
});
|
|
649
649
|
shellCompleted = true;
|
|
650
650
|
}
|
|
651
|
+
const MIN_DRAIN_TURNS = 8;
|
|
652
|
+
let lastBlockingSize = -1;
|
|
653
|
+
let lastRegistrySize = -1;
|
|
654
|
+
let drainTurn = 0;
|
|
655
|
+
const scheduleFlush = fn => {
|
|
656
|
+
const attempt = () => {
|
|
657
|
+
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
658
|
+
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
659
|
+
lastRegistrySize = registry.size;
|
|
660
|
+
queue(attempt);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
fn();
|
|
664
|
+
};
|
|
665
|
+
const progressed = blockingPromises.size !== lastBlockingSize;
|
|
666
|
+
lastBlockingSize = blockingPromises.size;
|
|
667
|
+
lastRegistrySize = -1;
|
|
668
|
+
drainTurn = 0;
|
|
669
|
+
progressed ? queue(attempt) : setTimeout(attempt);
|
|
670
|
+
};
|
|
651
671
|
return {
|
|
652
672
|
then(fn) {
|
|
653
673
|
function complete() {
|
|
@@ -663,7 +683,7 @@ function renderToStream(code, options = {}) {
|
|
|
663
683
|
} else onCompleteAll = complete;
|
|
664
684
|
function flush() {
|
|
665
685
|
allSettled(blockingPromises).then(() => {
|
|
666
|
-
|
|
686
|
+
scheduleFlush(() => {
|
|
667
687
|
if (!resolveRootHoles()) return flush();
|
|
668
688
|
queue(flushEnd);
|
|
669
689
|
});
|
|
@@ -674,7 +694,7 @@ function renderToStream(code, options = {}) {
|
|
|
674
694
|
pipe(w) {
|
|
675
695
|
function flush() {
|
|
676
696
|
allSettled(blockingPromises).then(() => {
|
|
677
|
-
|
|
697
|
+
scheduleFlush(() => {
|
|
678
698
|
doShell();
|
|
679
699
|
if (!shellCompleted) return flush();
|
|
680
700
|
buffer = writable = w;
|
|
@@ -694,7 +714,7 @@ function renderToStream(code, options = {}) {
|
|
|
694
714
|
const p = new Promise(r => resolve = r);
|
|
695
715
|
function flush() {
|
|
696
716
|
allSettled(blockingPromises).then(() => {
|
|
697
|
-
|
|
717
|
+
scheduleFlush(() => {
|
|
698
718
|
doShell();
|
|
699
719
|
if (!shellCompleted) return flush();
|
|
700
720
|
const encoder = new TextEncoder();
|
|
@@ -997,14 +1017,12 @@ function escape(s, attr) {
|
|
|
997
1017
|
}
|
|
998
1018
|
return s;
|
|
999
1019
|
}
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
const c = s.charCodeAt(i);
|
|
1004
|
-
if (c === 38 || c === delimCode) return escapeSlow(s, attr, i);
|
|
1005
|
-
}
|
|
1006
|
-
return s;
|
|
1020
|
+
const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
|
|
1021
|
+
if (i < 0) return s;
|
|
1022
|
+
return escapeSlow(s, attr, i);
|
|
1007
1023
|
}
|
|
1024
|
+
const ESCAPE_CONTENT = /[&<]/;
|
|
1025
|
+
const ESCAPE_ATTR = /[&"]/;
|
|
1008
1026
|
function escapeSlow(s, attr, start) {
|
|
1009
1027
|
const delim = attr ? '"' : "<";
|
|
1010
1028
|
const delimCode = attr ? 34 : 60;
|
package/dist/server.js
CHANGED
|
@@ -312,7 +312,8 @@ function renderToStream(code, options = {}) {
|
|
|
312
312
|
}
|
|
313
313
|
tasks += task + ";";
|
|
314
314
|
if (!timer && firstFlushed) {
|
|
315
|
-
timer =
|
|
315
|
+
timer = true;
|
|
316
|
+
queue(() => queue(writeTasks));
|
|
316
317
|
}
|
|
317
318
|
};
|
|
318
319
|
const onDone = () => {
|
|
@@ -395,7 +396,6 @@ function renderToStream(code, options = {}) {
|
|
|
395
396
|
buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
|
|
396
397
|
tasks = "";
|
|
397
398
|
}
|
|
398
|
-
timer && clearTimeout(timer);
|
|
399
399
|
timer = null;
|
|
400
400
|
};
|
|
401
401
|
let context;
|
|
@@ -647,6 +647,26 @@ function renderToStream(code, options = {}) {
|
|
|
647
647
|
});
|
|
648
648
|
shellCompleted = true;
|
|
649
649
|
}
|
|
650
|
+
const MIN_DRAIN_TURNS = 8;
|
|
651
|
+
let lastBlockingSize = -1;
|
|
652
|
+
let lastRegistrySize = -1;
|
|
653
|
+
let drainTurn = 0;
|
|
654
|
+
const scheduleFlush = fn => {
|
|
655
|
+
const attempt = () => {
|
|
656
|
+
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
657
|
+
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
658
|
+
lastRegistrySize = registry.size;
|
|
659
|
+
queue(attempt);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
fn();
|
|
663
|
+
};
|
|
664
|
+
const progressed = blockingPromises.size !== lastBlockingSize;
|
|
665
|
+
lastBlockingSize = blockingPromises.size;
|
|
666
|
+
lastRegistrySize = -1;
|
|
667
|
+
drainTurn = 0;
|
|
668
|
+
progressed ? queue(attempt) : setTimeout(attempt);
|
|
669
|
+
};
|
|
650
670
|
return {
|
|
651
671
|
then(fn) {
|
|
652
672
|
function complete() {
|
|
@@ -662,7 +682,7 @@ function renderToStream(code, options = {}) {
|
|
|
662
682
|
} else onCompleteAll = complete;
|
|
663
683
|
function flush() {
|
|
664
684
|
allSettled(blockingPromises).then(() => {
|
|
665
|
-
|
|
685
|
+
scheduleFlush(() => {
|
|
666
686
|
if (!resolveRootHoles()) return flush();
|
|
667
687
|
queue(flushEnd);
|
|
668
688
|
});
|
|
@@ -673,7 +693,7 @@ function renderToStream(code, options = {}) {
|
|
|
673
693
|
pipe(w) {
|
|
674
694
|
function flush() {
|
|
675
695
|
allSettled(blockingPromises).then(() => {
|
|
676
|
-
|
|
696
|
+
scheduleFlush(() => {
|
|
677
697
|
doShell();
|
|
678
698
|
if (!shellCompleted) return flush();
|
|
679
699
|
buffer = writable = w;
|
|
@@ -693,7 +713,7 @@ function renderToStream(code, options = {}) {
|
|
|
693
713
|
const p = new Promise(r => resolve = r);
|
|
694
714
|
function flush() {
|
|
695
715
|
allSettled(blockingPromises).then(() => {
|
|
696
|
-
|
|
716
|
+
scheduleFlush(() => {
|
|
697
717
|
doShell();
|
|
698
718
|
if (!shellCompleted) return flush();
|
|
699
719
|
const encoder = new TextEncoder();
|
|
@@ -996,14 +1016,12 @@ function escape(s, attr) {
|
|
|
996
1016
|
}
|
|
997
1017
|
return s;
|
|
998
1018
|
}
|
|
999
|
-
const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const c = s.charCodeAt(i);
|
|
1003
|
-
if (c === 38 || c === delimCode) return escapeSlow(s, attr, i);
|
|
1004
|
-
}
|
|
1005
|
-
return s;
|
|
1019
|
+
const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
|
|
1020
|
+
if (i < 0) return s;
|
|
1021
|
+
return escapeSlow(s, attr, i);
|
|
1006
1022
|
}
|
|
1023
|
+
const ESCAPE_CONTENT = /[&<]/;
|
|
1024
|
+
const ESCAPE_ATTR = /[&"]/;
|
|
1007
1025
|
function escapeSlow(s, attr, start) {
|
|
1008
1026
|
const delim = attr ? '"' : "<";
|
|
1009
1027
|
const delimCode = attr ? 34 : 60;
|
package/frames/dist/client.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var solidJs = require('solid-js');
|
|
4
|
+
var client = require('@solidjs/web/server-functions/client');
|
|
4
5
|
var seroval = require('seroval');
|
|
5
6
|
var web = require('seroval-plugins/web');
|
|
6
7
|
|
|
@@ -126,7 +127,20 @@ function createFrameHost(options = {}) {
|
|
|
126
127
|
const buffered = pending.get(id);
|
|
127
128
|
if (buffered) {
|
|
128
129
|
pending.delete(id);
|
|
129
|
-
|
|
130
|
+
const records = {};
|
|
131
|
+
let version;
|
|
132
|
+
for (const chunk of buffered) {
|
|
133
|
+
if (chunk.type === "data") {
|
|
134
|
+
options.applyData && options.applyData(chunk);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
version = chunk.version;
|
|
138
|
+
Object.assign(records, chunkToRecords(chunk));
|
|
139
|
+
}
|
|
140
|
+
if (version !== undefined) frame.apply({
|
|
141
|
+
version,
|
|
142
|
+
r: records
|
|
143
|
+
});
|
|
130
144
|
}
|
|
131
145
|
},
|
|
132
146
|
unregister(id, frame) {
|
|
@@ -346,11 +360,11 @@ class FrameImpl {
|
|
|
346
360
|
this.#runSlotCleanups(occurrence);
|
|
347
361
|
}
|
|
348
362
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
349
|
-
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
363
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
350
364
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
351
365
|
this.#slotNodes.set(occurrence, nodes);
|
|
352
366
|
this.#mountedSlots.add(occurrence);
|
|
353
|
-
|
|
367
|
+
this.#discoverRegions(occurrence, start);
|
|
354
368
|
this.#bindRegions(occurrence);
|
|
355
369
|
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
356
370
|
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
@@ -367,11 +381,12 @@ class FrameImpl {
|
|
|
367
381
|
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
368
382
|
}
|
|
369
383
|
}
|
|
370
|
-
#invokeSlot(occurrence, callback, record, start) {
|
|
384
|
+
#invokeSlot(occurrence, callback, record, start, adopted) {
|
|
371
385
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
372
386
|
const ctx = {
|
|
373
387
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
374
388
|
key: occurrence,
|
|
389
|
+
adopted: !!adopted,
|
|
375
390
|
onCleanup: fn => cleanups.push(fn),
|
|
376
391
|
existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
|
|
377
392
|
};
|
|
@@ -514,11 +529,22 @@ class FrameImpl {
|
|
|
514
529
|
}
|
|
515
530
|
#refArgsUnchanged(occurrence, record) {
|
|
516
531
|
const old = this.#slotArgs.get(occurrence);
|
|
517
|
-
if (!
|
|
518
|
-
|
|
532
|
+
if (!record || record.kind !== "slot") return false;
|
|
533
|
+
if (old && old.kind !== "slot") return false;
|
|
534
|
+
const a = old && old.args || {};
|
|
519
535
|
const b = record.args || {};
|
|
520
536
|
const ka = Object.keys(a);
|
|
521
|
-
|
|
537
|
+
const kb = Object.keys(b);
|
|
538
|
+
if (kb.length < ka.length) return false;
|
|
539
|
+
if (kb.length !== ka.length) {
|
|
540
|
+
const regions = this.#slotRegions.get(occurrence);
|
|
541
|
+
for (const key of kb) {
|
|
542
|
+
if (key in a) continue;
|
|
543
|
+
const vb = b[key];
|
|
544
|
+
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
545
|
+
if (!regions || !regions.has(vb.$frame)) return false;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
522
548
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
523
549
|
for (const key of ka) {
|
|
524
550
|
const va = a[key];
|
|
@@ -1258,6 +1284,9 @@ function tableFor(id) {
|
|
|
1258
1284
|
for (const [root, t] of tables) if (id.startsWith(root + ".")) return t;
|
|
1259
1285
|
return undefined;
|
|
1260
1286
|
}
|
|
1287
|
+
function beginStream(frameId) {
|
|
1288
|
+
tables.set(frameId, createJSONDataTable());
|
|
1289
|
+
}
|
|
1261
1290
|
function getFrameHost() {
|
|
1262
1291
|
if (!sharedHost) {
|
|
1263
1292
|
sharedHost = createFrameHost({
|
|
@@ -1322,7 +1351,7 @@ function slotsFor(props) {
|
|
|
1322
1351
|
const v = props[prop];
|
|
1323
1352
|
return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
|
|
1324
1353
|
};
|
|
1325
|
-
if (ctx && ctx.frame && ctx.existing && ctx.existing.length) {
|
|
1354
|
+
if (ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length) {
|
|
1326
1355
|
return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
|
|
1327
1356
|
}
|
|
1328
1357
|
return render();
|
|
@@ -1427,6 +1456,21 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1427
1456
|
};
|
|
1428
1457
|
}
|
|
1429
1458
|
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1459
|
+
client.configureServerFunctionsClient({
|
|
1460
|
+
responseHandler: createServerComponentHandler({
|
|
1461
|
+
host,
|
|
1462
|
+
capture: () => solidJs.getOwner() ?? undefined,
|
|
1463
|
+
component: frameId => boundaryComponent(host, frameId),
|
|
1464
|
+
onStream: frameId => beginStream(frameId),
|
|
1465
|
+
documentComponent: functionId => g._$SC.c[functionId],
|
|
1466
|
+
intercept: ({
|
|
1467
|
+
id
|
|
1468
|
+
}) => {
|
|
1469
|
+
if (claimedBoundaries.has(id) || !findBoundaryRange(id)) return undefined;
|
|
1470
|
+
return g._$SC.r(id);
|
|
1471
|
+
}
|
|
1472
|
+
})
|
|
1473
|
+
});
|
|
1430
1474
|
}
|
|
1431
1475
|
|
|
1432
1476
|
exports.FRAME_APPLIED_EVENT = FRAME_APPLIED_EVENT;
|
package/frames/dist/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getOwner, onCleanup, runWithOwner, sharedConfig, createOwner } from 'solid-js';
|
|
2
|
+
import { configureServerFunctionsClient } from '@solidjs/web/server-functions/client';
|
|
2
3
|
import { fromCrossJSON, Feature } from 'seroval';
|
|
3
4
|
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
4
5
|
|
|
@@ -124,7 +125,20 @@ function createFrameHost(options = {}) {
|
|
|
124
125
|
const buffered = pending.get(id);
|
|
125
126
|
if (buffered) {
|
|
126
127
|
pending.delete(id);
|
|
127
|
-
|
|
128
|
+
const records = {};
|
|
129
|
+
let version;
|
|
130
|
+
for (const chunk of buffered) {
|
|
131
|
+
if (chunk.type === "data") {
|
|
132
|
+
options.applyData && options.applyData(chunk);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
version = chunk.version;
|
|
136
|
+
Object.assign(records, chunkToRecords(chunk));
|
|
137
|
+
}
|
|
138
|
+
if (version !== undefined) frame.apply({
|
|
139
|
+
version,
|
|
140
|
+
r: records
|
|
141
|
+
});
|
|
128
142
|
}
|
|
129
143
|
},
|
|
130
144
|
unregister(id, frame) {
|
|
@@ -344,11 +358,11 @@ class FrameImpl {
|
|
|
344
358
|
this.#runSlotCleanups(occurrence);
|
|
345
359
|
}
|
|
346
360
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
347
|
-
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
361
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
348
362
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
349
363
|
this.#slotNodes.set(occurrence, nodes);
|
|
350
364
|
this.#mountedSlots.add(occurrence);
|
|
351
|
-
|
|
365
|
+
this.#discoverRegions(occurrence, start);
|
|
352
366
|
this.#bindRegions(occurrence);
|
|
353
367
|
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
354
368
|
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
@@ -365,11 +379,12 @@ class FrameImpl {
|
|
|
365
379
|
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
366
380
|
}
|
|
367
381
|
}
|
|
368
|
-
#invokeSlot(occurrence, callback, record, start) {
|
|
382
|
+
#invokeSlot(occurrence, callback, record, start, adopted) {
|
|
369
383
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
370
384
|
const ctx = {
|
|
371
385
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
372
386
|
key: occurrence,
|
|
387
|
+
adopted: !!adopted,
|
|
373
388
|
onCleanup: fn => cleanups.push(fn),
|
|
374
389
|
existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
|
|
375
390
|
};
|
|
@@ -512,11 +527,22 @@ class FrameImpl {
|
|
|
512
527
|
}
|
|
513
528
|
#refArgsUnchanged(occurrence, record) {
|
|
514
529
|
const old = this.#slotArgs.get(occurrence);
|
|
515
|
-
if (!
|
|
516
|
-
|
|
530
|
+
if (!record || record.kind !== "slot") return false;
|
|
531
|
+
if (old && old.kind !== "slot") return false;
|
|
532
|
+
const a = old && old.args || {};
|
|
517
533
|
const b = record.args || {};
|
|
518
534
|
const ka = Object.keys(a);
|
|
519
|
-
|
|
535
|
+
const kb = Object.keys(b);
|
|
536
|
+
if (kb.length < ka.length) return false;
|
|
537
|
+
if (kb.length !== ka.length) {
|
|
538
|
+
const regions = this.#slotRegions.get(occurrence);
|
|
539
|
+
for (const key of kb) {
|
|
540
|
+
if (key in a) continue;
|
|
541
|
+
const vb = b[key];
|
|
542
|
+
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
543
|
+
if (!regions || !regions.has(vb.$frame)) return false;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
520
546
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
521
547
|
for (const key of ka) {
|
|
522
548
|
const va = a[key];
|
|
@@ -1256,6 +1282,9 @@ function tableFor(id) {
|
|
|
1256
1282
|
for (const [root, t] of tables) if (id.startsWith(root + ".")) return t;
|
|
1257
1283
|
return undefined;
|
|
1258
1284
|
}
|
|
1285
|
+
function beginStream(frameId) {
|
|
1286
|
+
tables.set(frameId, createJSONDataTable());
|
|
1287
|
+
}
|
|
1259
1288
|
function getFrameHost() {
|
|
1260
1289
|
if (!sharedHost) {
|
|
1261
1290
|
sharedHost = createFrameHost({
|
|
@@ -1320,7 +1349,7 @@ function slotsFor(props) {
|
|
|
1320
1349
|
const v = props[prop];
|
|
1321
1350
|
return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
|
|
1322
1351
|
};
|
|
1323
|
-
if (ctx && ctx.frame && ctx.existing && ctx.existing.length) {
|
|
1352
|
+
if (ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length) {
|
|
1324
1353
|
return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
|
|
1325
1354
|
}
|
|
1326
1355
|
return render();
|
|
@@ -1425,6 +1454,21 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1425
1454
|
};
|
|
1426
1455
|
}
|
|
1427
1456
|
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1457
|
+
configureServerFunctionsClient({
|
|
1458
|
+
responseHandler: createServerComponentHandler({
|
|
1459
|
+
host,
|
|
1460
|
+
capture: () => getOwner() ?? undefined,
|
|
1461
|
+
component: frameId => boundaryComponent(host, frameId),
|
|
1462
|
+
onStream: frameId => beginStream(frameId),
|
|
1463
|
+
documentComponent: functionId => g._$SC.c[functionId],
|
|
1464
|
+
intercept: ({
|
|
1465
|
+
id
|
|
1466
|
+
}) => {
|
|
1467
|
+
if (claimedBoundaries.has(id) || !findBoundaryRange(id)) return undefined;
|
|
1468
|
+
return g._$SC.r(id);
|
|
1469
|
+
}
|
|
1470
|
+
})
|
|
1471
|
+
});
|
|
1428
1472
|
}
|
|
1429
1473
|
|
|
1430
1474
|
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, createFrame, createFrameHost, createFrameInsertable, createJSONDataTable, createServerComponentHandler, getFrameHost, installServerComponents, isFrameStreamResponse };
|
package/frames/dist/server.cjs
CHANGED
|
@@ -266,7 +266,8 @@ function renderToStream(code, options = {}) {
|
|
|
266
266
|
}
|
|
267
267
|
tasks += task + ";";
|
|
268
268
|
if (!timer && firstFlushed) {
|
|
269
|
-
timer =
|
|
269
|
+
timer = true;
|
|
270
|
+
queue(() => queue(writeTasks));
|
|
270
271
|
}
|
|
271
272
|
};
|
|
272
273
|
const onDone = () => {
|
|
@@ -349,7 +350,6 @@ function renderToStream(code, options = {}) {
|
|
|
349
350
|
buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
|
|
350
351
|
tasks = "";
|
|
351
352
|
}
|
|
352
|
-
timer && clearTimeout(timer);
|
|
353
353
|
timer = null;
|
|
354
354
|
};
|
|
355
355
|
let context;
|
|
@@ -601,6 +601,26 @@ function renderToStream(code, options = {}) {
|
|
|
601
601
|
});
|
|
602
602
|
shellCompleted = true;
|
|
603
603
|
}
|
|
604
|
+
const MIN_DRAIN_TURNS = 8;
|
|
605
|
+
let lastBlockingSize = -1;
|
|
606
|
+
let lastRegistrySize = -1;
|
|
607
|
+
let drainTurn = 0;
|
|
608
|
+
const scheduleFlush = fn => {
|
|
609
|
+
const attempt = () => {
|
|
610
|
+
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
611
|
+
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
612
|
+
lastRegistrySize = registry.size;
|
|
613
|
+
queue(attempt);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
fn();
|
|
617
|
+
};
|
|
618
|
+
const progressed = blockingPromises.size !== lastBlockingSize;
|
|
619
|
+
lastBlockingSize = blockingPromises.size;
|
|
620
|
+
lastRegistrySize = -1;
|
|
621
|
+
drainTurn = 0;
|
|
622
|
+
progressed ? queue(attempt) : setTimeout(attempt);
|
|
623
|
+
};
|
|
604
624
|
return {
|
|
605
625
|
then(fn) {
|
|
606
626
|
function complete() {
|
|
@@ -616,7 +636,7 @@ function renderToStream(code, options = {}) {
|
|
|
616
636
|
} else onCompleteAll = complete;
|
|
617
637
|
function flush() {
|
|
618
638
|
allSettled(blockingPromises).then(() => {
|
|
619
|
-
|
|
639
|
+
scheduleFlush(() => {
|
|
620
640
|
if (!resolveRootHoles()) return flush();
|
|
621
641
|
queue(flushEnd);
|
|
622
642
|
});
|
|
@@ -627,7 +647,7 @@ function renderToStream(code, options = {}) {
|
|
|
627
647
|
pipe(w) {
|
|
628
648
|
function flush() {
|
|
629
649
|
allSettled(blockingPromises).then(() => {
|
|
630
|
-
|
|
650
|
+
scheduleFlush(() => {
|
|
631
651
|
doShell();
|
|
632
652
|
if (!shellCompleted) return flush();
|
|
633
653
|
buffer = writable = w;
|
|
@@ -647,7 +667,7 @@ function renderToStream(code, options = {}) {
|
|
|
647
667
|
const p = new Promise(r => resolve = r);
|
|
648
668
|
function flush() {
|
|
649
669
|
allSettled(blockingPromises).then(() => {
|
|
650
|
-
|
|
670
|
+
scheduleFlush(() => {
|
|
651
671
|
doShell();
|
|
652
672
|
if (!shellCompleted) return flush();
|
|
653
673
|
const encoder = new TextEncoder();
|
|
@@ -861,14 +881,12 @@ function escape(s, attr) {
|
|
|
861
881
|
}
|
|
862
882
|
return s;
|
|
863
883
|
}
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
const c = s.charCodeAt(i);
|
|
868
|
-
if (c === 38 || c === delimCode) return escapeSlow(s, attr, i);
|
|
869
|
-
}
|
|
870
|
-
return s;
|
|
884
|
+
const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
|
|
885
|
+
if (i < 0) return s;
|
|
886
|
+
return escapeSlow(s, attr, i);
|
|
871
887
|
}
|
|
888
|
+
const ESCAPE_CONTENT = /[&<]/;
|
|
889
|
+
const ESCAPE_ATTR = /[&"]/;
|
|
872
890
|
function escapeSlow(s, attr, start) {
|
|
873
891
|
const delim = attr ? '"' : "<";
|
|
874
892
|
const delimCode = attr ? 34 : 60;
|
|
@@ -1516,7 +1534,7 @@ function renderedHtmlOf(out) {
|
|
|
1516
1534
|
try {
|
|
1517
1535
|
const res = solidJs.sharedConfig.context.resolve(out);
|
|
1518
1536
|
if (res && res.t && (!res.h || !res.h.length)) {
|
|
1519
|
-
return res.t[0].replace(/<!--[^>]*-->/g, "");
|
|
1537
|
+
return res.t[0].replace(/<!--[^>]*-->/g, "").replace(/ _hk=("[^"]*"|[^\s>]+)/g, "");
|
|
1520
1538
|
}
|
|
1521
1539
|
} catch (e) {}
|
|
1522
1540
|
return null;
|
package/frames/dist/server.js
CHANGED
|
@@ -264,7 +264,8 @@ function renderToStream(code, options = {}) {
|
|
|
264
264
|
}
|
|
265
265
|
tasks += task + ";";
|
|
266
266
|
if (!timer && firstFlushed) {
|
|
267
|
-
timer =
|
|
267
|
+
timer = true;
|
|
268
|
+
queue(() => queue(writeTasks));
|
|
268
269
|
}
|
|
269
270
|
};
|
|
270
271
|
const onDone = () => {
|
|
@@ -347,7 +348,6 @@ function renderToStream(code, options = {}) {
|
|
|
347
348
|
buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
|
|
348
349
|
tasks = "";
|
|
349
350
|
}
|
|
350
|
-
timer && clearTimeout(timer);
|
|
351
351
|
timer = null;
|
|
352
352
|
};
|
|
353
353
|
let context;
|
|
@@ -599,6 +599,26 @@ function renderToStream(code, options = {}) {
|
|
|
599
599
|
});
|
|
600
600
|
shellCompleted = true;
|
|
601
601
|
}
|
|
602
|
+
const MIN_DRAIN_TURNS = 8;
|
|
603
|
+
let lastBlockingSize = -1;
|
|
604
|
+
let lastRegistrySize = -1;
|
|
605
|
+
let drainTurn = 0;
|
|
606
|
+
const scheduleFlush = fn => {
|
|
607
|
+
const attempt = () => {
|
|
608
|
+
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
609
|
+
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
610
|
+
lastRegistrySize = registry.size;
|
|
611
|
+
queue(attempt);
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
fn();
|
|
615
|
+
};
|
|
616
|
+
const progressed = blockingPromises.size !== lastBlockingSize;
|
|
617
|
+
lastBlockingSize = blockingPromises.size;
|
|
618
|
+
lastRegistrySize = -1;
|
|
619
|
+
drainTurn = 0;
|
|
620
|
+
progressed ? queue(attempt) : setTimeout(attempt);
|
|
621
|
+
};
|
|
602
622
|
return {
|
|
603
623
|
then(fn) {
|
|
604
624
|
function complete() {
|
|
@@ -614,7 +634,7 @@ function renderToStream(code, options = {}) {
|
|
|
614
634
|
} else onCompleteAll = complete;
|
|
615
635
|
function flush() {
|
|
616
636
|
allSettled(blockingPromises).then(() => {
|
|
617
|
-
|
|
637
|
+
scheduleFlush(() => {
|
|
618
638
|
if (!resolveRootHoles()) return flush();
|
|
619
639
|
queue(flushEnd);
|
|
620
640
|
});
|
|
@@ -625,7 +645,7 @@ function renderToStream(code, options = {}) {
|
|
|
625
645
|
pipe(w) {
|
|
626
646
|
function flush() {
|
|
627
647
|
allSettled(blockingPromises).then(() => {
|
|
628
|
-
|
|
648
|
+
scheduleFlush(() => {
|
|
629
649
|
doShell();
|
|
630
650
|
if (!shellCompleted) return flush();
|
|
631
651
|
buffer = writable = w;
|
|
@@ -645,7 +665,7 @@ function renderToStream(code, options = {}) {
|
|
|
645
665
|
const p = new Promise(r => resolve = r);
|
|
646
666
|
function flush() {
|
|
647
667
|
allSettled(blockingPromises).then(() => {
|
|
648
|
-
|
|
668
|
+
scheduleFlush(() => {
|
|
649
669
|
doShell();
|
|
650
670
|
if (!shellCompleted) return flush();
|
|
651
671
|
const encoder = new TextEncoder();
|
|
@@ -859,14 +879,12 @@ function escape(s, attr) {
|
|
|
859
879
|
}
|
|
860
880
|
return s;
|
|
861
881
|
}
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
const c = s.charCodeAt(i);
|
|
866
|
-
if (c === 38 || c === delimCode) return escapeSlow(s, attr, i);
|
|
867
|
-
}
|
|
868
|
-
return s;
|
|
882
|
+
const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
|
|
883
|
+
if (i < 0) return s;
|
|
884
|
+
return escapeSlow(s, attr, i);
|
|
869
885
|
}
|
|
886
|
+
const ESCAPE_CONTENT = /[&<]/;
|
|
887
|
+
const ESCAPE_ATTR = /[&"]/;
|
|
870
888
|
function escapeSlow(s, attr, start) {
|
|
871
889
|
const delim = attr ? '"' : "<";
|
|
872
890
|
const delimCode = attr ? 34 : 60;
|
|
@@ -1514,7 +1532,7 @@ function renderedHtmlOf(out) {
|
|
|
1514
1532
|
try {
|
|
1515
1533
|
const res = sharedConfig.context.resolve(out);
|
|
1516
1534
|
if (res && res.t && (!res.h || !res.h.length)) {
|
|
1517
|
-
return res.t[0].replace(/<!--[^>]*-->/g, "");
|
|
1535
|
+
return res.t[0].replace(/<!--[^>]*-->/g, "").replace(/ _hk=("[^"]*"|[^\s>]+)/g, "");
|
|
1518
1536
|
}
|
|
1519
1537
|
} catch (e) {}
|
|
1520
1538
|
return null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/web",
|
|
3
3
|
"description": "Solid's web runtime: client rendering, hydration, SSR, and DOM-specific control flow (Portal, Dynamic).",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.25",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://solidjs.com",
|
|
@@ -296,25 +296,26 @@
|
|
|
296
296
|
"seroval-plugins": "~1.5.4"
|
|
297
297
|
},
|
|
298
298
|
"peerDependencies": {
|
|
299
|
-
"solid-js": "^2.0.0-beta.
|
|
299
|
+
"solid-js": "^2.0.0-beta.25"
|
|
300
300
|
},
|
|
301
301
|
"devDependencies": {
|
|
302
|
-
"solid-js": "2.0.0-beta.
|
|
302
|
+
"solid-js": "2.0.0-beta.25"
|
|
303
303
|
},
|
|
304
304
|
"scripts": {
|
|
305
305
|
"build": "npm-run-all -nl build:clean types:copy-jsx build:js",
|
|
306
306
|
"build:clean": "rimraf dist/",
|
|
307
307
|
"build:js": "rollup -c",
|
|
308
308
|
"link": "symlink-dir . node_modules/@solidjs/web",
|
|
309
|
-
"types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:copy-
|
|
310
|
-
"types:clean": "rimraf types/ types-cjs/ storage/types/ storage/types-cjs/ serialization/types/ serialization/types-cjs/",
|
|
309
|
+
"types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:copy-server-functions types:web-frames types:copy-serialization types:copy-frames types:cjs",
|
|
310
|
+
"types:clean": "rimraf types/ types-cjs/ storage/types/ storage/types-cjs/ serialization/types/ serialization/types-cjs/ frames/types/",
|
|
311
311
|
"types:copy-jsx": "ncp ../../node_modules/@dom-expressions/runtime/src/jsx.d.ts ./src/jsx.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/jsx-properties.d.ts ./src/jsx-properties.d.ts && dom-expressions-jsx-types --input ./src/jsx.d.ts --element \"SolidElement | Node | ArrayElement\" --import 'import type { Element as SolidElement } from \"solid-js\";'",
|
|
312
312
|
"types:web": "tsc --project ./tsconfig.build.json",
|
|
313
313
|
"types:copy-web": "ncp ../../node_modules/@dom-expressions/runtime/src/client.d.ts ./types/client.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/server.d.ts ./types/server.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/serializer.d.ts ./types/serializer.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/response.d.ts ./types/response.d.ts && ncp ./src/jsx.d.ts ./types/jsx.d.ts && ncp ./src/jsx-properties.d.ts ./types/jsx-properties.d.ts",
|
|
314
314
|
"types:web-storage": "tsc --project ./storage/tsconfig.build.json",
|
|
315
|
+
"types:web-frames": "tsc --project ./frames/tsconfig.build.json",
|
|
315
316
|
"types:copy-serialization": "node -e \"fs.mkdirSync('./serialization/types', { recursive: true }); fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/serializer.d.ts', './serialization/types/index.d.ts');\"",
|
|
316
317
|
"types:copy-server-functions": "node -e \"fs.mkdirSync('./types/server-functions', { recursive: true }); for (const f of ['shared', 'client', 'server']) fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/server-functions/' + f + '.d.ts', './types/server-functions/' + f + '.d.ts');\"",
|
|
317
|
-
"types:copy-frames": "node -e \"fs.mkdirSync('./types/frames', { recursive: true }); for (const f of ['frame-client', 'frame-transport', 'frame-sink', 'serializer']) fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/' + f + '.d.ts', './types/frames/' + f + '.d.ts'); for (const f of ['client', 'server']) fs.
|
|
318
|
+
"types:copy-frames": "node -e \"fs.mkdirSync('./types/frames', { recursive: true }); for (const f of ['frame-client', 'frame-transport', 'frame-sink', 'serializer']) fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/' + f + '.d.ts', './types/frames/' + f + '.d.ts'); for (const f of ['client', 'server']) fs.writeFileSync('./types/frames/' + f + '.d.ts', fs.readFileSync('./frames/types/' + f + '.d.ts', 'utf8').replaceAll('@dom-expressions/runtime/src/', './'));\"",
|
|
318
319
|
"types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs ./storage/types ./storage/types-cjs ./serialization/types ./serialization/types-cjs",
|
|
319
320
|
"test": "vitest run && vitest run --config vite.config.server.mjs && vitest run --config vite.config.hydrate.mjs",
|
|
320
321
|
"test:server": "vitest run --config vite.config.server.mjs",
|
|
@@ -332,18 +332,21 @@ async function decodeResponse(response, codecOptions) {
|
|
|
332
332
|
const config = {
|
|
333
333
|
provideEvent: undefined,
|
|
334
334
|
collectFlightData: undefined,
|
|
335
|
+
transformResult: undefined,
|
|
335
336
|
transformDirectResult: undefined,
|
|
336
337
|
endpoint: "/_server"
|
|
337
338
|
};
|
|
338
339
|
function configureServerFunctionsServer({
|
|
339
340
|
provideEvent,
|
|
340
341
|
collectFlightData,
|
|
342
|
+
transformResult,
|
|
341
343
|
transformDirectResult,
|
|
342
344
|
endpoint,
|
|
343
345
|
codec
|
|
344
346
|
} = {}) {
|
|
345
347
|
if (provideEvent !== undefined) config.provideEvent = provideEvent;
|
|
346
348
|
if (collectFlightData !== undefined) config.collectFlightData = collectFlightData;
|
|
349
|
+
if (transformResult !== undefined) config.transformResult = transformResult;
|
|
347
350
|
if (transformDirectResult !== undefined) config.transformDirectResult = transformDirectResult;
|
|
348
351
|
if (endpoint !== undefined) config.endpoint = endpoint;
|
|
349
352
|
if (codec !== undefined) configureServerFunctionsCodec(codec);
|
|
@@ -526,6 +529,7 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
526
529
|
};
|
|
527
530
|
const provide = options.provideEvent || provideEvent;
|
|
528
531
|
const flightHook = options.collectFlightData !== undefined ? options.collectFlightData : config.collectFlightData;
|
|
532
|
+
const transformResult = options.transformResult !== undefined ? options.transformResult : config.transformResult;
|
|
529
533
|
const collectsFlight = !!(flightHook && instance && request.headers.has(SINGLE_FLIGHT_HEADER));
|
|
530
534
|
const parsed = await parseArguments(request, url, instance, codec);
|
|
531
535
|
const headers = new Headers();
|
|
@@ -536,8 +540,8 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
536
540
|
};
|
|
537
541
|
return serverFunction(...parsed);
|
|
538
542
|
});
|
|
539
|
-
if (
|
|
540
|
-
result = await
|
|
543
|
+
if (transformResult) {
|
|
544
|
+
result = await transformResult(event, result, {
|
|
541
545
|
instance,
|
|
542
546
|
request
|
|
543
547
|
});
|
|
@@ -592,8 +596,8 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
592
596
|
return encodeResult(result, headers, status, codec);
|
|
593
597
|
} catch (x) {
|
|
594
598
|
if (x instanceof Response || isResponseEnvelope(x)) {
|
|
595
|
-
if (
|
|
596
|
-
x = await
|
|
599
|
+
if (transformResult) {
|
|
600
|
+
x = await transformResult(event, x, {
|
|
597
601
|
instance,
|
|
598
602
|
request,
|
|
599
603
|
thrown: true
|
|
@@ -330,18 +330,21 @@ async function decodeResponse(response, codecOptions) {
|
|
|
330
330
|
const config = {
|
|
331
331
|
provideEvent: undefined,
|
|
332
332
|
collectFlightData: undefined,
|
|
333
|
+
transformResult: undefined,
|
|
333
334
|
transformDirectResult: undefined,
|
|
334
335
|
endpoint: "/_server"
|
|
335
336
|
};
|
|
336
337
|
function configureServerFunctionsServer({
|
|
337
338
|
provideEvent,
|
|
338
339
|
collectFlightData,
|
|
340
|
+
transformResult,
|
|
339
341
|
transformDirectResult,
|
|
340
342
|
endpoint,
|
|
341
343
|
codec
|
|
342
344
|
} = {}) {
|
|
343
345
|
if (provideEvent !== undefined) config.provideEvent = provideEvent;
|
|
344
346
|
if (collectFlightData !== undefined) config.collectFlightData = collectFlightData;
|
|
347
|
+
if (transformResult !== undefined) config.transformResult = transformResult;
|
|
345
348
|
if (transformDirectResult !== undefined) config.transformDirectResult = transformDirectResult;
|
|
346
349
|
if (endpoint !== undefined) config.endpoint = endpoint;
|
|
347
350
|
if (codec !== undefined) configureServerFunctionsCodec(codec);
|
|
@@ -524,6 +527,7 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
524
527
|
};
|
|
525
528
|
const provide = options.provideEvent || provideEvent;
|
|
526
529
|
const flightHook = options.collectFlightData !== undefined ? options.collectFlightData : config.collectFlightData;
|
|
530
|
+
const transformResult = options.transformResult !== undefined ? options.transformResult : config.transformResult;
|
|
527
531
|
const collectsFlight = !!(flightHook && instance && request.headers.has(SINGLE_FLIGHT_HEADER));
|
|
528
532
|
const parsed = await parseArguments(request, url, instance, codec);
|
|
529
533
|
const headers = new Headers();
|
|
@@ -534,8 +538,8 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
534
538
|
};
|
|
535
539
|
return serverFunction(...parsed);
|
|
536
540
|
});
|
|
537
|
-
if (
|
|
538
|
-
result = await
|
|
541
|
+
if (transformResult) {
|
|
542
|
+
result = await transformResult(event, result, {
|
|
539
543
|
instance,
|
|
540
544
|
request
|
|
541
545
|
});
|
|
@@ -590,8 +594,8 @@ async function handleServerFunctionRequest(request, options = {}) {
|
|
|
590
594
|
return encodeResult(result, headers, status, codec);
|
|
591
595
|
} catch (x) {
|
|
592
596
|
if (x instanceof Response || isResponseEnvelope(x)) {
|
|
593
|
-
if (
|
|
594
|
-
x = await
|
|
597
|
+
if (transformResult) {
|
|
598
|
+
x = await transformResult(event, x, {
|
|
595
599
|
instance,
|
|
596
600
|
request,
|
|
597
601
|
thrown: true
|
package/types/frames/client.d.ts
CHANGED
|
@@ -1,53 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* boundaries. There is deliberately no server-component API here beyond
|
|
4
|
-
* `installServerComponents()`: `dynamic` + server functions IS the client
|
|
5
|
-
* surface — a server-function call whose response is a frame stream
|
|
6
|
-
* resolves with a stable per-call-site component.
|
|
7
|
-
*
|
|
8
|
-
* Copied next to the runtime's frame d.ts files at publish (see
|
|
9
|
-
* types:copy-frames), so the relative imports below resolve in-place.
|
|
10
|
-
*/
|
|
11
|
-
export {
|
|
12
|
-
createFrame,
|
|
13
|
-
createFrameHost,
|
|
14
|
-
createFrameInsertable,
|
|
15
|
-
FRAME_APPLIED_EVENT
|
|
16
|
-
} from "./frame-client.js";
|
|
17
|
-
export type {
|
|
18
|
-
Frame,
|
|
19
|
-
FrameChunk,
|
|
20
|
-
FrameHost,
|
|
21
|
-
FrameHostOptions,
|
|
22
|
-
FrameOptions,
|
|
23
|
-
FrameWrite,
|
|
24
|
-
Slot,
|
|
25
|
-
SlotContext
|
|
26
|
-
} from "./frame-client.js";
|
|
27
|
-
export {
|
|
28
|
-
FRAME_STREAM_HEADER,
|
|
29
|
-
applyFrameResponse,
|
|
30
|
-
isFrameStreamResponse,
|
|
31
|
-
createServerComponentHandler
|
|
32
|
-
} from "./frame-transport.js";
|
|
1
|
+
export { createFrame, createFrameHost, createFrameInsertable, FRAME_APPLIED_EVENT } from "./frame-client.js";
|
|
2
|
+
export { FRAME_STREAM_HEADER, applyFrameResponse, isFrameStreamResponse, createServerComponentHandler } from "./frame-transport.js";
|
|
33
3
|
export { createJSONDataTable } from "./serializer.js";
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
import type { FrameHost } from "./frame-client.js";
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The app-wide frame host (created on first use): one chunk router, with
|
|
40
|
-
* codec data tables rotated per response — deserializer cross-reference
|
|
41
|
-
* space is stream-scoped by contract.
|
|
42
|
-
*/
|
|
43
|
-
export function getFrameHost(): FrameHost;
|
|
44
|
-
|
|
4
|
+
export declare function getFrameHost(): any;
|
|
45
5
|
/**
|
|
46
6
|
* Installs the server-component transport policy on the server-function
|
|
47
|
-
* client: boundary identity derives from the reactive owner captured at
|
|
48
|
-
* call site,
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
7
|
+
* client: boundary identity derives from the reactive owner captured at
|
|
8
|
+
* each call site (`getOwner`), so distinct `dynamic()` sources get
|
|
9
|
+
* independent boundaries with nothing declared, refetches from the same
|
|
10
|
+
* source resolve to the identical component, and ownerless calls fall back
|
|
11
|
+
* to one boundary per function id.
|
|
12
|
+
*
|
|
13
|
+
* Call once in the client entry (an explicit call — the package is
|
|
14
|
+
* `sideEffects: false`, so a bare import would be tree-shaken away);
|
|
15
|
+
* call again to rebind to a custom host.
|
|
52
16
|
*/
|
|
53
|
-
export function installServerComponents(host?:
|
|
17
|
+
export declare function installServerComponents(host?: any): void;
|
|
@@ -72,6 +72,14 @@ export interface FrameWrite {
|
|
|
72
72
|
|
|
73
73
|
/** Context passed to a slot callback. */
|
|
74
74
|
export interface SlotContext {
|
|
75
|
+
/**
|
|
76
|
+
* True only for the hydration-attach invocation of an adopted
|
|
77
|
+
* document-SSR range — the one call a consumer may answer with a claim
|
|
78
|
+
* (`existing` IS the server-rendered output for these args). Unset on
|
|
79
|
+
* stream-driven re-calls: those must render for real, or content the
|
|
80
|
+
* re-call displaced (e.g. `{$frame}` region ranges) is dropped.
|
|
81
|
+
*/
|
|
82
|
+
adopted?: boolean;
|
|
75
83
|
/**
|
|
76
84
|
* Register cleanup for when this occurrence's range is removed from the
|
|
77
85
|
* server content, or the owning frame is disposed.
|
|
@@ -203,3 +211,12 @@ export function createFrameInsertable(options: FrameOptions): {
|
|
|
203
211
|
readonly frame: Frame | null;
|
|
204
212
|
dispose(): void;
|
|
205
213
|
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Binds a frame to an EXISTING marker range — the document-SSR adoption
|
|
217
|
+
* path: the page already holds the server-rendered boundary between
|
|
218
|
+
* `frame:<id>:start`/`:end` comments; the frame constructed over it treats
|
|
219
|
+
* that content as its own (first stream morphs rather than materializes)
|
|
220
|
+
* and slots sync immediately, claiming their server-rendered DOM.
|
|
221
|
+
*/
|
|
222
|
+
export function adoptFrameRange(start: Comment, end: Comment, options?: FrameOptions): Frame;
|
|
@@ -96,10 +96,11 @@ export interface ServerComponentHandlerOptions<C = unknown> {
|
|
|
96
96
|
* key a WeakMap of boundaries (dying with their call sites); ownerless calls
|
|
97
97
|
* fall back to one boundary per function id.
|
|
98
98
|
*/
|
|
99
|
-
export function createServerComponentHandler<C>(
|
|
100
|
-
options: ServerComponentHandlerOptions<C>
|
|
101
|
-
): {
|
|
99
|
+
export function createServerComponentHandler<C>(options: ServerComponentHandlerOptions<C>): {
|
|
102
100
|
capture?(info: { id: string; meta: unknown }): unknown;
|
|
103
101
|
intercept?(info: { id: string; meta: unknown; args: unknown[] }): C | undefined;
|
|
104
|
-
handle(
|
|
102
|
+
handle(
|
|
103
|
+
response: Response,
|
|
104
|
+
ctx: { id: string; meta: unknown; args: unknown[]; context: unknown }
|
|
105
|
+
): C | undefined;
|
|
105
106
|
};
|
package/types/frames/server.d.ts
CHANGED
|
@@ -1,21 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* @solidjs/web/frames — server half. Render server components (functions
|
|
3
|
-
* returned from server functions) to frame-chunk streams, serve them as
|
|
4
|
-
* framed HTTP responses through the server-function handler's
|
|
5
|
-
* transformResult hook, and render them inline during document SSR.
|
|
6
|
-
*
|
|
7
|
-
* Copied next to the runtime's frame d.ts files at publish (see
|
|
8
|
-
* types:copy-frames), so the relative imports below resolve in-place.
|
|
9
|
-
*/
|
|
10
|
-
export {
|
|
11
|
-
renderToFrameStream,
|
|
12
|
-
renderServerComponent,
|
|
13
|
-
serverComponentResponse,
|
|
14
|
-
frameTransformResult,
|
|
15
|
-
createFrameSink,
|
|
16
|
-
frameTransformDirectResult,
|
|
17
|
-
ServerComponentPlugin,
|
|
18
|
-
SERVER_COMPONENT_BOOTSTRAP
|
|
19
|
-
} from "./frame-sink.js";
|
|
20
|
-
export type { FrameAddress, FrameStream, FrameStreamOptions } from "./frame-sink.js";
|
|
1
|
+
export { renderToFrameStream, renderServerComponent, serverComponentResponse, frameTransformResult, createFrameSink, frameTransformDirectResult, ServerComponentPlugin, SERVER_COMPONENT_BOOTSTRAP } from "./frame-sink.js";
|
|
21
2
|
export { FRAME_STREAM_HEADER, isFrameStreamResponse } from "./frame-transport.js";
|
|
@@ -102,6 +102,23 @@ export interface ServerFunctionsServerConfig {
|
|
|
102
102
|
* router); per-handler `collectFlightData` options override it.
|
|
103
103
|
*/
|
|
104
104
|
collectFlightData?: CollectFlightDataHook;
|
|
105
|
+
/**
|
|
106
|
+
* Server-wide default for the handler's `transformResult` (same contract
|
|
107
|
+
* — see `HandleServerFunctionRequestOptions`); a per-request option
|
|
108
|
+
* overrides it. Registering it here makes result policies (e.g. frames'
|
|
109
|
+
* `frameTransformResult`) work through generic dispatchers that call
|
|
110
|
+
* `handleServerFunctionRequest(request)` with no options.
|
|
111
|
+
*/
|
|
112
|
+
transformResult?(
|
|
113
|
+
event: ServerFunctionEvent,
|
|
114
|
+
result: unknown,
|
|
115
|
+
context: { instance: string | null; request: Request; thrown?: boolean }
|
|
116
|
+
): unknown | ResponseEnvelope | Promise<unknown | ResponseEnvelope>;
|
|
117
|
+
/**
|
|
118
|
+
* The in-process mirror of `transformResult` for direct (same-server)
|
|
119
|
+
* calls during document SSR — e.g. frames' `frameTransformDirectResult`.
|
|
120
|
+
*/
|
|
121
|
+
transformDirectResult?(value: unknown, options: { id: string }): unknown;
|
|
105
122
|
/**
|
|
106
123
|
* Endpoint the HTTP handler is mounted on, used for the `url` of SSR'd
|
|
107
124
|
* references (e.g. form actions) — must match the client configuration.
|
|
@@ -369,3 +369,20 @@ export function decodeResponse<T = unknown>(
|
|
|
369
369
|
response: Response,
|
|
370
370
|
codecOptions?: JSONCodecOptions
|
|
371
371
|
): Promise<T | undefined>;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Frame one payload for the server-function wire: a `;0x<len32>;` length
|
|
375
|
+
* prefix followed by the utf-8 data. Both transports (server-function
|
|
376
|
+
* responses and frame streams) share this framing.
|
|
377
|
+
*/
|
|
378
|
+
export function createChunk(data: string): Uint8Array;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Incremental decoder for `createChunk` framing over a byte stream: `next()`
|
|
382
|
+
* yields one complete payload string per call (async-iterator result shape),
|
|
383
|
+
* buffering partial frames internally until their length prefix is satisfied.
|
|
384
|
+
*/
|
|
385
|
+
export class ChunkReader {
|
|
386
|
+
constructor(stream: ReadableStream<Uint8Array>);
|
|
387
|
+
next(): Promise<{ done: boolean; value: string | undefined }>;
|
|
388
|
+
}
|
|
@@ -1,53 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* boundaries. There is deliberately no server-component API here beyond
|
|
4
|
-
* `installServerComponents()`: `dynamic` + server functions IS the client
|
|
5
|
-
* surface — a server-function call whose response is a frame stream
|
|
6
|
-
* resolves with a stable per-call-site component.
|
|
7
|
-
*
|
|
8
|
-
* Copied next to the runtime's frame d.ts files at publish (see
|
|
9
|
-
* types:copy-frames), so the relative imports below resolve in-place.
|
|
10
|
-
*/
|
|
11
|
-
export {
|
|
12
|
-
createFrame,
|
|
13
|
-
createFrameHost,
|
|
14
|
-
createFrameInsertable,
|
|
15
|
-
FRAME_APPLIED_EVENT
|
|
16
|
-
} from "./frame-client.cjs";
|
|
17
|
-
export type {
|
|
18
|
-
Frame,
|
|
19
|
-
FrameChunk,
|
|
20
|
-
FrameHost,
|
|
21
|
-
FrameHostOptions,
|
|
22
|
-
FrameOptions,
|
|
23
|
-
FrameWrite,
|
|
24
|
-
Slot,
|
|
25
|
-
SlotContext
|
|
26
|
-
} from "./frame-client.cjs";
|
|
27
|
-
export {
|
|
28
|
-
FRAME_STREAM_HEADER,
|
|
29
|
-
applyFrameResponse,
|
|
30
|
-
isFrameStreamResponse,
|
|
31
|
-
createServerComponentHandler
|
|
32
|
-
} from "./frame-transport.cjs";
|
|
1
|
+
export { createFrame, createFrameHost, createFrameInsertable, FRAME_APPLIED_EVENT } from "./frame-client.cjs";
|
|
2
|
+
export { FRAME_STREAM_HEADER, applyFrameResponse, isFrameStreamResponse, createServerComponentHandler } from "./frame-transport.cjs";
|
|
33
3
|
export { createJSONDataTable } from "./serializer.cjs";
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
import type { FrameHost } from "./frame-client.cjs";
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The app-wide frame host (created on first use): one chunk router, with
|
|
40
|
-
* codec data tables rotated per response — deserializer cross-reference
|
|
41
|
-
* space is stream-scoped by contract.
|
|
42
|
-
*/
|
|
43
|
-
export function getFrameHost(): FrameHost;
|
|
44
|
-
|
|
4
|
+
export declare function getFrameHost(): any;
|
|
45
5
|
/**
|
|
46
6
|
* Installs the server-component transport policy on the server-function
|
|
47
|
-
* client: boundary identity derives from the reactive owner captured at
|
|
48
|
-
* call site,
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
7
|
+
* client: boundary identity derives from the reactive owner captured at
|
|
8
|
+
* each call site (`getOwner`), so distinct `dynamic()` sources get
|
|
9
|
+
* independent boundaries with nothing declared, refetches from the same
|
|
10
|
+
* source resolve to the identical component, and ownerless calls fall back
|
|
11
|
+
* to one boundary per function id.
|
|
12
|
+
*
|
|
13
|
+
* Call once in the client entry (an explicit call — the package is
|
|
14
|
+
* `sideEffects: false`, so a bare import would be tree-shaken away);
|
|
15
|
+
* call again to rebind to a custom host.
|
|
52
16
|
*/
|
|
53
|
-
export function installServerComponents(host?:
|
|
17
|
+
export declare function installServerComponents(host?: any): void;
|
|
@@ -72,6 +72,14 @@ export interface FrameWrite {
|
|
|
72
72
|
|
|
73
73
|
/** Context passed to a slot callback. */
|
|
74
74
|
export interface SlotContext {
|
|
75
|
+
/**
|
|
76
|
+
* True only for the hydration-attach invocation of an adopted
|
|
77
|
+
* document-SSR range — the one call a consumer may answer with a claim
|
|
78
|
+
* (`existing` IS the server-rendered output for these args). Unset on
|
|
79
|
+
* stream-driven re-calls: those must render for real, or content the
|
|
80
|
+
* re-call displaced (e.g. `{$frame}` region ranges) is dropped.
|
|
81
|
+
*/
|
|
82
|
+
adopted?: boolean;
|
|
75
83
|
/**
|
|
76
84
|
* Register cleanup for when this occurrence's range is removed from the
|
|
77
85
|
* server content, or the owning frame is disposed.
|
|
@@ -203,3 +211,12 @@ export function createFrameInsertable(options: FrameOptions): {
|
|
|
203
211
|
readonly frame: Frame | null;
|
|
204
212
|
dispose(): void;
|
|
205
213
|
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Binds a frame to an EXISTING marker range — the document-SSR adoption
|
|
217
|
+
* path: the page already holds the server-rendered boundary between
|
|
218
|
+
* `frame:<id>:start`/`:end` comments; the frame constructed over it treats
|
|
219
|
+
* that content as its own (first stream morphs rather than materializes)
|
|
220
|
+
* and slots sync immediately, claiming their server-rendered DOM.
|
|
221
|
+
*/
|
|
222
|
+
export function adoptFrameRange(start: Comment, end: Comment, options?: FrameOptions): Frame;
|
|
@@ -96,10 +96,11 @@ export interface ServerComponentHandlerOptions<C = unknown> {
|
|
|
96
96
|
* key a WeakMap of boundaries (dying with their call sites); ownerless calls
|
|
97
97
|
* fall back to one boundary per function id.
|
|
98
98
|
*/
|
|
99
|
-
export function createServerComponentHandler<C>(
|
|
100
|
-
options: ServerComponentHandlerOptions<C>
|
|
101
|
-
): {
|
|
99
|
+
export function createServerComponentHandler<C>(options: ServerComponentHandlerOptions<C>): {
|
|
102
100
|
capture?(info: { id: string; meta: unknown }): unknown;
|
|
103
101
|
intercept?(info: { id: string; meta: unknown; args: unknown[] }): C | undefined;
|
|
104
|
-
handle(
|
|
102
|
+
handle(
|
|
103
|
+
response: Response,
|
|
104
|
+
ctx: { id: string; meta: unknown; args: unknown[]; context: unknown }
|
|
105
|
+
): C | undefined;
|
|
105
106
|
};
|
|
@@ -1,21 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* @solidjs/web/frames — server half. Render server components (functions
|
|
3
|
-
* returned from server functions) to frame-chunk streams, serve them as
|
|
4
|
-
* framed HTTP responses through the server-function handler's
|
|
5
|
-
* transformResult hook, and render them inline during document SSR.
|
|
6
|
-
*
|
|
7
|
-
* Copied next to the runtime's frame d.ts files at publish (see
|
|
8
|
-
* types:copy-frames), so the relative imports below resolve in-place.
|
|
9
|
-
*/
|
|
10
|
-
export {
|
|
11
|
-
renderToFrameStream,
|
|
12
|
-
renderServerComponent,
|
|
13
|
-
serverComponentResponse,
|
|
14
|
-
frameTransformResult,
|
|
15
|
-
createFrameSink,
|
|
16
|
-
frameTransformDirectResult,
|
|
17
|
-
ServerComponentPlugin,
|
|
18
|
-
SERVER_COMPONENT_BOOTSTRAP
|
|
19
|
-
} from "./frame-sink.cjs";
|
|
20
|
-
export type { FrameAddress, FrameStream, FrameStreamOptions } from "./frame-sink.cjs";
|
|
1
|
+
export { renderToFrameStream, renderServerComponent, serverComponentResponse, frameTransformResult, createFrameSink, frameTransformDirectResult, ServerComponentPlugin, SERVER_COMPONENT_BOOTSTRAP } from "./frame-sink.cjs";
|
|
21
2
|
export { FRAME_STREAM_HEADER, isFrameStreamResponse } from "./frame-transport.cjs";
|
|
@@ -102,6 +102,23 @@ export interface ServerFunctionsServerConfig {
|
|
|
102
102
|
* router); per-handler `collectFlightData` options override it.
|
|
103
103
|
*/
|
|
104
104
|
collectFlightData?: CollectFlightDataHook;
|
|
105
|
+
/**
|
|
106
|
+
* Server-wide default for the handler's `transformResult` (same contract
|
|
107
|
+
* — see `HandleServerFunctionRequestOptions`); a per-request option
|
|
108
|
+
* overrides it. Registering it here makes result policies (e.g. frames'
|
|
109
|
+
* `frameTransformResult`) work through generic dispatchers that call
|
|
110
|
+
* `handleServerFunctionRequest(request)` with no options.
|
|
111
|
+
*/
|
|
112
|
+
transformResult?(
|
|
113
|
+
event: ServerFunctionEvent,
|
|
114
|
+
result: unknown,
|
|
115
|
+
context: { instance: string | null; request: Request; thrown?: boolean }
|
|
116
|
+
): unknown | ResponseEnvelope | Promise<unknown | ResponseEnvelope>;
|
|
117
|
+
/**
|
|
118
|
+
* The in-process mirror of `transformResult` for direct (same-server)
|
|
119
|
+
* calls during document SSR — e.g. frames' `frameTransformDirectResult`.
|
|
120
|
+
*/
|
|
121
|
+
transformDirectResult?(value: unknown, options: { id: string }): unknown;
|
|
105
122
|
/**
|
|
106
123
|
* Endpoint the HTTP handler is mounted on, used for the `url` of SSR'd
|
|
107
124
|
* references (e.g. form actions) — must match the client configuration.
|
|
@@ -369,3 +369,20 @@ export function decodeResponse<T = unknown>(
|
|
|
369
369
|
response: Response,
|
|
370
370
|
codecOptions?: JSONCodecOptions
|
|
371
371
|
): Promise<T | undefined>;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Frame one payload for the server-function wire: a `;0x<len32>;` length
|
|
375
|
+
* prefix followed by the utf-8 data. Both transports (server-function
|
|
376
|
+
* responses and frame streams) share this framing.
|
|
377
|
+
*/
|
|
378
|
+
export function createChunk(data: string): Uint8Array;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Incremental decoder for `createChunk` framing over a byte stream: `next()`
|
|
382
|
+
* yields one complete payload string per call (async-iterator result shape),
|
|
383
|
+
* buffering partial frames internally until their length prefix is satisfied.
|
|
384
|
+
*/
|
|
385
|
+
export class ChunkReader {
|
|
386
|
+
constructor(stream: ReadableStream<Uint8Array>);
|
|
387
|
+
next(): Promise<{ done: boolean; value: string | undefined }>;
|
|
388
|
+
}
|