| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b36e55a commit 2e612fe
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,54 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common.js'); | ||
| 4 | + | ||
| 5 | + const bench = common.createBenchmark(main, { | ||
| 6 | + input: [ | ||
| 7 | + 'arraybuffer', | ||
| 8 | + 'buffer', | ||
| 9 | + 'dataview', | ||
| 10 | + 'uint8array', | ||
| 11 | + 'uint8clampedarray', | ||
| 12 | + 'int8array', | ||
| 13 | + 'uint16array', | ||
| 14 | + 'int16array', | ||
| 15 | + 'uint32array', | ||
| 16 | + 'int32array', | ||
| 17 | + 'float16array', | ||
| 18 | + 'float32array', | ||
| 19 | + 'float64array', | ||
| 20 | + 'bigint64array', | ||
| 21 | + 'biguint64array', | ||
| 22 | + ], | ||
| 23 | + n: [1e6], | ||
| 24 | + }, { flags: ['--expose-internals'] }); | ||
| 25 | + | ||
| 26 | + function main({ n, input }) { | ||
| 27 | + const { converters } = require('internal/webidl'); | ||
| 28 | + | ||
| 29 | + let value; | ||
| 30 | + switch (input) { | ||
| 31 | + case 'arraybuffer': value = new ArrayBuffer(32); break; | ||
| 32 | + case 'buffer': value = Buffer.alloc(32); break; | ||
| 33 | + case 'dataview': value = new DataView(new ArrayBuffer(32)); break; | ||
| 34 | + case 'uint8array': value = new Uint8Array(32); break; | ||
| 35 | + case 'uint8clampedarray': value = new Uint8ClampedArray(32); break; | ||
| 36 | + case 'int8array': value = new Int8Array(32); break; | ||
| 37 | + case 'uint16array': value = new Uint16Array(16); break; | ||
| 38 | + case 'int16array': value = new Int16Array(16); break; | ||
| 39 | + case 'uint32array': value = new Uint32Array(8); break; | ||
| 40 | + case 'int32array': value = new Int32Array(8); break; | ||
| 41 | + case 'float16array': value = new Float16Array(16); break; | ||
| 42 | + case 'float32array': value = new Float32Array(8); break; | ||
| 43 | + case 'float64array': value = new Float64Array(4); break; | ||
| 44 | + case 'bigint64array': value = new BigInt64Array(4); break; | ||
| 45 | + case 'biguint64array': value = new BigUint64Array(4); break; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + const opts = { prefix: 'test', context: 'test' }; | ||
| 49 | + | ||
| 50 | + bench.start(); | ||
| 51 | + for (let i = 0; i < n; i++) | ||
| 52 | + converters.BufferSource(value, opts); | ||
| 53 | + bench.end(n); | ||
| 54 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | 4 | ArrayBufferIsView, | |
| 5 | + ArrayBufferPrototypeGetByteLength, | ||
| 5 | 6 | ArrayPrototypePush, | |
| 6 | 7 | ArrayPrototypeToSorted, | |
| 7 | 8 | DataViewPrototypeGetBuffer, | |
@@ -33,8 +34,7 @@ const { | |||
| 33 | 34 | const { kEmptyObject } = require('internal/util'); | |
| 34 | 35 | const { | |
| 35 | 36 | isArrayBuffer, | |
| 36 | - isDataView, | ||
| 37 | - isSharedArrayBuffer, | ||
| 37 | + isTypedArray, | ||
| 38 | 38 | } = require('internal/util/types'); | |
| 39 | 39 | ||
| 40 | 40 | const converters = { __proto__: null }; | |
@@ -390,9 +390,23 @@ function createInterfaceConverter(name, I) { | |||
| 390 | 390 | }; | |
| 391 | 391 | } | |
| 392 | 392 | ||
| 393 | - function getDataViewOrTypedArrayBuffer(V) { | ||
| 394 | - return isDataView(V) ? | ||
| 395 | - DataViewPrototypeGetBuffer(V) : TypedArrayPrototypeGetBuffer(V); | ||
| 393 | + // Returns the [[ViewedArrayBuffer]] of an ArrayBufferView without leaving JS. | ||
| 394 | + function getViewedArrayBuffer(V) { | ||
| 395 | + return isTypedArray(V) ? | ||
| 396 | + TypedArrayPrototypeGetBuffer(V) : DataViewPrototypeGetBuffer(V); | ||
| 397 | + } | ||
| 398 | + | ||
| 399 | + // Returns `true` if `buffer` is a `SharedArrayBuffer`. Uses a brand check via | ||
| 400 | + // the `ArrayBuffer.prototype.byteLength` getter, which succeeds only on real | ||
| 401 | + // (non-shared) ArrayBuffers and throws on SharedArrayBuffers — independent | ||
| 402 | + // of the receiver's prototype chain. | ||
| 403 | + function isSharedArrayBufferBacking(buffer) { | ||
| 404 | + try { | ||
| 405 | + ArrayBufferPrototypeGetByteLength(buffer); | ||
| 406 | + return false; | ||
| 407 | + } catch { | ||
| 408 | + return true; | ||
| 409 | + } | ||
| 396 | 410 | } | |
| 397 | 411 | ||
| 398 | 412 | // https://webidl.spec.whatwg.org/#ArrayBufferView | |
@@ -402,7 +416,7 @@ converters.ArrayBufferView = (V, opts = kEmptyObject) => { | |||
| 402 | 416 | 'is not an ArrayBufferView.', | |
| 403 | 417 | opts); | |
| 404 | 418 | } | |
| 405 | - if (isSharedArrayBuffer(getDataViewOrTypedArrayBuffer(V))) { | ||
| 419 | + if (isSharedArrayBufferBacking(getViewedArrayBuffer(V))) { | ||
| 406 | 420 | throw makeException( | |
| 407 | 421 | 'is a view on a SharedArrayBuffer, which is not allowed.', | |
| 408 | 422 | opts); | |
@@ -414,7 +428,7 @@ converters.ArrayBufferView = (V, opts = kEmptyObject) => { | |||
| 414 | 428 | // https://webidl.spec.whatwg.org/#BufferSource | |
| 415 | 429 | converters.BufferSource = (V, opts = kEmptyObject) => { | |
| 416 | 430 | if (ArrayBufferIsView(V)) { | |
| 417 | - if (isSharedArrayBuffer(getDataViewOrTypedArrayBuffer(V))) { | ||
| 431 | + if (isSharedArrayBufferBacking(getViewedArrayBuffer(V))) { | ||
| 418 | 432 | throw makeException( | |
| 419 | 433 | 'is a view on a SharedArrayBuffer, which is not allowed.', | |
| 420 | 434 | opts); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,208 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + 'use strict'; | ||
| 3 | + | ||
| 4 | + require('../common'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + const { test } = require('node:test'); | ||
| 7 | + | ||
| 8 | + const { converters } = require('internal/webidl'); | ||
| 9 | + | ||
| 10 | + const TYPED_ARRAY_CTORS = [ | ||
| 11 | + Uint8Array, Int8Array, Uint8ClampedArray, | ||
| 12 | + Uint16Array, Int16Array, | ||
| 13 | + Uint32Array, Int32Array, | ||
| 14 | + Float16Array, Float32Array, Float64Array, | ||
| 15 | + BigInt64Array, BigUint64Array, | ||
| 16 | + ]; | ||
| 17 | + | ||
| 18 | + test('BufferSource accepts ArrayBuffer', () => { | ||
| 19 | + const ab = new ArrayBuffer(8); | ||
| 20 | + assert.strictEqual(converters.BufferSource(ab), ab); | ||
| 21 | + }); | ||
| 22 | + | ||
| 23 | + test('BufferSource accepts all TypedArray kinds', () => { | ||
| 24 | + for (const Ctor of TYPED_ARRAY_CTORS) { | ||
| 25 | + const ta = new Ctor(4); | ||
| 26 | + assert.strictEqual(converters.BufferSource(ta), ta); | ||
| 27 | + } | ||
| 28 | + }); | ||
| 29 | + | ||
| 30 | + test('BufferSource accepts Buffer', () => { | ||
| 31 | + const buf = Buffer.alloc(8); | ||
| 32 | + assert.strictEqual(converters.BufferSource(buf), buf); | ||
| 33 | + }); | ||
| 34 | + | ||
| 35 | + test('BufferSource accepts DataView', () => { | ||
| 36 | + const dv = new DataView(new ArrayBuffer(8)); | ||
| 37 | + assert.strictEqual(converters.BufferSource(dv), dv); | ||
| 38 | + }); | ||
| 39 | + | ||
| 40 | + test('BufferSource accepts ArrayBuffer subclass instance', () => { | ||
| 41 | + class MyAB extends ArrayBuffer {} | ||
| 42 | + const sub = new MyAB(8); | ||
| 43 | + assert.strictEqual(converters.BufferSource(sub), sub); | ||
| 44 | + }); | ||
| 45 | + | ||
| 46 | + test('BufferSource accepts TypedArray with null prototype', () => { | ||
| 47 | + const ta = new Uint8Array(4); | ||
| 48 | + Object.setPrototypeOf(ta, null); | ||
| 49 | + assert.strictEqual(converters.BufferSource(ta), ta); | ||
| 50 | + }); | ||
| 51 | + | ||
| 52 | + test('BufferSource accepts DataView with null prototype', () => { | ||
| 53 | + const dv = new DataView(new ArrayBuffer(4)); | ||
| 54 | + Object.setPrototypeOf(dv, null); | ||
| 55 | + assert.strictEqual(converters.BufferSource(dv), dv); | ||
| 56 | + }); | ||
| 57 | + | ||
| 58 | + test('BufferSource accepts ArrayBuffer with null prototype', () => { | ||
| 59 | + const ab = new ArrayBuffer(4); | ||
| 60 | + Object.setPrototypeOf(ab, null); | ||
| 61 | + assert.strictEqual(converters.BufferSource(ab), ab); | ||
| 62 | + }); | ||
| 63 | + | ||
| 64 | + test('BufferSource rejects SharedArrayBuffer', () => { | ||
| 65 | + assert.throws( | ||
| 66 | + () => converters.BufferSource(new SharedArrayBuffer(4)), | ||
| 67 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 68 | + ); | ||
| 69 | + }); | ||
| 70 | + | ||
| 71 | + test('BufferSource rejects SAB-backed TypedArray', () => { | ||
| 72 | + const view = new Uint8Array(new SharedArrayBuffer(4)); | ||
| 73 | + assert.throws( | ||
| 74 | + () => converters.BufferSource(view), | ||
| 75 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 76 | + ); | ||
| 77 | + }); | ||
| 78 | + | ||
| 79 | + test('BufferSource rejects SAB-backed DataView', () => { | ||
| 80 | + const dv = new DataView(new SharedArrayBuffer(4)); | ||
| 81 | + assert.throws( | ||
| 82 | + () => converters.BufferSource(dv), | ||
| 83 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 84 | + ); | ||
| 85 | + }); | ||
| 86 | + | ||
| 87 | + test('BufferSource rejects SAB view whose buffer prototype was reassigned', () => { | ||
| 88 | + const sab = new SharedArrayBuffer(4); | ||
| 89 | + Object.setPrototypeOf(sab, ArrayBuffer.prototype); | ||
| 90 | + const view = new Uint8Array(sab); | ||
| 91 | + assert.throws( | ||
| 92 | + () => converters.BufferSource(view), | ||
| 93 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 94 | + ); | ||
| 95 | + }); | ||
| 96 | + | ||
| 97 | + test('BufferSource accepts a detached ArrayBuffer', () => { | ||
| 98 | + const ab = new ArrayBuffer(8); | ||
| 99 | + structuredClone(ab, { transfer: [ab] }); | ||
| 100 | + assert.strictEqual(ab.byteLength, 0); | ||
| 101 | + assert.strictEqual(converters.BufferSource(ab), ab); | ||
| 102 | + }); | ||
| 103 | + | ||
| 104 | + test('BufferSource rejects objects with a forged @@toStringTag', () => { | ||
| 105 | + const fake = { [Symbol.toStringTag]: 'Uint8Array' }; | ||
| 106 | + assert.throws( | ||
| 107 | + () => converters.BufferSource(fake), | ||
| 108 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 109 | + ); | ||
| 110 | + }); | ||
| 111 | + | ||
| 112 | + for (const value of [null, undefined, 0, 1, 1n, '', 'x', true, Symbol('s'), [], | ||
| 113 | + {}, () => {}]) { | ||
| 114 | + test(`BufferSource rejects ${typeof value} ${String(value)}`, () => { | ||
| 115 | + assert.throws( | ||
| 116 | + () => converters.BufferSource(value), | ||
| 117 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 118 | + ); | ||
| 119 | + }); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + test('ArrayBufferView accepts all TypedArray kinds', () => { | ||
| 123 | + for (const Ctor of TYPED_ARRAY_CTORS) { | ||
| 124 | + const ta = new Ctor(4); | ||
| 125 | + assert.strictEqual(converters.ArrayBufferView(ta), ta); | ||
| 126 | + } | ||
| 127 | + }); | ||
| 128 | + | ||
| 129 | + test('ArrayBufferView accepts DataView', () => { | ||
| 130 | + const dv = new DataView(new ArrayBuffer(8)); | ||
| 131 | + assert.strictEqual(converters.ArrayBufferView(dv), dv); | ||
| 132 | + }); | ||
| 133 | + | ||
| 134 | + test('ArrayBufferView accepts TypedArray subclass instance', () => { | ||
| 135 | + class MyU8 extends Uint8Array {} | ||
| 136 | + const sub = new MyU8(4); | ||
| 137 | + assert.strictEqual(converters.ArrayBufferView(sub), sub); | ||
| 138 | + }); | ||
| 139 | + | ||
| 140 | + test('ArrayBufferView accepts TypedArray with null prototype', () => { | ||
| 141 | + const ta = new Uint8Array(4); | ||
| 142 | + Object.setPrototypeOf(ta, null); | ||
| 143 | + assert.strictEqual(converters.ArrayBufferView(ta), ta); | ||
| 144 | + }); | ||
| 145 | + | ||
| 146 | + test('ArrayBufferView accepts DataView with null prototype', () => { | ||
| 147 | + const dv = new DataView(new ArrayBuffer(4)); | ||
| 148 | + Object.setPrototypeOf(dv, null); | ||
| 149 | + assert.strictEqual(converters.ArrayBufferView(dv), dv); | ||
| 150 | + }); | ||
| 151 | + | ||
| 152 | + test('ArrayBufferView rejects raw ArrayBuffer', () => { | ||
| 153 | + assert.throws( | ||
| 154 | + () => converters.ArrayBufferView(new ArrayBuffer(4)), | ||
| 155 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 156 | + ); | ||
| 157 | + }); | ||
| 158 | + | ||
| 159 | + test('ArrayBufferView rejects raw SharedArrayBuffer', () => { | ||
| 160 | + assert.throws( | ||
| 161 | + () => converters.ArrayBufferView(new SharedArrayBuffer(4)), | ||
| 162 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 163 | + ); | ||
| 164 | + }); | ||
| 165 | + | ||
| 166 | + test('ArrayBufferView rejects SAB-backed TypedArray', () => { | ||
| 167 | + const view = new Uint8Array(new SharedArrayBuffer(4)); | ||
| 168 | + assert.throws( | ||
| 169 | + () => converters.ArrayBufferView(view), | ||
| 170 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 171 | + ); | ||
| 172 | + }); | ||
| 173 | + | ||
| 174 | + test('ArrayBufferView rejects SAB-backed DataView', () => { | ||
| 175 | + const dv = new DataView(new SharedArrayBuffer(4)); | ||
| 176 | + assert.throws( | ||
| 177 | + () => converters.ArrayBufferView(dv), | ||
| 178 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 179 | + ); | ||
| 180 | + }); | ||
| 181 | + | ||
| 182 | + test('ArrayBufferView rejects SAB view whose buffer prototype was reassigned', () => { | ||
| 183 | + const sab = new SharedArrayBuffer(4); | ||
| 184 | + Object.setPrototypeOf(sab, ArrayBuffer.prototype); | ||
| 185 | + const view = new Uint8Array(sab); | ||
| 186 | + assert.throws( | ||
| 187 | + () => converters.ArrayBufferView(view), | ||
| 188 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 189 | + ); | ||
| 190 | + }); | ||
| 191 | + | ||
| 192 | + test('ArrayBufferView rejects objects with a forged @@toStringTag', () => { | ||
| 193 | + const fake = { [Symbol.toStringTag]: 'Uint8Array' }; | ||
| 194 | + assert.throws( | ||
| 195 | + () => converters.ArrayBufferView(fake), | ||
| 196 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 197 | + ); | ||
| 198 | + }); | ||
| 199 | + | ||
| 200 | + for (const value of [null, undefined, 0, 1, 1n, '', 'x', true, Symbol('s'), [], | ||
| 201 | + {}, () => {}]) { | ||
| 202 | + test(`ArrayBufferView rejects ${typeof value} ${String(value)}`, () => { | ||
| 203 | + assert.throws( | ||
| 204 | + () => converters.ArrayBufferView(value), | ||
| 205 | + { code: 'ERR_INVALID_ARG_TYPE' }, | ||
| 206 | + ); | ||
| 207 | + }); | ||
| 208 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments