-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Streams: tests for readable byte stream fixes #28557
Streams: tests for readable byte stream fixes #28557
Conversation
function transferArrayBufferView(view) { | ||
const noopByteStream = new ReadableStream({ | ||
type: 'bytes', | ||
pull(c) { | ||
c.byobRequest.respond(c.byobRequest.view.byteLength); | ||
c.close(); | ||
} | ||
}); | ||
const reader = noopByteStream.getReader({ mode: 'byob' }); | ||
return reader.read(view).then((result) => result.value); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the "easiest" solution I could come up with to transfer an ArrayBufferView
.
We could also use postMessage()
like we do with createTransferredReadableStream, but then we also need to change the test setup for the reference implementation... and I can't be bothered. 😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enqueue-with-detached-buffer.window.js also uses postMessage, hmm. It might be worth changing https://github.com/whatwg/streams/blob/0ff6d4508b58acce28386696b2854b2a1570d205/reference-implementation/run-web-platform-tests.js#L43-L56 to just stick the "transferred" flag onto the transferred argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean replacing window.postMessage(message, targetOrigin, transfer)
to add our special "transferred" flag to every ArrayBuffer
in transfer
? It'll be a bit complicated:
- We need to export the TransferArrayBuffer helper in index.js, so that we can access it after loading the bundle. We have to use the same helper, so that it'll use the exact same isFakeDetached symbol.
- We have to transfer any
ArrayBuffer
s insidetransfer
and replace all references to those buffers insidemessage
. Sure, we can assume that for our tests, the message will always be anArrayBufferView
(and not some deeply nested JavaScript object). We'll then have to re-construct that view onto the transferred buffer.
Sure, I guess I can try it. Not sure if it'll be pretty though. 😛 (It's times like these where I wish tc39/proposal-resizablearraybuffer were already a reality... 😞)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I'm not sure it's worth it; just an idea to throw out there!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, so this would work:
const windowPostMessage = window.postMessage.bind(window);
window.postMessage = function (message, targetOrigin, transfer) {
if (targetOrigin === '*' && transfer.length === 1 && transfer[0] instanceof window.ArrayBuffer) {
const originalBuffer = transfer[0];
const transferredBuffer = window.whatwgStreamsInternals.TransferArrayBuffer(originalBuffer);
if (window.ArrayBuffer.isView(message) && message.buffer === originalBuffer) {
message = new message.constructor(transferredBuffer, message.byteOffset, message.byteLength);
}
transfer = [transferredBuffer];
}
windowPostMessage(message, targetOrigin, transfer);
};
window.whatwgStreamsInternals
would be defined in lib/index.js
as:
// ...
const { TransferArrayBuffer } = require('./abstract-ops/ecmascript.js');
window.whatwgStreamsInternals = { TransferArrayBuffer };
Then we can change transferArrayBufferView
inside the test utilities:
function transferArrayBufferView(view) {
return new Promise((resolve) => {
self.addEventListener('message', (event) => resolve(event.data), { once: true });
self.postMessage(view, '*', [view.buffer]);
});
}
Do we like this better? I think it looks nicer in WPT, but the runner becomes a little bit more complicated. That said, many different browser developers need to read and understand the WPT tests, so I suppose we should favor simplicity of the tests over simplicity of our test runner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the version that doesn't involve us monkey patching postMessage in the reference implementation. The weirdness of the byte-stream-based transferArrayBufferView()
implementation is nicely encapsulated, so it's not hurting anyone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I slightly prefer the monkeypatch, but I'll defer to @ricea.
9b7f435
to
6aeaa1c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it's not testing the wasm memory case? Should we add those? It probably causes some reference implementation headaches, but seems like important coverage since those kind of un-transferrable buffers are so different from already-transferred ones.
function transferArrayBufferView(view) { | ||
const noopByteStream = new ReadableStream({ | ||
type: 'bytes', | ||
pull(c) { | ||
c.byobRequest.respond(c.byobRequest.view.byteLength); | ||
c.close(); | ||
} | ||
}); | ||
const reader = noopByteStream.getReader({ mode: 'byob' }); | ||
return reader.read(view).then((result) => result.value); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enqueue-with-detached-buffer.window.js also uses postMessage, hmm. It might be worth changing https://github.com/whatwg/streams/blob/0ff6d4508b58acce28386696b2854b2a1570d205/reference-implementation/run-web-platform-tests.js#L43-L56 to just stick the "transferred" flag onto the transferred argument.
Indeed, I didn't write tests for WebAssembly memories yet because I don't know how to make those work in the reference implementation... 😕 Is there an easy way to test whether a given Alternatively, we put all the WebAssembly-related tests in a separate file and filter them out for the reference implementation's test runs? |
Yeah, separate file is probably the best way to go. |
…-transferable buffers
97d37b5
to
a414e58
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! lgtm.
See whatwg/streams#1123 for the accompanying spec change.
To do:
WebAssembly.Memory
's buffer tobyobReader.read()
,byteStreamController.enqueue()
andbyobRequest.respondWithNewView()
throws an error.