octane 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/runtime.cjs +99 -35
- package/dist/cjs/runtime.server.cjs +76 -39
- package/dist/cjs/server/streamed-signals.cjs +97 -62
- package/dist/cjs/version.cjs +1 -1
- package/dist/compiler/compile.js +489 -27
- package/dist/compiler/hydrate-boundaries.js +118 -0
- package/dist/compiler/private-context.js +160 -0
- package/dist/hydration/stream-delivery.d.ts +1 -1
- package/dist/hydration/stream-delivery.js +16 -9
- package/dist/hydration/stream-result-receiver.d.ts +1 -0
- package/dist/hydration/stream-result-receiver.js +8 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.js +97 -35
- package/dist/runtime.server.d.ts +8 -2
- package/dist/runtime.server.js +76 -39
- package/dist/server/streamed-signals.d.ts +1 -0
- package/dist/server/streamed-signals.js +97 -62
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -117,10 +117,7 @@ function createStreamedRendererFrameStream(frames, options = {}) {
|
|
|
117
117
|
let totalBytes = 0;
|
|
118
118
|
let finished = false;
|
|
119
119
|
let controller;
|
|
120
|
-
|
|
121
|
-
() => fail(new Error("Streamed renderer response timed out.")),
|
|
122
|
-
budget.timeoutMs
|
|
123
|
-
);
|
|
120
|
+
let timer;
|
|
124
121
|
const cleanup = () => {
|
|
125
122
|
clearTimeout(timer);
|
|
126
123
|
options.signal?.removeEventListener("abort", abort);
|
|
@@ -149,8 +146,13 @@ function createStreamedRendererFrameStream(frames, options = {}) {
|
|
|
149
146
|
},
|
|
150
147
|
async pull() {
|
|
151
148
|
if (finished) return;
|
|
149
|
+
timer = setTimeout(
|
|
150
|
+
() => fail(new Error("Streamed renderer response timed out.")),
|
|
151
|
+
budget.timeoutMs
|
|
152
|
+
);
|
|
152
153
|
try {
|
|
153
154
|
const next = await iterator.next();
|
|
155
|
+
clearTimeout(timer);
|
|
154
156
|
if (finished) return;
|
|
155
157
|
if (next.done) {
|
|
156
158
|
finished = true;
|
|
@@ -191,10 +193,15 @@ function streamedSignalSelectionScript(identity, nonce) {
|
|
|
191
193
|
return `<script ${import_stream_protocol.STREAM_SCRIPT_ATTR}${nonce === void 0 ? "" : ` nonce="${escapeAttribute(nonce)}"`}>(function(g){var k="__octaneStreamedRenderer",e=g[k];if(!e){var q=[];g[k]={version:1,frames:q,receive:function(f){if(q.length>=512){this.overflow=true;return;}q.push(f);}};}var z="__octaneStreamedSignalSelections",v=g[z];if(!v){var a=[];v=g[z]={version:1,identities:a,register:function(i){if(a.length>=256){this.overflow=true;return;}a.push(i);}};}v.register(${encoded});})(globalThis);</script>`;
|
|
192
194
|
}
|
|
193
195
|
function createStreamedSignalInjection(identity, result, options = {}) {
|
|
196
|
+
return createSignalInjection(identity, result, options, "Streamed renderer injection timed out.");
|
|
197
|
+
}
|
|
198
|
+
function createSignalInjection(identity, result, options, timeoutMessage) {
|
|
194
199
|
const budget = limits(options);
|
|
195
200
|
const iterator = createStreamedSignalResultFrames(identity, result, options)[Symbol.asyncIterator]();
|
|
196
201
|
let queued = options.announceSelection ? streamedSignalSelectionScript(identity, options.nonce) : "";
|
|
197
202
|
let pending = false;
|
|
203
|
+
let awaitingAcceptance = false;
|
|
204
|
+
let queuedBytes = queued === "" ? 0 : new TextEncoder().encode(queued).byteLength;
|
|
198
205
|
let finished = false;
|
|
199
206
|
let subscribed = false;
|
|
200
207
|
let totalBytes = 0;
|
|
@@ -225,11 +232,13 @@ function createStreamedSignalInjection(identity, result, options = {}) {
|
|
|
225
232
|
rejectDone(error);
|
|
226
233
|
};
|
|
227
234
|
const pump = () => {
|
|
228
|
-
if (!subscribed || pending || queued !== "" || finished) return;
|
|
235
|
+
if (!subscribed || pending || awaitingAcceptance || queued !== "" || finished) return;
|
|
229
236
|
pending = true;
|
|
237
|
+
timer = setTimeout(() => fail(new Error(timeoutMessage)), budget.timeoutMs);
|
|
230
238
|
void iterator.next().then(
|
|
231
239
|
(next) => {
|
|
232
240
|
pending = false;
|
|
241
|
+
clearTimeout(timer);
|
|
233
242
|
if (finished) return;
|
|
234
243
|
if (next.done) {
|
|
235
244
|
finished = true;
|
|
@@ -245,6 +254,7 @@ function createStreamedSignalInjection(identity, result, options = {}) {
|
|
|
245
254
|
}
|
|
246
255
|
totalBytes += bytes;
|
|
247
256
|
queued = html;
|
|
257
|
+
queuedBytes = bytes;
|
|
248
258
|
notify?.();
|
|
249
259
|
},
|
|
250
260
|
(error) => {
|
|
@@ -256,17 +266,17 @@ function createStreamedSignalInjection(identity, result, options = {}) {
|
|
|
256
266
|
const abort = () => {
|
|
257
267
|
fail(options.signal?.reason ?? new DOMException("Aborted", "AbortError"));
|
|
258
268
|
};
|
|
259
|
-
timer = setTimeout(
|
|
260
|
-
() => fail(new Error("Streamed renderer injection timed out.")),
|
|
261
|
-
budget.timeoutMs
|
|
262
|
-
);
|
|
263
269
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
264
270
|
if (options.signal?.aborted) abort();
|
|
265
271
|
return {
|
|
266
272
|
streamedRenderer: true,
|
|
273
|
+
get queuedBytes() {
|
|
274
|
+
return queuedBytes;
|
|
275
|
+
},
|
|
267
276
|
take() {
|
|
268
277
|
const html = queued;
|
|
269
278
|
queued = "";
|
|
279
|
+
if (html !== "") awaitingAcceptance = true;
|
|
270
280
|
return html;
|
|
271
281
|
},
|
|
272
282
|
subscribe(callback) {
|
|
@@ -278,6 +288,7 @@ function createStreamedSignalInjection(identity, result, options = {}) {
|
|
|
278
288
|
};
|
|
279
289
|
},
|
|
280
290
|
accepted() {
|
|
291
|
+
awaitingAcceptance = false;
|
|
281
292
|
pump();
|
|
282
293
|
},
|
|
283
294
|
cancel: fail,
|
|
@@ -296,17 +307,20 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
296
307
|
if (!Number.isSafeInteger(selectionGeneration) || selectionGeneration < 0) {
|
|
297
308
|
throw new RangeError("selectionGeneration must be a nonnegative safe integer.");
|
|
298
309
|
}
|
|
299
|
-
const children =
|
|
310
|
+
const children = /* @__PURE__ */ new Set();
|
|
311
|
+
const ready = /* @__PURE__ */ new Set();
|
|
300
312
|
const observedAttempts = /* @__PURE__ */ new Set();
|
|
301
313
|
let initialSelections = [];
|
|
302
314
|
let queued = "";
|
|
303
315
|
let active;
|
|
316
|
+
let awaitingAcceptance = false;
|
|
317
|
+
let hasSignalAttempts = false;
|
|
318
|
+
let pumping = false;
|
|
304
319
|
let subscribed = false;
|
|
305
320
|
let renderComplete = false;
|
|
306
321
|
let finished = false;
|
|
307
322
|
let totalBytes = 0;
|
|
308
323
|
let notify;
|
|
309
|
-
let timer;
|
|
310
324
|
let resolveDone;
|
|
311
325
|
let rejectDone;
|
|
312
326
|
const done = new Promise((resolve, reject) => {
|
|
@@ -314,6 +328,8 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
314
328
|
rejectDone = reject;
|
|
315
329
|
});
|
|
316
330
|
const cleanupChild = (child) => {
|
|
331
|
+
if (!children.delete(child)) return;
|
|
332
|
+
ready.delete(child);
|
|
317
333
|
try {
|
|
318
334
|
child.unsubscribe();
|
|
319
335
|
} catch {
|
|
@@ -326,7 +342,6 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
326
342
|
const fail = (error) => {
|
|
327
343
|
if (finished) return;
|
|
328
344
|
finished = true;
|
|
329
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
330
345
|
for (const child of children) {
|
|
331
346
|
try {
|
|
332
347
|
child.source.cancel?.(error);
|
|
@@ -337,11 +352,9 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
337
352
|
rejectDone(error);
|
|
338
353
|
};
|
|
339
354
|
const maybeDone = () => {
|
|
340
|
-
if (finished || !renderComplete || active !== void 0 || queued !== "")
|
|
341
|
-
|
|
355
|
+
if (finished || !renderComplete || active !== void 0 || awaitingAcceptance || queued !== "" || children.size !== 0)
|
|
356
|
+
return;
|
|
342
357
|
finished = true;
|
|
343
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
344
|
-
for (const child of children) cleanupChild(child);
|
|
345
358
|
resolveDone();
|
|
346
359
|
};
|
|
347
360
|
const takeInitialSelections = () => {
|
|
@@ -363,33 +376,41 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
363
376
|
return html;
|
|
364
377
|
};
|
|
365
378
|
const pump = () => {
|
|
366
|
-
if (!subscribed || finished || active !== void 0 || queued !== "")
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
if (pumping || !subscribed || finished || active !== void 0 || awaitingAcceptance || queued !== "")
|
|
380
|
+
return;
|
|
381
|
+
pumping = true;
|
|
382
|
+
try {
|
|
383
|
+
if (initialSelections !== void 0) {
|
|
384
|
+
try {
|
|
385
|
+
queued = takeInitialSelections();
|
|
386
|
+
} catch {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (queued !== "") notify?.();
|
|
372
390
|
}
|
|
373
|
-
|
|
391
|
+
for (const child of ready) {
|
|
392
|
+
if (finished || active !== void 0 || awaitingAcceptance || queued !== "") return;
|
|
393
|
+
ready.delete(child);
|
|
394
|
+
const html = child.source.take();
|
|
395
|
+
if (finished) return;
|
|
396
|
+
if (html === "") {
|
|
397
|
+
if (child.done && (child.attempt !== void 0 || renderComplete)) cleanupChild(child);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const bytes = child.attempt === void 0 ? new TextEncoder().encode(html).byteLength : child.source.queuedBytes;
|
|
401
|
+
if (bytes > budget.maxFrameBytes || totalBytes + bytes > budget.maxTotalBytes) {
|
|
402
|
+
fail(new Error("Automatic streamed signals exceeded their byte budget."));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
totalBytes += bytes;
|
|
406
|
+
active = child;
|
|
407
|
+
queued = html;
|
|
374
408
|
notify?.();
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
for (const child of children) {
|
|
379
|
-
const html = child.source.take();
|
|
380
|
-
if (html === "") continue;
|
|
381
|
-
const bytes = new TextEncoder().encode(html).byteLength;
|
|
382
|
-
if (bytes > budget.maxFrameBytes || totalBytes + bytes > budget.maxTotalBytes) {
|
|
383
|
-
fail(new Error("Automatic streamed signals exceeded their byte budget."));
|
|
384
|
-
return;
|
|
385
409
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
notify?.();
|
|
390
|
-
return;
|
|
410
|
+
maybeDone();
|
|
411
|
+
} finally {
|
|
412
|
+
pumping = false;
|
|
391
413
|
}
|
|
392
|
-
maybeDone();
|
|
393
414
|
};
|
|
394
415
|
const addChild = (source, release, attempt) => {
|
|
395
416
|
const child = {
|
|
@@ -400,17 +421,23 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
400
421
|
...attempt === void 0 ? {} : { attempt },
|
|
401
422
|
done: false
|
|
402
423
|
};
|
|
403
|
-
children.
|
|
404
|
-
|
|
424
|
+
children.add(child);
|
|
425
|
+
const available = () => {
|
|
426
|
+
if (finished || !children.has(child)) return;
|
|
427
|
+
ready.add(child);
|
|
428
|
+
pump();
|
|
429
|
+
};
|
|
430
|
+
ready.add(child);
|
|
431
|
+
child.unsubscribe = source.subscribe(available);
|
|
405
432
|
source.done.then(
|
|
406
433
|
() => {
|
|
407
434
|
child.done = true;
|
|
408
|
-
|
|
435
|
+
available();
|
|
409
436
|
},
|
|
410
437
|
(error) => {
|
|
411
438
|
if (child.attempt !== void 0 && !child.attempt.isCurrent()) {
|
|
412
439
|
child.done = true;
|
|
413
|
-
|
|
440
|
+
available();
|
|
414
441
|
} else fail(error);
|
|
415
442
|
}
|
|
416
443
|
);
|
|
@@ -421,7 +448,7 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
421
448
|
takeInitialSelections,
|
|
422
449
|
createSignalAttemptObservations: import_signal_query_observation.createServerSignalQueryAttemptObservations,
|
|
423
450
|
get streamedRenderer() {
|
|
424
|
-
return external?.streamedRenderer === true ||
|
|
451
|
+
return external?.streamedRenderer === true || hasSignalAttempts ? true : void 0;
|
|
425
452
|
},
|
|
426
453
|
observeSignalAttempt(attempt, run) {
|
|
427
454
|
if (finished || !attempt.isCurrent()) {
|
|
@@ -439,18 +466,13 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
439
466
|
attempt.release();
|
|
440
467
|
return;
|
|
441
468
|
}
|
|
442
|
-
if (children.
|
|
469
|
+
if (children.size >= 256) {
|
|
443
470
|
attempt.release();
|
|
444
471
|
fail(new Error("Automatic streamed signals exceeded their channel budget."));
|
|
445
472
|
return;
|
|
446
473
|
}
|
|
447
474
|
observedAttempts.add(attemptKey);
|
|
448
|
-
|
|
449
|
-
timer = setTimeout(
|
|
450
|
-
() => fail(new Error("Automatic streamed signals timed out.")),
|
|
451
|
-
budget.timeoutMs
|
|
452
|
-
);
|
|
453
|
-
}
|
|
475
|
+
hasSignalAttempts = true;
|
|
454
476
|
const identity = {
|
|
455
477
|
protocol: 1,
|
|
456
478
|
buildId: options.buildId,
|
|
@@ -463,21 +485,27 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
463
485
|
attempt: attempt.attempt
|
|
464
486
|
};
|
|
465
487
|
initialSelections?.push({ identity, attempt });
|
|
466
|
-
const source =
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
488
|
+
const source = createSignalInjection(
|
|
489
|
+
identity,
|
|
490
|
+
attempt.result,
|
|
491
|
+
{
|
|
492
|
+
signal: attempt.signal,
|
|
493
|
+
run,
|
|
494
|
+
nonce: options.nonce,
|
|
495
|
+
announceSelection: initialSelections === void 0,
|
|
496
|
+
maxFrameBytes: budget.maxFrameBytes,
|
|
497
|
+
maxTotalBytes: budget.maxTotalBytes,
|
|
498
|
+
timeoutMs: budget.timeoutMs
|
|
499
|
+
},
|
|
500
|
+
"Automatic streamed signals timed out."
|
|
501
|
+
);
|
|
475
502
|
addChild(source, attempt.release, attempt);
|
|
476
503
|
pump();
|
|
477
504
|
},
|
|
478
505
|
take() {
|
|
479
506
|
const html = queued;
|
|
480
507
|
queued = "";
|
|
508
|
+
if (html !== "") awaitingAcceptance = true;
|
|
481
509
|
return html;
|
|
482
510
|
},
|
|
483
511
|
subscribe(callback) {
|
|
@@ -490,15 +518,22 @@ function createAutomaticStreamedSignalInjection(options, external) {
|
|
|
490
518
|
},
|
|
491
519
|
accepted() {
|
|
492
520
|
const child = active;
|
|
493
|
-
active = void 0;
|
|
494
521
|
child?.source.accepted?.();
|
|
522
|
+
if (child !== void 0 && children.has(child)) ready.add(child);
|
|
523
|
+
active = void 0;
|
|
524
|
+
awaitingAcceptance = false;
|
|
495
525
|
pump();
|
|
496
526
|
},
|
|
497
527
|
cancel: fail,
|
|
498
528
|
done,
|
|
499
529
|
renderComplete() {
|
|
500
530
|
renderComplete = true;
|
|
501
|
-
|
|
531
|
+
external?.renderComplete?.();
|
|
532
|
+
for (const child of children) {
|
|
533
|
+
if (child.attempt !== void 0) child.source.renderComplete?.();
|
|
534
|
+
if (child.done) ready.add(child);
|
|
535
|
+
}
|
|
536
|
+
pump();
|
|
502
537
|
maybeDone();
|
|
503
538
|
}
|
|
504
539
|
};
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -21,7 +21,7 @@ __export(version_exports, {
|
|
|
21
21
|
version: () => version
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(version_exports);
|
|
24
|
-
const version = "0.3.
|
|
24
|
+
const version = "0.3.1";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
version
|