Skip to content

Commit 49da1a5

Browse files
committed
webstreams: improve respondWithNewView()
This fixes validating an ArrayBufferView given to ReadableStreamBYOBRequest.respondWithNewView() to improve the web streams compatibility. Signed-off-by: Daeyeon Jeong [email protected]
1 parent dabda03 commit 49da1a5

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

lib/internal/webstreams/readablestream.js

+12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const {
2828
Uint8Array,
2929
} = primordials;
3030

31+
const { arrayBufferIsDetached } = internalBinding('util');
32+
3133
const {
3234
codes: {
3335
ERR_ILLEGAL_CONSTRUCTOR,
@@ -681,6 +683,16 @@ class ReadableStreamBYOBRequest {
681683
'This BYOB request has been invalidated');
682684
}
683685

686+
const viewedBuffer = ArrayBufferViewGetBuffer(view);
687+
const viewedBufferByteLength = ArrayBufferGetByteLength(viewedBuffer);
688+
const isDetached = arrayBufferIsDetached(viewedBuffer);
689+
690+
if (viewedBufferByteLength === 0 && isDetached) {
691+
throw new ERR_INVALID_STATE.TypeError(
692+
'Viewed ArrayBuffer is detached',
693+
);
694+
}
695+
684696
readableByteStreamControllerRespondWithNewView(controller, view);
685697
}
686698

src/node_util.cc

+7
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ void ArrayBufferViewHasBuffer(const FunctionCallbackInfo<Value>& args) {
207207
args.GetReturnValue().Set(args[0].As<ArrayBufferView>()->HasBuffer());
208208
}
209209

210+
void ArrayBufferIsDetached(const FunctionCallbackInfo<Value>& args) {
211+
CHECK(args[0]->IsArrayBuffer());
212+
v8::Local<v8::ArrayBuffer> ab = args[0].As<v8::ArrayBuffer>();
213+
args.GetReturnValue().Set(ab->GetBackingStore()->Data() == nullptr);
214+
}
215+
210216
class WeakReference : public BaseObject {
211217
public:
212218
WeakReference(Environment* env, Local<Object> object, Local<Object> target)
@@ -380,6 +386,7 @@ void Initialize(Local<Object> target,
380386
env->SetMethod(target, "sleep", Sleep);
381387

382388
env->SetMethod(target, "arrayBufferViewHasBuffer", ArrayBufferViewHasBuffer);
389+
env->SetMethod(target, "arrayBufferIsDetached", ArrayBufferIsDetached);
383390
Local<Object> constants = Object::New(env->isolate());
384391
NODE_DEFINE_CONSTANT(constants, ALL_PROPERTIES);
385392
NODE_DEFINE_CONSTANT(constants, ONLY_WRITABLE);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('node:assert');
5+
6+
{
7+
// ReadableStream with byte source: respondWithNewView() throws if the
8+
// supplied view's buffer has a different length (in the closed state)
9+
const stream = new ReadableStream({
10+
pull: common.mustCall(async (c) => {
11+
const view = new Uint8Array(new ArrayBuffer(10), 0, 0);
12+
13+
c.close();
14+
15+
assert.throws(() => {
16+
c.byobRequest.respondWithNewView(view);
17+
}, RangeError);
18+
}),
19+
type: 'bytes',
20+
});
21+
22+
const reader = stream.getReader({ mode: 'byob' });
23+
reader.read(new Uint8Array([4, 5, 6]));
24+
}
25+
26+
{
27+
// ReadableStream with byte source: respondWithNewView() throws if the
28+
// supplied view's buffer has been detached (in the closed state)
29+
const stream = new ReadableStream({
30+
pull: common.mustCall((c) => {
31+
c.close();
32+
33+
// Detach it by reading into it
34+
const view = new Uint8Array([1, 2, 3]);
35+
reader.read(view);
36+
37+
assert.throws(() => {
38+
c.byobRequest.respondWithNewView(view);
39+
}, TypeError);
40+
}),
41+
type: 'bytes',
42+
});
43+
44+
const reader = stream.getReader({ mode: 'byob' });
45+
reader.read(new Uint8Array([4, 5, 6]));
46+
}

test/parallel/test-whatwg-readablebytestream.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ class Source {
9898
this.controller.close();
9999
}
100100

101-
assert.throws(() => byobRequest.respondWithNewView({}), {
102-
code: 'ERR_INVALID_ARG_TYPE',
103-
});
101+
assert.throws(() => byobRequest.respondWithNewView({}), TypeError);
104102

105103
byobRequest.respond(bytesRead);
106104

0 commit comments

Comments
 (0)