Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .changeset/fast-frame-refill.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/revert-fast-frame-refill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflow/world-vercel': patch
---

Revert the deferred frame-buffer concatenation in `decodeFrames`: stashing yielded chunk views across `await`s let the stream reuse their backing buffers before the copy, corrupting encrypted frame payloads (vercel-world e2e and WS transport lanes failed fleet-wide). Chunks are copied on receipt again.
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ jobs:
e2e-vercel-prod:
name: E2E Vercel Prod Tests (${{ matrix.app.name }} - ${{ matrix.vm }})
runs-on: ubuntu-latest
timeout-minutes: 30
# The quickjs lanes run the WASM engine and have outgrown 30 minutes as
# the suite grew (nextjs-turbopack quickjs was killed mid-final-group,
# all tests passing, on three consecutive attempts on 2026-08-18).
timeout-minutes: 40
needs: ci-scope
if: ${{ needs.ci-scope.outputs.fast-path != 'true' }}
permissions:
Expand Down
25 changes: 8 additions & 17 deletions packages/world-vercel/src/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,14 @@ export async function* decodeFrames(
let buffer = new Uint8Array(0);

const refill = async (needed: number): Promise<boolean> => {
if (buffer.byteLength >= needed) return true;

const parts: Uint8Array[] = [buffer];
let byteLength = buffer.byteLength;
while (byteLength < needed) {
const chunk = await chunks.next();
if (chunk.done) return false;
if (chunk.value.byteLength === 0) continue;
parts.push(chunk.value);
byteLength += chunk.value.byteLength;
}

buffer = new Uint8Array(byteLength);
let offset = 0;
for (const part of parts) {
buffer.set(part, offset);
offset += part.byteLength;
while (buffer.byteLength < needed) {
const { done, value } = await chunks.next();
if (done) return false;
if (!value || value.byteLength === 0) continue;
const next = new Uint8Array(buffer.byteLength + value.byteLength);
next.set(buffer, 0);
next.set(value, buffer.byteLength);
buffer = next;
Comment on lines +72 to +76
}
return true;
};
Expand Down
Loading