Skip to content

Commit 3a0fec2

Browse files
Add allowResizable option
1 parent 3f59834 commit 3a0fec2

File tree

2 files changed

+191
-8
lines changed

2 files changed

+191
-8
lines changed

lib/index.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,25 @@ function isSharedArrayBuffer(value) {
322322
}
323323
}
324324

325+
const abResizableGetter = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "resizable").get;
326+
const sabGrowableGetter = Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, "growable").get;
327+
328+
function isNonSharedArrayBufferResizable(value) {
329+
try {
330+
return abResizableGetter.call(value);
331+
} catch {
332+
return false;
333+
}
334+
}
335+
336+
function isSharedArrayBufferGrowable(value) {
337+
try {
338+
return sabGrowableGetter.call(value);
339+
} catch {
340+
return false;
341+
}
342+
}
343+
325344
function isArrayBufferDetached(value) {
326345
try {
327346
// eslint-disable-next-line no-new
@@ -336,6 +355,9 @@ exports.ArrayBuffer = (value, options = {}) => {
336355
if (!isNonSharedArrayBuffer(value)) {
337356
throw makeException(TypeError, "is not an ArrayBuffer", options);
338357
}
358+
if (!options.allowResizable && isNonSharedArrayBufferResizable(value)) {
359+
throw makeException(TypeError, "is a resizable ArrayBuffer", options);
360+
}
339361
if (isArrayBufferDetached(value)) {
340362
throw makeException(TypeError, "is a detached ArrayBuffer", options);
341363
}
@@ -347,6 +369,9 @@ exports.SharedArrayBuffer = (value, options = {}) => {
347369
if (!isSharedArrayBuffer(value)) {
348370
throw makeException(TypeError, "is not a SharedArrayBuffer", options);
349371
}
372+
if (!options.allowResizable && isSharedArrayBufferGrowable(value)) {
373+
throw makeException(TypeError, "is a growable SharedArrayBuffer", options);
374+
}
350375
if (isArrayBufferDetached(value)) {
351376
throw makeException(TypeError, "is a detached SharedArrayBuffer", options);
352377
}
@@ -405,6 +430,14 @@ exports.ArrayBufferView = (value, options = {}) => {
405430
throw makeException(TypeError, "is a view on a SharedArrayBuffer, which is not allowed", options);
406431
}
407432

433+
if (!options.allowResizable) {
434+
if (isNonSharedArrayBufferResizable(value.buffer)) {
435+
throw makeException(TypeError, "is a view on a resizable ArrayBuffer, which is not allowed", options);
436+
} else if (isSharedArrayBufferGrowable(value.buffer)) {
437+
throw makeException(TypeError, "is a view on a growable SharedArrayBuffer, which is not allowed", options);
438+
}
439+
}
440+
408441
if (isArrayBufferDetached(value.buffer)) {
409442
throw makeException(TypeError, "is a view on a detached ArrayBuffer", options);
410443
}

test/buffer-source.js

Lines changed: 158 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,23 @@ const bufferSourceCreators = [
8686
{
8787
typeName: "ArrayBuffer",
8888
isShared: false,
89+
isResizable: false,
8990
isDetached: false,
9091
label: "ArrayBuffer same realm",
9192
creator: () => new ArrayBuffer(0)
9293
},
9394
{
9495
typeName: "ArrayBuffer",
9596
isShared: false,
97+
isResizable: true,
98+
isDetached: false,
99+
label: "resizable ArrayBuffer same realm",
100+
creator: () => new ArrayBuffer(0, { maxByteLength: 1 })
101+
},
102+
{
103+
typeName: "ArrayBuffer",
104+
isShared: false,
105+
isResizable: false,
96106
isDetached: true,
97107
label: "detached ArrayBuffer",
98108
creator: () => {
@@ -105,16 +115,34 @@ const bufferSourceCreators = [
105115
{
106116
typeName: "SharedArrayBuffer",
107117
isShared: true,
118+
isResizable: false,
108119
isDetached: false,
109120
label: "SharedArrayBuffer same realm",
110121
creator: () => new SharedArrayBuffer(0)
111122
},
112123
{
113124
typeName: "SharedArrayBuffer",
114125
isShared: true,
126+
isResizable: true,
127+
isDetached: false,
128+
label: "growable SharedArrayBuffer same realm",
129+
creator: () => new SharedArrayBuffer(0, { maxByteLength: 1 })
130+
},
131+
{
132+
typeName: "SharedArrayBuffer",
133+
isShared: true,
134+
isResizable: false,
115135
isDetached: false,
116136
label: "SharedArrayBuffer different realm",
117137
creator: () => vm.runInContext(`new SharedArrayBuffer(0)`, differentRealm)
138+
},
139+
{
140+
typeName: "SharedArrayBuffer",
141+
isShared: true,
142+
isResizable: true,
143+
isDetached: false,
144+
label: "growable SharedArrayBuffer different realm",
145+
creator: () => vm.runInContext(`new SharedArrayBuffer(0, { maxByteLength: 1 })`, differentRealm)
118146
}
119147
];
120148

@@ -128,6 +156,7 @@ for (const constructor of bufferSourceConstructors) {
128156
{
129157
typeName: name,
130158
isShared: false,
159+
isResizable: false,
131160
isDetached: false,
132161
isForged: false,
133162
label: `${name} same realm`,
@@ -136,6 +165,7 @@ for (const constructor of bufferSourceConstructors) {
136165
{
137166
typeName: name,
138167
isShared: false,
168+
isResizable: false,
139169
isDetached: false,
140170
isForged: false,
141171
label: `${name} different realm`,
@@ -144,6 +174,28 @@ for (const constructor of bufferSourceConstructors) {
144174
{
145175
typeName: name,
146176
isShared: false,
177+
isResizable: true,
178+
isDetached: false,
179+
isForged: false,
180+
label: `resizable ${name} same realm`,
181+
creator: () => new constructor(new ArrayBuffer(0, { maxByteLength: 1 }))
182+
},
183+
{
184+
typeName: name,
185+
isShared: false,
186+
isResizable: true,
187+
isDetached: false,
188+
isForged: false,
189+
label: `resizable ${name} different realm`,
190+
creator: () => vm.runInContext(
191+
`new ${constructor.name}(new ArrayBuffer(0, { maxByteLength: 1 }))`,
192+
differentRealm
193+
)
194+
},
195+
{
196+
typeName: name,
197+
isShared: false,
198+
isResizable: false,
147199
isDetached: false,
148200
isForged: true,
149201
label: `forged ${name}`,
@@ -152,6 +204,7 @@ for (const constructor of bufferSourceConstructors) {
152204
{
153205
typeName: name,
154206
isShared: false,
207+
isResizable: false,
155208
isDetached: true,
156209
isForged: false,
157210
label: `detached ${name}`,
@@ -165,6 +218,7 @@ for (const constructor of bufferSourceConstructors) {
165218
{
166219
typeName: name,
167220
isShared: true,
221+
isResizable: false,
168222
isDetached: false,
169223
isForged: false,
170224
label: `${name} SharedArrayBuffer same realm`,
@@ -173,10 +227,32 @@ for (const constructor of bufferSourceConstructors) {
173227
{
174228
typeName: name,
175229
isShared: true,
230+
isResizable: false,
176231
isDetached: false,
177232
isForged: false,
178233
label: `${name} SharedArrayBuffer different realm`,
179234
creator: () => vm.runInContext(`new ${constructor.name}(new SharedArrayBuffer(0))`, differentRealm)
235+
},
236+
{
237+
typeName: name,
238+
isShared: true,
239+
isResizable: true,
240+
isDetached: false,
241+
isForged: false,
242+
label: `${name} growable SharedArrayBuffer same realm`,
243+
creator: () => new constructor(new SharedArrayBuffer(0, { maxByteLength: 1 }))
244+
},
245+
{
246+
typeName: name,
247+
isShared: true,
248+
isResizable: true,
249+
isDetached: false,
250+
isForged: false,
251+
label: `${name} growable SharedArrayBuffer different realm`,
252+
creator: () => vm.runInContext(
253+
`new ${constructor.name}(new SharedArrayBuffer(0, { maxByteLength: 1 }))`,
254+
differentRealm
255+
)
180256
}
181257
);
182258
}
@@ -190,6 +266,7 @@ for (const type of bufferSourceConstructors) {
190266
const testFunction =
191267
innerType.typeName === typeName &&
192268
!innerType.isShared &&
269+
!innerType.isResizable &&
193270
!innerType.isDetached &&
194271
!innerType.isForged ?
195272
testOk :
@@ -203,13 +280,38 @@ for (const type of bufferSourceConstructors) {
203280
describe("with [AllowShared]", () => {
204281
const allowSharedSUT = (v, opts) => conversions[typeName](v, { ...opts, allowShared: true });
205282

206-
for (const { label, creator, typeName: innerTypeName, isDetached, isForged } of bufferSourceCreators) {
207-
const testFunction = innerTypeName === typeName && !isDetached && !isForged ? testOk : testNotOk;
283+
for (const {
284+
label, creator, typeName: innerTypeName, isResizable, isDetached, isForged
285+
} of bufferSourceCreators) {
286+
const testFunction = innerTypeName === typeName &&
287+
!isResizable &&
288+
!isDetached &&
289+
!isForged ?
290+
testOk :
291+
testNotOk;
208292
testFunction(label, allowSharedSUT, creator);
209293
}
210294

211295
commonNotOk(allowSharedSUT);
212296
});
297+
298+
describe("with [AllowResizable]", () => {
299+
const allowResizableSUT = (v, opts) => conversions[typeName](v, { ...opts, allowResizable: true });
300+
301+
for (const {
302+
label, creator, typeName: innerTypeName, isShared, isDetached, isForged
303+
} of bufferSourceCreators) {
304+
const testFunction = innerTypeName === typeName &&
305+
!isShared &&
306+
!isDetached &&
307+
!isForged ?
308+
testOk :
309+
testNotOk;
310+
testFunction(label, allowResizableSUT, creator);
311+
}
312+
313+
commonNotOk(allowResizableSUT);
314+
});
213315
});
214316
}
215317

@@ -220,6 +322,7 @@ describe(`WebIDL SharedArrayBuffer type`, () => {
220322
const testFunction =
221323
innerType.typeName === "SharedArrayBuffer" &&
222324
innerType.isShared &&
325+
!innerType.isResizable &&
223326
!innerType.isDetached &&
224327
!innerType.isForged ?
225328
testOk :
@@ -229,16 +332,32 @@ describe(`WebIDL SharedArrayBuffer type`, () => {
229332
}
230333

231334
commonNotOk(sut);
335+
336+
describe("with [AllowResizable]", () => {
337+
const allowResizableSUT = (v, opts) => sut(v, { ...opts, allowResizable: true });
338+
339+
for (const { label, creator, typeName: innerTypeName, isDetached, isForged } of bufferSourceCreators) {
340+
const testFunction = innerTypeName === "SharedArrayBuffer" &&
341+
!isDetached &&
342+
!isForged ?
343+
testOk :
344+
testNotOk;
345+
testFunction(label, allowResizableSUT, creator);
346+
}
347+
348+
commonNotOk(allowResizableSUT);
349+
});
232350
});
233351

234352
describe("WebIDL ArrayBufferView type", () => {
235353
const sut = conversions.ArrayBufferView;
236354

237-
for (const { label, typeName, isShared, isDetached, isForged, creator } of bufferSourceCreators) {
355+
for (const { label, typeName, isShared, isResizable, isDetached, isForged, creator } of bufferSourceCreators) {
238356
const testFunction =
239357
typeName !== "ArrayBuffer" &&
240358
typeName !== "SharedArrayBuffer" &&
241359
!isShared &&
360+
!isResizable &&
242361
!isDetached &&
243362
!isForged ?
244363
testOk :
@@ -252,10 +371,11 @@ describe("WebIDL ArrayBufferView type", () => {
252371
describe("with [AllowShared]", () => {
253372
const allowSharedSUT = (v, opts) => conversions.ArrayBufferView(v, { ...opts, allowShared: true });
254373

255-
for (const { label, creator, typeName, isDetached, isForged } of bufferSourceCreators) {
374+
for (const { label, creator, typeName, isResizable, isDetached, isForged } of bufferSourceCreators) {
256375
const testFunction =
257376
typeName !== "ArrayBuffer" &&
258377
typeName !== "SharedArrayBuffer" &&
378+
!isResizable &&
259379
!isDetached &&
260380
!isForged ?
261381
testOk :
@@ -266,13 +386,32 @@ describe("WebIDL ArrayBufferView type", () => {
266386

267387
commonNotOk(allowSharedSUT);
268388
});
389+
390+
describe("with [AllowResizable]", () => {
391+
const allowResizableSUT = (v, opts) => conversions.ArrayBufferView(v, { ...opts, allowResizable: true });
392+
393+
for (const { label, creator, typeName, isShared, isDetached, isForged } of bufferSourceCreators) {
394+
const testFunction =
395+
typeName !== "ArrayBuffer" &&
396+
typeName !== "SharedArrayBuffer" &&
397+
!isShared &&
398+
!isDetached &&
399+
!isForged ?
400+
testOk :
401+
testNotOk;
402+
403+
testFunction(label, allowResizableSUT, creator);
404+
}
405+
406+
commonNotOk(allowResizableSUT);
407+
});
269408
});
270409

271410
describe("WebIDL BufferSource type", () => {
272411
const sut = conversions.BufferSource;
273412

274-
for (const { label, creator, isShared, isDetached, isForged } of bufferSourceCreators) {
275-
const testFunction = !isShared && !isDetached && !isForged ? testOk : testNotOk;
413+
for (const { label, creator, isShared, isResizable, isDetached, isForged } of bufferSourceCreators) {
414+
const testFunction = !isShared && !isResizable && !isDetached && !isForged ? testOk : testNotOk;
276415
testFunction(label, sut, creator);
277416
}
278417

@@ -281,11 +420,22 @@ describe("WebIDL BufferSource type", () => {
281420
describe("with [AllowShared]", () => {
282421
const allowSharedSUT = (v, opts) => conversions.BufferSource(v, { ...opts, allowShared: true });
283422

284-
for (const { label, creator, isDetached, isForged } of bufferSourceCreators) {
285-
const testFunction = !isDetached && !isForged ? testOk : testNotOk;
423+
for (const { label, creator, isResizable, isDetached, isForged } of bufferSourceCreators) {
424+
const testFunction = !isResizable && !isDetached && !isForged ? testOk : testNotOk;
286425
testFunction(label, allowSharedSUT, creator);
287426
}
288427

289428
commonNotOk(allowSharedSUT);
290429
});
430+
431+
describe("with [AllowResizable]", () => {
432+
const allowResizableSUT = (v, opts) => conversions.BufferSource(v, { ...opts, allowResizable: true });
433+
434+
for (const { label, creator, isShared, isDetached, isForged } of bufferSourceCreators) {
435+
const testFunction = !isShared && !isDetached && !isForged ? testOk : testNotOk;
436+
testFunction(label, allowResizableSUT, creator);
437+
}
438+
439+
commonNotOk(allowResizableSUT);
440+
});
291441
});

0 commit comments

Comments
 (0)