lib: reject SharedArrayBuffer in web APIs per spec · nodejs/node@3d18162
1+'use strict';
2+// Flags: --expose-internals
3+const common = require('../common');
4+const assert = require('assert');
5+const test = require('node:test');
6+const { ReadableStream } = require('stream/web');
7+8+const sab = new SharedArrayBuffer(8);
9+const sabView = new Uint8Array(sab);
10+const sabDataView = new DataView(sab);
11+12+// -- ReadableStreamBYOBReader.read() --
13+14+test('ReadableStreamBYOBReader.read() rejects SAB-backed Uint8Array', async () => {
15+const rs = new ReadableStream({
16+type: 'bytes',
17+pull(controller) {
18+controller.enqueue(new Uint8Array([1, 2, 3]));
19+},
20+});
21+const reader = rs.getReader({ mode: 'byob' });
22+await assert.rejects(
23+reader.read(new Uint8Array(sab)),
24+{ code: 'ERR_INVALID_ARG_VALUE' },
25+);
26+reader.releaseLock();
27+});
28+29+test('ReadableStreamBYOBReader.read() rejects SAB-backed DataView', async () => {
30+const rs = new ReadableStream({
31+type: 'bytes',
32+pull(controller) {
33+controller.enqueue(new Uint8Array([1, 2, 3]));
34+},
35+});
36+const reader = rs.getReader({ mode: 'byob' });
37+await assert.rejects(
38+reader.read(sabDataView),
39+{ code: 'ERR_INVALID_ARG_VALUE' },
40+);
41+reader.releaseLock();
42+});
43+44+test('ReadableStreamBYOBReader.read() accepts regular view', async () => {
45+const rs = new ReadableStream({
46+type: 'bytes',
47+pull(controller) {
48+controller.enqueue(new Uint8Array([1, 2, 3]));
49+},
50+});
51+const reader = rs.getReader({ mode: 'byob' });
52+const { value, done } = await reader.read(new Uint8Array(3));
53+assert.strictEqual(done, false);
54+assert.deepStrictEqual(value, new Uint8Array([1, 2, 3]));
55+reader.releaseLock();
56+});
57+58+// -- ReadableByteStreamController.enqueue() --
59+60+test('ReadableByteStreamController.enqueue() rejects SAB-backed Uint8Array', async () => {
61+const sabForEnqueue = new SharedArrayBuffer(4);
62+const sabViewForEnqueue = new Uint8Array(sabForEnqueue);
63+sabViewForEnqueue[0] = 42;
64+65+const rs = new ReadableStream({
66+type: 'bytes',
67+pull: common.mustCall((controller) => {
68+assert.throws(
69+() => controller.enqueue(sabViewForEnqueue),
70+{ code: 'ERR_INVALID_ARG_VALUE' },
71+);
72+controller.enqueue(new Uint8Array([1]));
73+}),
74+});
75+const reader = rs.getReader();
76+const { value } = await reader.read();
77+assert.deepStrictEqual(value, new Uint8Array([1]));
78+reader.releaseLock();
79+});
80+81+test('ReadableByteStreamController.enqueue() rejects SAB-backed DataView', async () => {
82+const sabForDv = new SharedArrayBuffer(4);
83+const dvForEnqueue = new DataView(sabForDv);
84+85+const rs = new ReadableStream({
86+type: 'bytes',
87+pull: common.mustCall((controller) => {
88+assert.throws(
89+() => controller.enqueue(dvForEnqueue),
90+{ code: 'ERR_INVALID_ARG_VALUE' },
91+);
92+controller.enqueue(new Uint8Array([2]));
93+}),
94+});
95+const reader = rs.getReader();
96+const { value } = await reader.read();
97+assert.deepStrictEqual(value, new Uint8Array([2]));
98+reader.releaseLock();
99+});
100+101+// -- SharedWebIDL converters --
102+103+const { converters } = require('internal/webidl');
104+105+test('webidl converters.BufferSource rejects SharedArrayBuffer', () => {
106+assert.throws(
107+() => converters.BufferSource(sab),
108+{ code: 'ERR_INVALID_ARG_TYPE' },
109+);
110+});
111+112+test('webidl converters.BufferSource rejects SAB-backed Uint8Array', () => {
113+assert.throws(
114+() => converters.BufferSource(sabView),
115+{ code: 'ERR_INVALID_ARG_TYPE' },
116+);
117+});
118+119+test('webidl converters.BufferSource rejects SAB-backed DataView', () => {
120+assert.throws(
121+() => converters.BufferSource(sabDataView),
122+{ code: 'ERR_INVALID_ARG_TYPE' },
123+);
124+});
125+126+test('webidl converters.BufferSource accepts ArrayBuffer', () => {
127+const ab = new ArrayBuffer(4);
128+assert.strictEqual(converters.BufferSource(ab), ab);
129+});
130+131+test('webidl converters.BufferSource accepts regular TypedArray', () => {
132+const ta = new Uint8Array(4);
133+assert.strictEqual(converters.BufferSource(ta), ta);
134+});
135+136+test('webidl converters.ArrayBufferView rejects SAB-backed Uint8Array', () => {
137+assert.throws(
138+() => converters.ArrayBufferView(sabView),
139+{ code: 'ERR_INVALID_ARG_TYPE' },
140+);
141+});
142+143+test('webidl converters.ArrayBufferView rejects SAB-backed DataView', () => {
144+assert.throws(
145+() => converters.ArrayBufferView(sabDataView),
146+{ code: 'ERR_INVALID_ARG_TYPE' },
147+);
148+});
149+150+test('webidl converters.ArrayBufferView rejects non-view', () => {
151+assert.throws(
152+() => converters.ArrayBufferView('not a view'),
153+{ code: 'ERR_INVALID_ARG_TYPE' },
154+);
155+});
156+157+test('webidl converters.ArrayBufferView accepts regular Uint8Array', () => {
158+const ta = new Uint8Array(4);
159+assert.strictEqual(converters.ArrayBufferView(ta), ta);
160+});
161+162+test('webidl converters.ArrayBufferView accepts regular DataView', () => {
163+const dv = new DataView(new ArrayBuffer(4));
164+assert.strictEqual(converters.ArrayBufferView(dv), dv);
165+});