@solidjs/web 2.0.0-beta.28 → 2.0.0-beta.29
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/dev.cjs +40 -2
- package/dist/dev.js +39 -4
- package/dist/server.cjs +90 -31
- package/dist/server.js +89 -33
- package/dist/web.cjs +40 -2
- package/dist/web.js +39 -4
- package/frames/dist/client.cjs +370 -209
- package/frames/dist/client.dev.cjs +370 -210
- package/frames/dist/client.dev.js +371 -211
- package/frames/dist/client.js +371 -210
- package/frames/dist/server.cjs +351 -69
- package/frames/dist/server.js +351 -70
- package/package.json +3 -3
- package/server-functions/dist/client.cjs +87 -3
- package/server-functions/dist/client.js +80 -4
- package/server-functions/dist/server.cjs +52 -17
- package/server-functions/dist/server.js +51 -17
- package/types/client.d.ts +15 -0
- package/types/core.d.ts +1 -1
- package/types/frames/client.d.ts +7 -5
- package/types/frames/frame-client.d.ts +17 -0
- package/types/frames/frame-sink.d.ts +29 -6
- package/types/frames/frame-transport.d.ts +76 -12
- package/types/frames/server.d.ts +1 -1
- package/types/index.d.ts +74 -0
- package/types/server-functions/client.d.ts +24 -0
- package/types/server-functions/server.d.ts +75 -16
- package/types/server-functions/shared.d.ts +9 -0
- package/types/server-mock.d.ts +6 -2
- package/types/server.d.ts +39 -1
- package/types-cjs/client.d.cts +15 -0
- package/types-cjs/core.d.cts +1 -1
- package/types-cjs/frames/client.d.cts +7 -5
- package/types-cjs/frames/frame-client.d.cts +17 -0
- package/types-cjs/frames/frame-sink.d.cts +29 -6
- package/types-cjs/frames/frame-transport.d.cts +76 -12
- package/types-cjs/frames/server.d.cts +1 -1
- package/types-cjs/index.d.cts +74 -0
- package/types-cjs/server-functions/client.d.cts +24 -0
- package/types-cjs/server-functions/server.d.cts +75 -16
- package/types-cjs/server-functions/shared.d.cts +9 -0
- package/types-cjs/server-mock.d.cts +6 -2
- package/types-cjs/server.d.cts +39 -1
package/frames/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { runWithOwner, createOwner, sharedConfig, createRoot, ssrHandleError, getOwner, NoHydration, runInServerComponentScope, Hydration } from 'solid-js';
|
|
1
2
|
import { toCrossJSONStream, Feature, Serializer, getCrossReferenceHeader, createPlugin } from 'seroval';
|
|
2
|
-
import { runWithOwner, createOwner, sharedConfig, createRoot, ssrHandleError, getOwner, NoHydration, Hydration } from 'solid-js';
|
|
3
3
|
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
4
4
|
|
|
5
5
|
const runWithHydrationScope = (id, fn) => runWithOwner(createOwner({
|
|
@@ -54,6 +54,21 @@ function resolveCodecOptions({
|
|
|
54
54
|
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
function serializeJSON(value, {
|
|
58
|
+
onParse,
|
|
59
|
+
onDone,
|
|
60
|
+
onError,
|
|
61
|
+
...codecOptions
|
|
62
|
+
}) {
|
|
63
|
+
const resolved = resolveCodecOptions(codecOptions);
|
|
64
|
+
return toCrossJSONStream(value, {
|
|
65
|
+
onParse,
|
|
66
|
+
onDone,
|
|
67
|
+
onError,
|
|
68
|
+
...resolved,
|
|
69
|
+
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
|
|
70
|
+
});
|
|
71
|
+
}
|
|
57
72
|
function createJSONSerializer({
|
|
58
73
|
onData,
|
|
59
74
|
onDone,
|
|
@@ -633,6 +648,51 @@ function renderToStream(code, options = {}) {
|
|
|
633
648
|
drainTurn = 0;
|
|
634
649
|
progressed ? queue(attempt) : setTimeout(attempt);
|
|
635
650
|
};
|
|
651
|
+
let cachedReadable;
|
|
652
|
+
let consumer;
|
|
653
|
+
const claimConsumer = name => {
|
|
654
|
+
if (consumer && consumer !== name) {
|
|
655
|
+
throw new Error(`renderToStream result was already consumed via \`${consumer}\`; cannot also consume it via \`${name}\`. Use exactly one of \`pipe\`, \`pipeTo\`, or \`readable\`.`);
|
|
656
|
+
}
|
|
657
|
+
consumer = name;
|
|
658
|
+
};
|
|
659
|
+
const pipeToImpl = w => {
|
|
660
|
+
let resolve;
|
|
661
|
+
const p = new Promise(r => resolve = r);
|
|
662
|
+
function flush() {
|
|
663
|
+
allSettled(blockingPromises).then(() => {
|
|
664
|
+
scheduleFlush(() => {
|
|
665
|
+
doShell();
|
|
666
|
+
if (!shellCompleted) return flush();
|
|
667
|
+
const encoder = new TextEncoder();
|
|
668
|
+
const writer = w.getWriter();
|
|
669
|
+
let pendingWrites = Promise.resolve();
|
|
670
|
+
writable = {
|
|
671
|
+
end() {
|
|
672
|
+
pendingWrites.then(() => {
|
|
673
|
+
writer.releaseLock();
|
|
674
|
+
w.close().catch(() => {});
|
|
675
|
+
resolve();
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
buffer = {
|
|
680
|
+
write(payload) {
|
|
681
|
+
pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(() => {});
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
buffer.write(tmp);
|
|
685
|
+
firstFlushed = true;
|
|
686
|
+
if (completed) {
|
|
687
|
+
dispose();
|
|
688
|
+
writable.end();
|
|
689
|
+
} else flushEnd();
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
flush();
|
|
694
|
+
return p;
|
|
695
|
+
};
|
|
636
696
|
return {
|
|
637
697
|
then(fn) {
|
|
638
698
|
function complete() {
|
|
@@ -657,6 +717,7 @@ function renderToStream(code, options = {}) {
|
|
|
657
717
|
flush();
|
|
658
718
|
},
|
|
659
719
|
pipe(w) {
|
|
720
|
+
claimConsumer("pipe");
|
|
660
721
|
function flush() {
|
|
661
722
|
allSettled(blockingPromises).then(() => {
|
|
662
723
|
scheduleFlush(() => {
|
|
@@ -675,38 +736,17 @@ function renderToStream(code, options = {}) {
|
|
|
675
736
|
flush();
|
|
676
737
|
},
|
|
677
738
|
pipeTo(w) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
writable = {
|
|
688
|
-
end() {
|
|
689
|
-
writer.releaseLock();
|
|
690
|
-
w.close().catch(() => {});
|
|
691
|
-
resolve();
|
|
692
|
-
}
|
|
693
|
-
};
|
|
694
|
-
buffer = {
|
|
695
|
-
write(payload) {
|
|
696
|
-
writer.write(encoder.encode(payload)).catch(() => {});
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
buffer.write(tmp);
|
|
700
|
-
firstFlushed = true;
|
|
701
|
-
if (completed) {
|
|
702
|
-
dispose();
|
|
703
|
-
writable.end();
|
|
704
|
-
} else flushEnd();
|
|
705
|
-
});
|
|
706
|
-
});
|
|
739
|
+
claimConsumer("pipeTo");
|
|
740
|
+
return pipeToImpl(w);
|
|
741
|
+
},
|
|
742
|
+
get readable() {
|
|
743
|
+
claimConsumer("readable");
|
|
744
|
+
if (!cachedReadable) {
|
|
745
|
+
const t = new TransformStream();
|
|
746
|
+
pipeToImpl(t.writable);
|
|
747
|
+
cachedReadable = t.readable;
|
|
707
748
|
}
|
|
708
|
-
|
|
709
|
-
return p;
|
|
749
|
+
return cachedReadable;
|
|
710
750
|
}
|
|
711
751
|
};
|
|
712
752
|
}
|
|
@@ -1151,6 +1191,51 @@ function resolveSSRSync(node) {
|
|
|
1151
1191
|
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
1152
1192
|
}
|
|
1153
1193
|
|
|
1194
|
+
function frameAddress(id, args) {
|
|
1195
|
+
return args && args.length ? id + ":" + hashArguments(args) : id;
|
|
1196
|
+
}
|
|
1197
|
+
function hashArguments(args) {
|
|
1198
|
+
let hash = 0;
|
|
1199
|
+
const text = stableString(args);
|
|
1200
|
+
for (let i = 0; i < text.length; i++) {
|
|
1201
|
+
hash = (hash << 5) - hash + text.charCodeAt(i);
|
|
1202
|
+
hash |= 0;
|
|
1203
|
+
}
|
|
1204
|
+
return (hash >>> 0).toString(36);
|
|
1205
|
+
}
|
|
1206
|
+
function stableString(value, seen) {
|
|
1207
|
+
if (value === null || typeof value !== "object") {
|
|
1208
|
+
return typeof value === "bigint" ? value + "n" : String(value);
|
|
1209
|
+
}
|
|
1210
|
+
if (value instanceof Date) return "Date:" + value.getTime();
|
|
1211
|
+
seen || (seen = new Set());
|
|
1212
|
+
if (seen.has(value)) return "~";
|
|
1213
|
+
seen.add(value);
|
|
1214
|
+
if (value instanceof Map) {
|
|
1215
|
+
const entries = [];
|
|
1216
|
+
for (const [k, v] of value) {
|
|
1217
|
+
entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
|
|
1218
|
+
}
|
|
1219
|
+
return "Map{" + entries.sort().join(",") + "}";
|
|
1220
|
+
}
|
|
1221
|
+
if (value instanceof Set) {
|
|
1222
|
+
const members = [];
|
|
1223
|
+
for (const v of value) members.push(stableString(v, seen));
|
|
1224
|
+
return "Set{" + members.sort().join(",") + "}";
|
|
1225
|
+
}
|
|
1226
|
+
if (Array.isArray(value)) {
|
|
1227
|
+
let out = "[";
|
|
1228
|
+
for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
|
|
1229
|
+
return out + "]";
|
|
1230
|
+
}
|
|
1231
|
+
const keys = Object.keys(value).sort();
|
|
1232
|
+
let out = "{";
|
|
1233
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1234
|
+
out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
|
|
1235
|
+
}
|
|
1236
|
+
return out + "}";
|
|
1237
|
+
}
|
|
1238
|
+
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
1154
1239
|
function createChunk(data) {
|
|
1155
1240
|
const encodeData = new TextEncoder().encode(data);
|
|
1156
1241
|
const bytes = encodeData.length;
|
|
@@ -1162,16 +1247,138 @@ function createChunk(data) {
|
|
|
1162
1247
|
chunk.set(encodeData, 12);
|
|
1163
1248
|
return chunk;
|
|
1164
1249
|
}
|
|
1250
|
+
class ChunkReader {
|
|
1251
|
+
constructor(stream) {
|
|
1252
|
+
this.reader = stream.getReader();
|
|
1253
|
+
this.buffer = new Uint8Array(0);
|
|
1254
|
+
this.done = false;
|
|
1255
|
+
}
|
|
1256
|
+
async readChunk() {
|
|
1257
|
+
const chunk = await this.reader.read();
|
|
1258
|
+
if (!chunk.done) {
|
|
1259
|
+
const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
|
|
1260
|
+
newBuffer.set(this.buffer);
|
|
1261
|
+
newBuffer.set(chunk.value, this.buffer.length);
|
|
1262
|
+
this.buffer = newBuffer;
|
|
1263
|
+
} else {
|
|
1264
|
+
this.done = true;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
async next() {
|
|
1268
|
+
while (this.buffer.length < 12) {
|
|
1269
|
+
if (this.done) {
|
|
1270
|
+
if (this.buffer.length === 0) return {
|
|
1271
|
+
done: true,
|
|
1272
|
+
value: undefined
|
|
1273
|
+
};
|
|
1274
|
+
throw new Error("Malformed server function stream.");
|
|
1275
|
+
}
|
|
1276
|
+
await this.readChunk();
|
|
1277
|
+
}
|
|
1278
|
+
const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
|
|
1279
|
+
const bytes = Number.parseInt(head, 16);
|
|
1280
|
+
if (Number.isNaN(bytes)) {
|
|
1281
|
+
throw new Error("Malformed server function stream.");
|
|
1282
|
+
}
|
|
1283
|
+
while (bytes > this.buffer.length - 12) {
|
|
1284
|
+
if (this.done) {
|
|
1285
|
+
throw new Error("Malformed server function stream.");
|
|
1286
|
+
}
|
|
1287
|
+
await this.readChunk();
|
|
1288
|
+
}
|
|
1289
|
+
const partial = new TextDecoder().decode(this.buffer.subarray(12, 12 + bytes));
|
|
1290
|
+
this.buffer = this.buffer.subarray(12 + bytes);
|
|
1291
|
+
return {
|
|
1292
|
+
done: false,
|
|
1293
|
+
value: partial
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
async drain(interpret) {
|
|
1297
|
+
while (true) {
|
|
1298
|
+
const result = await this.next();
|
|
1299
|
+
if (result.done) {
|
|
1300
|
+
break;
|
|
1301
|
+
}
|
|
1302
|
+
interpret(result.value);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
function serializeStream(value, codecOptions) {
|
|
1307
|
+
return new ReadableStream({
|
|
1308
|
+
start(controller) {
|
|
1309
|
+
serializeJSON(value, {
|
|
1310
|
+
...codecOptions,
|
|
1311
|
+
onParse(node) {
|
|
1312
|
+
controller.enqueue(createChunk(JSON.stringify(node)));
|
|
1313
|
+
},
|
|
1314
|
+
onDone() {
|
|
1315
|
+
controller.close();
|
|
1316
|
+
},
|
|
1317
|
+
onError(error) {
|
|
1318
|
+
controller.error(error);
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1165
1324
|
|
|
1166
1325
|
const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
|
|
1167
1326
|
function isResponseEnvelope(value) {
|
|
1168
1327
|
return !!(value && typeof value === "object" && value[ENVELOPE]);
|
|
1169
1328
|
}
|
|
1170
1329
|
|
|
1330
|
+
const INVOCATIONS = new WeakMap();
|
|
1331
|
+
function getEventServerFunctionInvocation(event) {
|
|
1332
|
+
return event && INVOCATIONS.get(event);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1171
1335
|
const FRAME_STREAM_HEADER = "X-Frame-Stream";
|
|
1172
1336
|
function isFrameStreamResponse(response) {
|
|
1173
1337
|
return response.headers.has(FRAME_STREAM_HEADER);
|
|
1174
1338
|
}
|
|
1339
|
+
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1340
|
+
const SERVER_COMPONENT_SOURCE = /*#__PURE__*/Symbol.for("dom-expressions.server-component-source");
|
|
1341
|
+
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1342
|
+
function parseServerComponent(value, ctx) {
|
|
1343
|
+
return {
|
|
1344
|
+
id: ctx.parse(value[SERVER_COMPONENT]),
|
|
1345
|
+
address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
1349
|
+
tag: "dom-expressions/server-component",
|
|
1350
|
+
test(value) {
|
|
1351
|
+
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
1352
|
+
},
|
|
1353
|
+
parse: {
|
|
1354
|
+
sync: parseServerComponent,
|
|
1355
|
+
async async(value, ctx) {
|
|
1356
|
+
return {
|
|
1357
|
+
id: await ctx.parse(value[SERVER_COMPONENT]),
|
|
1358
|
+
address: await ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1359
|
+
};
|
|
1360
|
+
},
|
|
1361
|
+
stream: parseServerComponent
|
|
1362
|
+
},
|
|
1363
|
+
serialize(node, ctx) {
|
|
1364
|
+
return "self._$SC.r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1365
|
+
},
|
|
1366
|
+
deserialize(node, ctx) {
|
|
1367
|
+
const id = ctx.deserialize(node.id);
|
|
1368
|
+
ctx.deserialize(node.address);
|
|
1369
|
+
return globalThis._$SC.r(id);
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
function flightCodec(codec) {
|
|
1373
|
+
const plugins = codec && codec.plugins || [];
|
|
1374
|
+
for (const plugin of plugins) {
|
|
1375
|
+
if (plugin && plugin.tag === "dom-expressions/server-component") return codec;
|
|
1376
|
+
}
|
|
1377
|
+
return {
|
|
1378
|
+
...codec,
|
|
1379
|
+
plugins: [...plugins, ServerComponentPlugin]
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1175
1382
|
|
|
1176
1383
|
function serverOwned(render) {
|
|
1177
1384
|
return NoHydration ? NoHydration({
|
|
@@ -1180,6 +1387,9 @@ function serverOwned(render) {
|
|
|
1180
1387
|
}
|
|
1181
1388
|
}) : render();
|
|
1182
1389
|
}
|
|
1390
|
+
function serverComponentScope(render) {
|
|
1391
|
+
return runInServerComponentScope ? runInServerComponentScope(render) : render();
|
|
1392
|
+
}
|
|
1183
1393
|
function createFrameSink(emit, frame) {
|
|
1184
1394
|
const {
|
|
1185
1395
|
id,
|
|
@@ -1361,7 +1571,7 @@ function renderToFrameStream(code, options = {}) {
|
|
|
1361
1571
|
function renderServerComponent(component, options = {}) {
|
|
1362
1572
|
return frameStream((sink, frame) => {
|
|
1363
1573
|
const props = createSlotProps(sink, frame);
|
|
1364
|
-
return () => component(props);
|
|
1574
|
+
return () => serverComponentScope(() => component(props));
|
|
1365
1575
|
}, options);
|
|
1366
1576
|
}
|
|
1367
1577
|
function frameStream(makeCode, options) {
|
|
@@ -1554,16 +1764,23 @@ function frameElementOpen(id) {
|
|
|
1554
1764
|
}
|
|
1555
1765
|
const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
|
|
1556
1766
|
function frameTransformDirectResult(value, {
|
|
1557
|
-
id
|
|
1767
|
+
id,
|
|
1768
|
+
args
|
|
1558
1769
|
}) {
|
|
1559
1770
|
if (typeof value !== "function") return value;
|
|
1560
1771
|
const component = value;
|
|
1561
1772
|
const wrapped = props => [{
|
|
1562
1773
|
t: frameElementOpen(id)
|
|
1563
|
-
},
|
|
1774
|
+
},
|
|
1775
|
+
serverOwned(() => {
|
|
1776
|
+
const slotProps = createDocumentSlotProps(props, id);
|
|
1777
|
+
return serverComponentScope(() => component(slotProps));
|
|
1778
|
+
}), {
|
|
1564
1779
|
t: FRAME_ELEMENT_CLOSE
|
|
1565
1780
|
}];
|
|
1566
1781
|
wrapped[SERVER_COMPONENT] = id;
|
|
1782
|
+
wrapped[SERVER_COMPONENT_SOURCE] = component;
|
|
1783
|
+
wrapped[SERVER_COMPONENT_ADDRESS] = frameAddress(id, args);
|
|
1567
1784
|
return wrapped;
|
|
1568
1785
|
}
|
|
1569
1786
|
function resolveRegionHtml(ctx, node) {
|
|
@@ -1580,37 +1797,7 @@ function resolveRegionHtml(ctx, node) {
|
|
|
1580
1797
|
return out;
|
|
1581
1798
|
});
|
|
1582
1799
|
}
|
|
1583
|
-
const
|
|
1584
|
-
const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
1585
|
-
tag: "dom-expressions/server-component",
|
|
1586
|
-
test(value) {
|
|
1587
|
-
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
1588
|
-
},
|
|
1589
|
-
parse: {
|
|
1590
|
-
sync(value, ctx) {
|
|
1591
|
-
return {
|
|
1592
|
-
id: ctx.parse(value[SERVER_COMPONENT])
|
|
1593
|
-
};
|
|
1594
|
-
},
|
|
1595
|
-
async async(value, ctx) {
|
|
1596
|
-
return {
|
|
1597
|
-
id: await ctx.parse(value[SERVER_COMPONENT])
|
|
1598
|
-
};
|
|
1599
|
-
},
|
|
1600
|
-
stream(value, ctx) {
|
|
1601
|
-
return {
|
|
1602
|
-
id: ctx.parse(value[SERVER_COMPONENT])
|
|
1603
|
-
};
|
|
1604
|
-
}
|
|
1605
|
-
},
|
|
1606
|
-
serialize(node, ctx) {
|
|
1607
|
-
return "self._$SC.r(" + ctx.serialize(node.id) + ")";
|
|
1608
|
-
},
|
|
1609
|
-
deserialize(node, ctx) {
|
|
1610
|
-
return globalThis._$SC.r(ctx.deserialize(node.id));
|
|
1611
|
-
}
|
|
1612
|
-
});
|
|
1613
|
-
const SERVER_COMPONENT_BOOTSTRAP = "self._$SC={c:{},r(i){return this.c[i]||(this.c[i]=(p)=>self._$SC.impl(i,p))}};";
|
|
1800
|
+
const SERVER_COMPONENT_BOOTSTRAP = "self._$SC={c:{},a:{},r(i,a){a&&(this.a[a]=i,this.reg&&this.reg(a,i));return this.c[i]||(this.c[i]=(p)=>self._$SC.impl(i,p))}};";
|
|
1614
1801
|
function isServerContent(value) {
|
|
1615
1802
|
if (value && typeof value === "object") {
|
|
1616
1803
|
if ("t" in value) return true;
|
|
@@ -1719,7 +1906,7 @@ function serverComponentResponse(component, options = {}, init = {}) {
|
|
|
1719
1906
|
headers
|
|
1720
1907
|
});
|
|
1721
1908
|
}
|
|
1722
|
-
function frameTransformResult(event, result) {
|
|
1909
|
+
function frameTransformResult(event, result, context) {
|
|
1723
1910
|
let init;
|
|
1724
1911
|
if (isResponseEnvelope(result)) {
|
|
1725
1912
|
const {
|
|
@@ -1734,12 +1921,106 @@ function frameTransformResult(event, result) {
|
|
|
1734
1921
|
result = value;
|
|
1735
1922
|
}
|
|
1736
1923
|
if (typeof result !== "function") return result;
|
|
1737
|
-
|
|
1924
|
+
if (context && context.collectsFlight) return init ? {
|
|
1925
|
+
response: init,
|
|
1926
|
+
value: result
|
|
1927
|
+
} : result;
|
|
1928
|
+
const invocation = getEventServerFunctionInvocation(event);
|
|
1738
1929
|
return serverComponentResponse(result, {
|
|
1739
1930
|
frame: {
|
|
1740
|
-
id:
|
|
1931
|
+
id: invocation && invocation.id || ""
|
|
1741
1932
|
}
|
|
1742
1933
|
}, init);
|
|
1743
1934
|
}
|
|
1935
|
+
async function frameTransformFlightResult(event, outcome, context) {
|
|
1936
|
+
const {
|
|
1937
|
+
value,
|
|
1938
|
+
data
|
|
1939
|
+
} = outcome;
|
|
1940
|
+
const regions = [];
|
|
1941
|
+
let serialized = data;
|
|
1942
|
+
if (data && typeof data === "object") {
|
|
1943
|
+
serialized = {};
|
|
1944
|
+
const keys = Object.keys(data);
|
|
1945
|
+
const values = await Promise.all(keys.map(key => data[key]));
|
|
1946
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1947
|
+
const entry = values[i];
|
|
1948
|
+
serialized[keys[i]] = entry;
|
|
1949
|
+
if (typeof entry === "function") {
|
|
1950
|
+
regions.push({
|
|
1951
|
+
id: entry[SERVER_COMPONENT_ADDRESS] || keys[i],
|
|
1952
|
+
component: entry[SERVER_COMPONENT_SOURCE] || entry
|
|
1953
|
+
});
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
const invocation = getEventServerFunctionInvocation(event);
|
|
1958
|
+
const primary = typeof value === "function" ? {
|
|
1959
|
+
id: invocation && invocation.id || "",
|
|
1960
|
+
component: value
|
|
1961
|
+
} : undefined;
|
|
1962
|
+
if (!primary && !regions.length) return undefined;
|
|
1963
|
+
return frameFlightResponse({
|
|
1964
|
+
primary,
|
|
1965
|
+
regions,
|
|
1966
|
+
outcome: {
|
|
1967
|
+
value: primary ? undefined : value,
|
|
1968
|
+
data: serialized
|
|
1969
|
+
},
|
|
1970
|
+
codec: context && context.codec
|
|
1971
|
+
});
|
|
1972
|
+
}
|
|
1973
|
+
function frameFlightResponse({
|
|
1974
|
+
primary,
|
|
1975
|
+
regions = [],
|
|
1976
|
+
outcome,
|
|
1977
|
+
codec
|
|
1978
|
+
}, init = {}) {
|
|
1979
|
+
const frames = primary ? [primary, ...regions] : regions;
|
|
1980
|
+
const headers = new Headers(init.headers);
|
|
1981
|
+
headers.set("Content-Type", "application/x-frame-stream");
|
|
1982
|
+
headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
|
|
1983
|
+
headers.set("X-Content-Raw", "1");
|
|
1984
|
+
headers.set(SINGLE_FLIGHT_HEADER, "true");
|
|
1985
|
+
const body = new ReadableStream({
|
|
1986
|
+
async start(controller) {
|
|
1987
|
+
const write = chunk => controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
1988
|
+
try {
|
|
1989
|
+
for (const {
|
|
1990
|
+
id,
|
|
1991
|
+
component
|
|
1992
|
+
} of frames) {
|
|
1993
|
+
await new Promise(resolve => {
|
|
1994
|
+
renderServerComponent(component, {
|
|
1995
|
+
frame: {
|
|
1996
|
+
id,
|
|
1997
|
+
version: 1
|
|
1998
|
+
}
|
|
1999
|
+
}).pipe({
|
|
2000
|
+
write,
|
|
2001
|
+
end: resolve
|
|
2002
|
+
});
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
if (outcome) {
|
|
2006
|
+
const reader = new ChunkReader(serializeStream(outcome, flightCodec(codec)));
|
|
2007
|
+
for (let node = await reader.next(); !node.done; node = await reader.next()) {
|
|
2008
|
+
write({
|
|
2009
|
+
type: "outcome",
|
|
2010
|
+
payload: node.value
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
controller.close();
|
|
2015
|
+
} catch (err) {
|
|
2016
|
+
controller.error(err);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
return new Response(body, {
|
|
2021
|
+
status: init.status || 200,
|
|
2022
|
+
headers
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
1744
2025
|
|
|
1745
|
-
export { FRAME_STREAM_HEADER, SERVER_COMPONENT_BOOTSTRAP, ServerComponentPlugin, createFrameSink, frameTransformDirectResult, frameTransformResult, isFrameStreamResponse, renderServerComponent, renderToFrameStream, serverComponentResponse };
|
|
2026
|
+
export { FRAME_STREAM_HEADER, SERVER_COMPONENT_BOOTSTRAP, ServerComponentPlugin, createFrameSink, frameTransformDirectResult, frameTransformFlightResult, frameTransformResult, isFrameStreamResponse, renderServerComponent, renderToFrameStream, serverComponentResponse };
|
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.29",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://solidjs.com",
|
|
@@ -316,10 +316,10 @@
|
|
|
316
316
|
"seroval-plugins": "~1.5.4"
|
|
317
317
|
},
|
|
318
318
|
"peerDependencies": {
|
|
319
|
-
"solid-js": "^2.0.0-beta.
|
|
319
|
+
"solid-js": "^2.0.0-beta.29"
|
|
320
320
|
},
|
|
321
321
|
"devDependencies": {
|
|
322
|
-
"solid-js": "2.0.0-beta.
|
|
322
|
+
"solid-js": "2.0.0-beta.29"
|
|
323
323
|
},
|
|
324
324
|
"scripts": {
|
|
325
325
|
"build": "npm-run-all -nl build:clean types:copy-jsx build:js",
|
|
@@ -42,6 +42,9 @@ const codecConfig = {
|
|
|
42
42
|
function configureServerFunctionsCodec(codec) {
|
|
43
43
|
codecConfig.codec = codec;
|
|
44
44
|
}
|
|
45
|
+
function getServerFunctionsCodec() {
|
|
46
|
+
return codecConfig.codec;
|
|
47
|
+
}
|
|
45
48
|
const flightConfig = {
|
|
46
49
|
consumer: undefined
|
|
47
50
|
};
|
|
@@ -54,6 +57,50 @@ function subscribeFlightData(consumer) {
|
|
|
54
57
|
function getFlightDataConsumer() {
|
|
55
58
|
return flightConfig.consumer;
|
|
56
59
|
}
|
|
60
|
+
function frameAddress(id, args) {
|
|
61
|
+
return args && args.length ? id + ":" + hashArguments(args) : id;
|
|
62
|
+
}
|
|
63
|
+
function hashArguments(args) {
|
|
64
|
+
let hash = 0;
|
|
65
|
+
const text = stableString(args);
|
|
66
|
+
for (let i = 0; i < text.length; i++) {
|
|
67
|
+
hash = (hash << 5) - hash + text.charCodeAt(i);
|
|
68
|
+
hash |= 0;
|
|
69
|
+
}
|
|
70
|
+
return (hash >>> 0).toString(36);
|
|
71
|
+
}
|
|
72
|
+
function stableString(value, seen) {
|
|
73
|
+
if (value === null || typeof value !== "object") {
|
|
74
|
+
return typeof value === "bigint" ? value + "n" : String(value);
|
|
75
|
+
}
|
|
76
|
+
if (value instanceof Date) return "Date:" + value.getTime();
|
|
77
|
+
seen || (seen = new Set());
|
|
78
|
+
if (seen.has(value)) return "~";
|
|
79
|
+
seen.add(value);
|
|
80
|
+
if (value instanceof Map) {
|
|
81
|
+
const entries = [];
|
|
82
|
+
for (const [k, v] of value) {
|
|
83
|
+
entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
|
|
84
|
+
}
|
|
85
|
+
return "Map{" + entries.sort().join(",") + "}";
|
|
86
|
+
}
|
|
87
|
+
if (value instanceof Set) {
|
|
88
|
+
const members = [];
|
|
89
|
+
for (const v of value) members.push(stableString(v, seen));
|
|
90
|
+
return "Set{" + members.sort().join(",") + "}";
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
let out = "[";
|
|
94
|
+
for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
|
|
95
|
+
return out + "]";
|
|
96
|
+
}
|
|
97
|
+
const keys = Object.keys(value).sort();
|
|
98
|
+
let out = "{";
|
|
99
|
+
for (let i = 0; i < keys.length; i++) {
|
|
100
|
+
out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
|
|
101
|
+
}
|
|
102
|
+
return out + "}";
|
|
103
|
+
}
|
|
57
104
|
const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
|
|
58
105
|
function getServerFunctionMetadata(fn) {
|
|
59
106
|
if (typeof fn !== "function") return undefined;
|
|
@@ -211,6 +258,17 @@ async function extractBody(source, codecOptions) {
|
|
|
211
258
|
}
|
|
212
259
|
return undefined;
|
|
213
260
|
}
|
|
261
|
+
function createChunk(data) {
|
|
262
|
+
const encodeData = new TextEncoder().encode(data);
|
|
263
|
+
const bytes = encodeData.length;
|
|
264
|
+
const baseHex = bytes.toString(16);
|
|
265
|
+
const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex;
|
|
266
|
+
const head = new TextEncoder().encode(`;0x${totalHex};`);
|
|
267
|
+
const chunk = new Uint8Array(12 + bytes);
|
|
268
|
+
chunk.set(head);
|
|
269
|
+
chunk.set(encodeData, 12);
|
|
270
|
+
return chunk;
|
|
271
|
+
}
|
|
214
272
|
class ChunkReader {
|
|
215
273
|
constructor(stream) {
|
|
216
274
|
this.reader = stream.getReader();
|
|
@@ -391,6 +449,21 @@ async function initializeResponse(base, id, instance, options, args, meta) {
|
|
|
391
449
|
}
|
|
392
450
|
}, meta);
|
|
393
451
|
}
|
|
452
|
+
if (args.length > 1) {
|
|
453
|
+
const trailing = getHeadersAndBody(args[args.length - 1]);
|
|
454
|
+
const leading = args.slice(0, -1).map(arg => arg === undefined ? null : arg);
|
|
455
|
+
if (trailing && isJSONSafe(leading)) {
|
|
456
|
+
const target = base + (base.includes("?") ? "&" : "?") + "args=" + encodeURIComponent(JSON.stringify(leading));
|
|
457
|
+
return createRequest(target, id, instance, {
|
|
458
|
+
...options,
|
|
459
|
+
body: trailing.body,
|
|
460
|
+
headers: {
|
|
461
|
+
...options.headers,
|
|
462
|
+
...trailing.headers
|
|
463
|
+
}
|
|
464
|
+
}, meta);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
394
467
|
return createRequest(base, id, instance, {
|
|
395
468
|
...options,
|
|
396
469
|
body: await serializeArguments(args),
|
|
@@ -401,7 +474,7 @@ async function initializeResponse(base, id, instance, options, args, meta) {
|
|
|
401
474
|
}
|
|
402
475
|
}, meta);
|
|
403
476
|
}
|
|
404
|
-
async function fetchServerFunction(base, id, options, args, meta) {
|
|
477
|
+
async function fetchServerFunction(base, id, options, args, meta, callArgs = args) {
|
|
405
478
|
const instance = `server-function:${INSTANCE++}`;
|
|
406
479
|
const handler = config.responseHandler;
|
|
407
480
|
const context = handler && handler.capture ? handler.capture({
|
|
@@ -413,7 +486,7 @@ async function fetchServerFunction(base, id, options, args, meta) {
|
|
|
413
486
|
const handled = handler.handle(response, {
|
|
414
487
|
id,
|
|
415
488
|
meta,
|
|
416
|
-
args,
|
|
489
|
+
args: callArgs,
|
|
417
490
|
context
|
|
418
491
|
});
|
|
419
492
|
if (handled !== undefined) return handled;
|
|
@@ -492,7 +565,7 @@ function GET(fn) {
|
|
|
492
565
|
}
|
|
493
566
|
return fetchServerFunction(base, id, {
|
|
494
567
|
method: "GET"
|
|
495
|
-
}, [], metadata);
|
|
568
|
+
}, [], metadata, args);
|
|
496
569
|
};
|
|
497
570
|
wrapped[SERVER_FUNCTION_METADATA] = metadata;
|
|
498
571
|
wrapped.id = id;
|
|
@@ -507,21 +580,32 @@ function GET(fn) {
|
|
|
507
580
|
function registerServerReference() {
|
|
508
581
|
throw new Error("registerServerReference must not be called in the client build");
|
|
509
582
|
}
|
|
583
|
+
function getServerFunctionInvocation() {
|
|
584
|
+
return undefined;
|
|
585
|
+
}
|
|
510
586
|
|
|
587
|
+
exports.ChunkReader = ChunkReader;
|
|
511
588
|
exports.ERROR_HEADER = ERROR_HEADER;
|
|
512
589
|
exports.FLASH_COOKIE = FLASH_COOKIE;
|
|
513
590
|
exports.FUNCTION_HEADER = FUNCTION_HEADER;
|
|
514
591
|
exports.GET = GET;
|
|
515
592
|
exports.INSTANCE_HEADER = INSTANCE_HEADER;
|
|
593
|
+
exports.REVALIDATE_HEADER = REVALIDATE_HEADER;
|
|
516
594
|
exports.SINGLE_FLIGHT_HEADER = SINGLE_FLIGHT_HEADER;
|
|
517
595
|
exports.clearFlashCookie = clearFlashCookie;
|
|
518
596
|
exports.configureServerFunctionsClient = configureServerFunctionsClient;
|
|
597
|
+
exports.createChunk = createChunk;
|
|
519
598
|
exports.createServerReference = createServerReference;
|
|
520
599
|
exports.decodeErrorHeaderValue = decodeErrorHeaderValue;
|
|
521
600
|
exports.decodeResponse = decodeResponse;
|
|
522
601
|
exports.decodeResponsePayload = decodeResponsePayload;
|
|
602
|
+
exports.deserializeStream = deserializeStream;
|
|
523
603
|
exports.encodeErrorHeaderValue = encodeErrorHeaderValue;
|
|
604
|
+
exports.frameAddress = frameAddress;
|
|
605
|
+
exports.getFlightDataConsumer = getFlightDataConsumer;
|
|
606
|
+
exports.getServerFunctionInvocation = getServerFunctionInvocation;
|
|
524
607
|
exports.getServerFunctionMetadata = getServerFunctionMetadata;
|
|
608
|
+
exports.getServerFunctionsCodec = getServerFunctionsCodec;
|
|
525
609
|
exports.hasFlashCookie = hasFlashCookie;
|
|
526
610
|
exports.isServerFunction = isServerFunction;
|
|
527
611
|
exports.registerServerReference = registerServerReference;
|