@solidjs/web 2.0.0-beta.23 → 2.0.0-beta.24
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 +33 -8
- package/frames/dist/client.js +33 -8
- package/frames/dist/server.cjs +31 -13
- package/frames/dist/server.js +31 -13
- package/package.json +3 -3
- package/server-functions/dist/server.cjs +8 -4
- package/server-functions/dist/server.js +8 -4
- package/types/frames/frame-client.d.ts +17 -0
- package/types/frames/frame-transport.d.ts +5 -4
- package/types/server-functions/server.d.ts +17 -0
- package/types/server-functions/shared.d.ts +17 -0
- package/types-cjs/frames/frame-client.d.cts +17 -0
- package/types-cjs/frames/frame-transport.d.cts +5 -4
- 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
|
@@ -126,7 +126,20 @@ function createFrameHost(options = {}) {
|
|
|
126
126
|
const buffered = pending.get(id);
|
|
127
127
|
if (buffered) {
|
|
128
128
|
pending.delete(id);
|
|
129
|
-
|
|
129
|
+
const records = {};
|
|
130
|
+
let version;
|
|
131
|
+
for (const chunk of buffered) {
|
|
132
|
+
if (chunk.type === "data") {
|
|
133
|
+
options.applyData && options.applyData(chunk);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
version = chunk.version;
|
|
137
|
+
Object.assign(records, chunkToRecords(chunk));
|
|
138
|
+
}
|
|
139
|
+
if (version !== undefined) frame.apply({
|
|
140
|
+
version,
|
|
141
|
+
r: records
|
|
142
|
+
});
|
|
130
143
|
}
|
|
131
144
|
},
|
|
132
145
|
unregister(id, frame) {
|
|
@@ -346,11 +359,11 @@ class FrameImpl {
|
|
|
346
359
|
this.#runSlotCleanups(occurrence);
|
|
347
360
|
}
|
|
348
361
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
349
|
-
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
362
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
350
363
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
351
364
|
this.#slotNodes.set(occurrence, nodes);
|
|
352
365
|
this.#mountedSlots.add(occurrence);
|
|
353
|
-
|
|
366
|
+
this.#discoverRegions(occurrence, start);
|
|
354
367
|
this.#bindRegions(occurrence);
|
|
355
368
|
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
356
369
|
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
@@ -367,11 +380,12 @@ class FrameImpl {
|
|
|
367
380
|
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
368
381
|
}
|
|
369
382
|
}
|
|
370
|
-
#invokeSlot(occurrence, callback, record, start) {
|
|
383
|
+
#invokeSlot(occurrence, callback, record, start, adopted) {
|
|
371
384
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
372
385
|
const ctx = {
|
|
373
386
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
374
387
|
key: occurrence,
|
|
388
|
+
adopted: !!adopted,
|
|
375
389
|
onCleanup: fn => cleanups.push(fn),
|
|
376
390
|
existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
|
|
377
391
|
};
|
|
@@ -514,11 +528,22 @@ class FrameImpl {
|
|
|
514
528
|
}
|
|
515
529
|
#refArgsUnchanged(occurrence, record) {
|
|
516
530
|
const old = this.#slotArgs.get(occurrence);
|
|
517
|
-
if (!
|
|
518
|
-
|
|
531
|
+
if (!record || record.kind !== "slot") return false;
|
|
532
|
+
if (old && old.kind !== "slot") return false;
|
|
533
|
+
const a = old && old.args || {};
|
|
519
534
|
const b = record.args || {};
|
|
520
535
|
const ka = Object.keys(a);
|
|
521
|
-
|
|
536
|
+
const kb = Object.keys(b);
|
|
537
|
+
if (kb.length < ka.length) return false;
|
|
538
|
+
if (kb.length !== ka.length) {
|
|
539
|
+
const regions = this.#slotRegions.get(occurrence);
|
|
540
|
+
for (const key of kb) {
|
|
541
|
+
if (key in a) continue;
|
|
542
|
+
const vb = b[key];
|
|
543
|
+
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
544
|
+
if (!regions || !regions.has(vb.$frame)) return false;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
522
547
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
523
548
|
for (const key of ka) {
|
|
524
549
|
const va = a[key];
|
|
@@ -1322,7 +1347,7 @@ function slotsFor(props) {
|
|
|
1322
1347
|
const v = props[prop];
|
|
1323
1348
|
return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
|
|
1324
1349
|
};
|
|
1325
|
-
if (ctx && ctx.frame && ctx.existing && ctx.existing.length) {
|
|
1350
|
+
if (ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length) {
|
|
1326
1351
|
return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
|
|
1327
1352
|
}
|
|
1328
1353
|
return render();
|
package/frames/dist/client.js
CHANGED
|
@@ -124,7 +124,20 @@ function createFrameHost(options = {}) {
|
|
|
124
124
|
const buffered = pending.get(id);
|
|
125
125
|
if (buffered) {
|
|
126
126
|
pending.delete(id);
|
|
127
|
-
|
|
127
|
+
const records = {};
|
|
128
|
+
let version;
|
|
129
|
+
for (const chunk of buffered) {
|
|
130
|
+
if (chunk.type === "data") {
|
|
131
|
+
options.applyData && options.applyData(chunk);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
version = chunk.version;
|
|
135
|
+
Object.assign(records, chunkToRecords(chunk));
|
|
136
|
+
}
|
|
137
|
+
if (version !== undefined) frame.apply({
|
|
138
|
+
version,
|
|
139
|
+
r: records
|
|
140
|
+
});
|
|
128
141
|
}
|
|
129
142
|
},
|
|
130
143
|
unregister(id, frame) {
|
|
@@ -344,11 +357,11 @@ class FrameImpl {
|
|
|
344
357
|
this.#runSlotCleanups(occurrence);
|
|
345
358
|
}
|
|
346
359
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
347
|
-
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
360
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
348
361
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
349
362
|
this.#slotNodes.set(occurrence, nodes);
|
|
350
363
|
this.#mountedSlots.add(occurrence);
|
|
351
|
-
|
|
364
|
+
this.#discoverRegions(occurrence, start);
|
|
352
365
|
this.#bindRegions(occurrence);
|
|
353
366
|
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
354
367
|
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
@@ -365,11 +378,12 @@ class FrameImpl {
|
|
|
365
378
|
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
366
379
|
}
|
|
367
380
|
}
|
|
368
|
-
#invokeSlot(occurrence, callback, record, start) {
|
|
381
|
+
#invokeSlot(occurrence, callback, record, start, adopted) {
|
|
369
382
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
370
383
|
const ctx = {
|
|
371
384
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
372
385
|
key: occurrence,
|
|
386
|
+
adopted: !!adopted,
|
|
373
387
|
onCleanup: fn => cleanups.push(fn),
|
|
374
388
|
existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
|
|
375
389
|
};
|
|
@@ -512,11 +526,22 @@ class FrameImpl {
|
|
|
512
526
|
}
|
|
513
527
|
#refArgsUnchanged(occurrence, record) {
|
|
514
528
|
const old = this.#slotArgs.get(occurrence);
|
|
515
|
-
if (!
|
|
516
|
-
|
|
529
|
+
if (!record || record.kind !== "slot") return false;
|
|
530
|
+
if (old && old.kind !== "slot") return false;
|
|
531
|
+
const a = old && old.args || {};
|
|
517
532
|
const b = record.args || {};
|
|
518
533
|
const ka = Object.keys(a);
|
|
519
|
-
|
|
534
|
+
const kb = Object.keys(b);
|
|
535
|
+
if (kb.length < ka.length) return false;
|
|
536
|
+
if (kb.length !== ka.length) {
|
|
537
|
+
const regions = this.#slotRegions.get(occurrence);
|
|
538
|
+
for (const key of kb) {
|
|
539
|
+
if (key in a) continue;
|
|
540
|
+
const vb = b[key];
|
|
541
|
+
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
542
|
+
if (!regions || !regions.has(vb.$frame)) return false;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
520
545
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
521
546
|
for (const key of ka) {
|
|
522
547
|
const va = a[key];
|
|
@@ -1320,7 +1345,7 @@ function slotsFor(props) {
|
|
|
1320
1345
|
const v = props[prop];
|
|
1321
1346
|
return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
|
|
1322
1347
|
};
|
|
1323
|
-
if (ctx && ctx.frame && ctx.existing && ctx.existing.length) {
|
|
1348
|
+
if (ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length) {
|
|
1324
1349
|
return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
|
|
1325
1350
|
}
|
|
1326
1351
|
return render();
|
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.24",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://solidjs.com",
|
|
@@ -296,10 +296,10 @@
|
|
|
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.24"
|
|
300
300
|
},
|
|
301
301
|
"devDependencies": {
|
|
302
|
-
"solid-js": "2.0.0-beta.
|
|
302
|
+
"solid-js": "2.0.0-beta.24"
|
|
303
303
|
},
|
|
304
304
|
"scripts": {
|
|
305
305
|
"build": "npm-run-all -nl build:clean types:copy-jsx build:js",
|
|
@@ -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
|
|
@@ -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
|
};
|
|
@@ -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
|
+
}
|
|
@@ -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
|
};
|
|
@@ -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
|
+
}
|