mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibWeb: Make TransferArrayBuffer zero-copy
Move owned ArrayBuffer storage directly when transferring stream buffers instead of copying the bytes before detaching the source. WebAssembly memory continues to copy because its ArrayBuffer wraps externally-owned storage. Preserve the abrupt completion from DetachArrayBuffer before moving storage so non-transferable buffers, such as WebAssembly.Memory-backed views, still surface TypeError through stream operations instead of aborting. This saves ~130ms of main thread time when loading a YouTube video on my Linux computer. :^)
This commit is contained in:
committed by
Andreas Kling
parent
59bf30f17f
commit
b629914428
Notes:
github-actions[bot]
2026-04-25 08:55:16 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/b6299144288 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/9088
@@ -0,0 +1,6 @@
|
||||
read() rejected with TypeError: true
|
||||
Read buffer byteLength: 65536
|
||||
enqueue() threw TypeError: true
|
||||
Enqueue buffer byteLength: 65536
|
||||
respondWithNewView() rejected with TypeError: true
|
||||
RespondWithNewView buffer byteLength: 65536
|
||||
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
asyncTest(async done => {
|
||||
{
|
||||
const stream = new ReadableStream({ type: "bytes" });
|
||||
const reader = stream.getReader({ mode: "byob" });
|
||||
const memory = new WebAssembly.Memory({ initial: 1 });
|
||||
const view = new Uint8Array(memory.buffer, 0, 8);
|
||||
|
||||
try {
|
||||
await reader.read(view);
|
||||
println("FAIL: read() should reject");
|
||||
} catch (error) {
|
||||
println(`read() rejected with TypeError: ${error instanceof TypeError}`);
|
||||
}
|
||||
|
||||
println(`Read buffer byteLength: ${memory.buffer.byteLength}`);
|
||||
}
|
||||
|
||||
{
|
||||
let controller;
|
||||
new ReadableStream({
|
||||
type: "bytes",
|
||||
start(streamController) {
|
||||
controller = streamController;
|
||||
},
|
||||
});
|
||||
const memory = new WebAssembly.Memory({ initial: 1 });
|
||||
|
||||
try {
|
||||
controller.enqueue(new Uint8Array(memory.buffer, 0, 8));
|
||||
println("FAIL: enqueue() should throw");
|
||||
} catch (error) {
|
||||
println(`enqueue() threw TypeError: ${error instanceof TypeError}`);
|
||||
}
|
||||
|
||||
println(`Enqueue buffer byteLength: ${memory.buffer.byteLength}`);
|
||||
}
|
||||
|
||||
{
|
||||
const memory = new WebAssembly.Memory({ initial: 1 });
|
||||
const stream = new ReadableStream({
|
||||
type: "bytes",
|
||||
pull(controller) {
|
||||
controller.byobRequest.respondWithNewView(new Uint8Array(memory.buffer, 0, 8));
|
||||
},
|
||||
});
|
||||
const reader = stream.getReader({ mode: "byob" });
|
||||
|
||||
try {
|
||||
await reader.read(new Uint8Array(new ArrayBuffer(memory.buffer.byteLength), 0, 8));
|
||||
println("FAIL: read() should reject after respondWithNewView()");
|
||||
} catch (error) {
|
||||
println(`respondWithNewView() rejected with TypeError: ${error instanceof TypeError}`);
|
||||
}
|
||||
|
||||
println(`RespondWithNewView buffer byteLength: ${memory.buffer.byteLength}`);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user