resizablearraybuffer-growablesharedarraybuffer.js 18.4 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --harmony-rab-gsab --allow-natives-syntax

"use strict";

9 10
d8.file.execute('test/mjsunit/typedarray-helpers.js');

11 12 13 14 15 16 17 18 19 20 21 22 23
function resizeHelper(ab, value) {
  const return_value = ab.resize(value);
  assertEquals(undefined, return_value);
  assertEquals(value, ab.byteLength);
}

function growHelper(ab, value) {
  const return_value = ab.grow(value);
  assertEquals(undefined, return_value);
  assertEquals(value, ab.byteLength);
}

(function TestRABBasics() {
24 25
  const rab = CreateResizableArrayBuffer(10, 20);
  assertTrue(rab instanceof ArrayBuffer);
26 27 28 29 30 31
  assertFalse(rab instanceof SharedArrayBuffer);
  assertEquals(10, rab.byteLength);
  assertEquals(20, rab.maxByteLength);
})();

(function TestRABCtorByteLengthEqualsMax() {
32
  const rab = CreateResizableArrayBuffer(10, 10);
33 34 35 36 37
  assertEquals(10, rab.byteLength);
  assertEquals(10, rab.maxByteLength);
})();

(function TestRABCtorByteLengthZero() {
38
  const rab = CreateResizableArrayBuffer(0, 10);
39 40 41 42 43
  assertEquals(0, rab.byteLength);
  assertEquals(10, rab.maxByteLength);
})();

(function TestRABCtorByteLengthAndMaxZero() {
44
  const rab = CreateResizableArrayBuffer(0, 0);
45 46 47 48
  assertEquals(0, rab.byteLength);
  assertEquals(0, rab.maxByteLength);
})();

49 50
const arrayBufferCtors = [[ArrayBuffer, (b) => b.resizable],
                          [SharedArrayBuffer, (b) => b.growable]];
51 52

(function TestOptionsBagNotObject() {
53
  for (let [ctor, resizable] of arrayBufferCtors) {
54 55 56 57 58 59 60 61 62
    const buffer = new ctor(10, 'this is not an options bag');
    assertFalse(resizable(buffer));
  }
})();

(function TestOptionsBagMaxByteLengthGetterThrows() {
  let evil = {};
  Object.defineProperty(evil, 'maxByteLength',
                        {get: () => { throw new Error('thrown'); }});
63
  for (let [ctor, resizable] of arrayBufferCtors) {
64 65 66 67 68 69 70 71 72 73 74 75
    let caught = false;
    try {
      new ctor(10, evil);
    } catch(e) {
      assertEquals('thrown', e.message);
      caught = true;
    }
    assertTrue(caught);
  }
})();

(function TestMaxByteLengthNonExisting() {
76
  for (let [ctor, resizable] of arrayBufferCtors) {
77 78 79 80 81 82
    const buffer = new ctor(10, {});
    assertFalse(resizable(buffer));
  }
})();

(function TestMaxByteLengthUndefinedOrNan() {
83
  for (let [ctor, resizable] of arrayBufferCtors) {
84 85 86 87 88 89 90 91 92 93
    const buffer1 = new ctor(10, {maxByteLength: undefined});
    assertFalse(resizable(buffer1));
    const buffer2 = new ctor(0, {maxByteLength: NaN});
    assertTrue(resizable(buffer2));
    assertEquals(0, buffer2.byteLength);
    assertEquals(0, buffer2.maxByteLength);
  }
})();

(function TestMaxByteLengthBooleanNullOrString() {
94
  for (let [ctor, resizable] of arrayBufferCtors) {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    const buffer1 = new ctor(0, {maxByteLength: true});
    assertTrue(resizable(buffer1));
    assertEquals(0, buffer1.byteLength);
    assertEquals(1, buffer1.maxByteLength);
    const buffer2 = new ctor(0, {maxByteLength: false});
    assertTrue(resizable(buffer2));
    assertEquals(0, buffer2.byteLength);
    assertEquals(0, buffer2.maxByteLength);
    const buffer3 = new ctor(0, {maxByteLength: null});
    assertTrue(resizable(buffer3));
    assertEquals(0, buffer3.byteLength);
    assertEquals(0, buffer3.maxByteLength);
    const buffer4 = new ctor(0, {maxByteLength: '100'});
    assertTrue(resizable(buffer4));
    assertEquals(0, buffer4.byteLength);
    assertEquals(100, buffer4.maxByteLength);
  }
})();

(function TestMaxByteLengthDouble() {
115
  for (let [ctor, resizable] of arrayBufferCtors) {
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    const buffer1 = new ctor(0, {maxByteLength: -0.0});
    assertTrue(resizable(buffer1));
    assertEquals(0, buffer1.byteLength);
    assertEquals(0, buffer1.maxByteLength);
    const buffer2 = new ctor(0, {maxByteLength: -0.1});
    assertTrue(resizable(buffer2));
    assertEquals(0, buffer2.byteLength);
    assertEquals(0, buffer2.maxByteLength);
    const buffer3 = new ctor(0, {maxByteLength: 1.2});
    assertTrue(resizable(buffer3));
    assertEquals(0, buffer3.byteLength);
    assertEquals(1, buffer3.maxByteLength);
    assertThrows(() => { new ctor(0, {maxByteLength: -1.5}) });
    assertThrows(() => { new ctor(0, {maxByteLength: -1}) });
  }
})();

(function TestMaxByteLengthThrows() {
  const evil = {valueOf: () => { throw new Error('thrown');}};
135
  for (let [ctor, resizable] of arrayBufferCtors) {
136 137 138 139 140 141 142 143 144 145 146 147 148 149
    let caught = false;
    try {
      new ctor(0, {maxByteLength: evil});
    } catch (e) {
      assertEquals('thrown', e.message);
      caught = true;
    }
    assertTrue(caught);
  }
})();

(function TestByteLengthThrows() {
  const evil1 = {valueOf: () => { throw new Error('byteLength throws');}};
  const evil2 = {valueOf: () => { throw new Error('maxByteLength throws');}};
150
  for (let [ctor, resizable] of arrayBufferCtors) {
151 152 153 154 155 156 157 158 159
    let caught = false;
    try {
      new ctor(evil1, {maxByteLength: evil2});
    } catch (e) {
      assertEquals('byteLength throws', e.message);
      caught = true;
    }
    assertTrue(caught);
  }
160 161 162
})();

(function TestAllocatingOutrageouslyMuchThrows() {
163
  assertThrows(() => { CreateResizableArrayBuffer(0, 2 ** 100);}, RangeError);
164 165 166 167 168 169 170 171
})();

(function TestRABCtorOperationOrder() {
  let log = '';
  const mock_length = {valueOf: function() {
      log += 'valueof length, '; return 10; }};
  const mock_max_length = {valueOf: function() {
      log += 'valueof max_length, '; return 10; }};
172
  CreateResizableArrayBuffer(mock_length, mock_max_length);
173 174 175 176 177 178 179 180 181 182

  assertEquals('valueof length, valueof max_length, ', log);
})();

(function TestGSABCtorOperationOrder() {
  let log = '';
  const mock_length = {valueOf: function() {
      log += 'valueof length, '; return 10; }};
  const mock_max_length = {valueOf: function() {
      log += 'valueof max_length, '; return 10; }};
183
  CreateResizableArrayBuffer(mock_length, mock_max_length);
184 185 186 187 188 189 190 191 192 193 194 195 196

  assertEquals('valueof length, valueof max_length, ', log);
})();

(function TestByteLengthGetterReceiverChecks() {
  const name = 'byteLength';
  const ab_getter = Object.getOwnPropertyDescriptor(
      ArrayBuffer.prototype, name).get;
  const sab_getter = Object.getOwnPropertyDescriptor(
      SharedArrayBuffer.prototype, name).get;

  const ab = new ArrayBuffer(40);
  const sab = new SharedArrayBuffer(40);
197 198
  const rab = CreateResizableArrayBuffer(40, 40);
  const gsab = CreateGrowableSharedArrayBuffer(40, 40);
199 200

  assertEquals(40, ab_getter.call(ab));
201
  assertEquals(40, ab_getter.call(rab));
202
  assertEquals(40, sab_getter.call(sab));
203
  assertEquals(40, sab_getter.call(gsab));
204 205 206 207 208 209

  assertThrows(() => { ab_getter.call(sab);});
  assertThrows(() => { ab_getter.call(gsab);});

  assertThrows(() => { sab_getter.call(ab);});
  assertThrows(() => { sab_getter.call(rab);});
210 211
})();

212 213
(function TestMaxByteLengthGetterReceiverChecks() {
  const name = 'maxByteLength';
214 215 216 217
  const ab_getter = Object.getOwnPropertyDescriptor(
      ArrayBuffer.prototype, name).get;
  const sab_getter = Object.getOwnPropertyDescriptor(
      SharedArrayBuffer.prototype, name).get;
218 219 220

  const ab = new ArrayBuffer(40);
  const sab = new SharedArrayBuffer(40);
221 222
  const rab = CreateResizableArrayBuffer(20, 40);
  const gsab = CreateGrowableSharedArrayBuffer(20, 40);
223

224 225 226 227
  assertEquals(40, ab_getter.call(ab));
  assertEquals(40, ab_getter.call(rab));
  assertEquals(40, sab_getter.call(sab));
  assertEquals(40, sab_getter.call(gsab));
228

229 230
  assertThrows(() => { ab_getter.call(sab);});
  assertThrows(() => { ab_getter.call(gsab);});
231

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
  assertThrows(() => { sab_getter.call(ab);});
  assertThrows(() => { sab_getter.call(rab);});
})();

(function TestResizableGetterReceiverChecks() {
  const ab_getter = Object.getOwnPropertyDescriptor(
      ArrayBuffer.prototype, 'resizable').get;
  const sab_getter = Object.getOwnPropertyDescriptor(
      SharedArrayBuffer.prototype, 'growable').get;

  const ab = new ArrayBuffer(40);
  const sab = new SharedArrayBuffer(40);
  const rab = CreateResizableArrayBuffer(40, 40);
  const gsab = CreateGrowableSharedArrayBuffer(40, 40);

  assertEquals(false, ab_getter.call(ab));
  assertEquals(true, ab_getter.call(rab));
  assertEquals(false, sab_getter.call(sab));
  assertEquals(true, sab_getter.call(gsab));

  assertThrows(() => { ab_getter.call(sab);});
  assertThrows(() => { ab_getter.call(gsab);});

  assertThrows(() => { sab_getter.call(ab);});
  assertThrows(() => { sab_getter.call(rab);});
})();

(function TestByteLengthAndMaxByteLengthOfDetached() {
  const rab = CreateResizableArrayBuffer(10, 20);
  %ArrayBufferDetach(rab);
  assertEquals(0, rab.byteLength);
  assertEquals(0, rab.maxByteLength);
264 265 266
})();

(function TestResizeAndGrowReceiverChecks() {
267 268
  const rab_resize = ArrayBuffer.prototype.resize;
  const gsab_grow = SharedArrayBuffer.prototype.grow;
269 270 271

  const ab = new ArrayBuffer(40);
  const sab = new SharedArrayBuffer(40);
272 273
  const rab = CreateResizableArrayBuffer(10, 40);
  const gsab = CreateGrowableSharedArrayBuffer(10, 40);
274 275 276 277 278 279 280 281 282 283 284 285 286

  rab_resize.call(rab, 20);
  gsab_grow.call(gsab, 20);
  assertThrows(() => { rab_resize.call(ab, 30);});
  assertThrows(() => { rab_resize.call(sab, 30);});
  assertThrows(() => { rab_resize.call(gsab, 30);});

  assertThrows(() => { gsab_grow.call(ab, 30);});
  assertThrows(() => { gsab_grow.call(sab, 30);});
  assertThrows(() => { gsab_grow.call(rab, 30);});
})();

(function TestRABResizeToMax() {
287
  const rab = CreateResizableArrayBuffer(10, 20);
288 289 290 291
  resizeHelper(rab, 20);
})();

(function TestRABResizeToSameSize() {
292
  const rab = CreateResizableArrayBuffer(10, 20);
293 294 295 296
  resizeHelper(rab, 10);
})();

(function TestRABResizeToSmaller() {
297
  const rab = CreateResizableArrayBuffer(10, 20);
298 299 300 301
  resizeHelper(rab, 5);
})();

(function TestRABResizeToZero() {
302
  const rab = CreateResizableArrayBuffer(10, 20);
303 304 305 306
  resizeHelper(rab, 0);
})();

(function TestRABResizeZeroToZero() {
307
  const rab = CreateResizableArrayBuffer(0, 20);
308 309 310 311
  resizeHelper(rab, 0);
})();

(function TestRABGrowBeyondMaxThrows() {
312
  const rab = CreateResizableArrayBuffer(10, 20);
313 314 315 316 317 318
  assertEquals(10, rab.byteLength);
  assertThrows(() => {rab.grow(21)});
  assertEquals(10, rab.byteLength);
})();

(function TestRABResizeMultipleTimes() {
319
  const rab = CreateResizableArrayBuffer(10, 20);
320 321 322 323 324 325 326
  const sizes = [15, 7, 7, 0, 8, 20, 20, 10];
  for (let s of sizes) {
    resizeHelper(rab, s);
  }
})();

(function TestRABResizeParameters() {
327
  const rab = CreateResizableArrayBuffer(10, 20);
328 329 330 331 332 333 334 335 336
  rab.resize('15');
  assertEquals(15, rab.byteLength);
  rab.resize({valueOf: function() { return 16; }});
  assertEquals(16, rab.byteLength);
  rab.resize(17.9);
  assertEquals(17, rab.byteLength);
})();

(function TestRABResizeInvalidParameters() {
337
  const rab = CreateResizableArrayBuffer(10, 20);
338 339 340 341 342 343 344 345 346 347 348 349 350
  assertThrows(() => { rab.resize(-1) }, RangeError);
  assertThrows(() => { rab.resize({valueOf: function() {
      throw new Error('length param'); }})});
  assertEquals(10, rab.byteLength);

  // Various non-numbers are converted to NaN which is treated as 0.
  rab.resize('string');
  assertEquals(0, rab.byteLength);
  rab.resize();
  assertEquals(0, rab.byteLength);
})();

(function TestRABResizeDetached() {
351
  const rab = CreateResizableArrayBuffer(10, 20);
352 353 354 355 356
  %ArrayBufferDetach(rab);
  assertThrows(() => { rab.resize(15) }, TypeError);
})();

(function DetachInsideResizeParameterConversion() {
357
  const rab = CreateResizableArrayBuffer(40, 80);
358 359 360 361 362 363 364 365 366

  const evil = {
    valueOf: () => { %ArrayBufferDetach(rab); return 20; }
  };

  assertThrows(() => { rab.resize(evil); });
})();

(function ResizeInsideResizeParameterConversion() {
367
  const rab = CreateResizableArrayBuffer(40, 80);
368 369 370 371 372 373 374 375 376 377 378 379

  const evil = {
    valueOf: () => { rab.resize(10); return 20; }
  };

  rab.resize(evil);
  assertEquals(20, rab.byteLength);
})();


(function TestRABNewMemoryAfterResizeInitializedToZero() {
  const maybe_page_size = 4096;
380
  const rab = CreateResizableArrayBuffer(maybe_page_size, 2 * maybe_page_size);
381 382 383 384 385 386 387 388 389
  const i8a = new Int8Array(rab);
  rab.resize(2 * maybe_page_size);
  for (let i = 0; i < 2 * maybe_page_size; ++i) {
    assertEquals(0, i8a[i]);
  }
})();

(function TestRABMemoryInitializedToZeroAfterShrinkAndGrow() {
  const maybe_page_size = 4096;
390
  const rab = CreateResizableArrayBuffer(maybe_page_size, 2 * maybe_page_size);
391 392 393 394 395 396 397 398 399 400 401 402
  const i8a = new Int8Array(rab);
  for (let i = 0; i < maybe_page_size; ++i) {
    i8a[i] = 1;
  }
  rab.resize(maybe_page_size / 2);
  rab.resize(maybe_page_size);
  for (let i = maybe_page_size / 2; i < maybe_page_size; ++i) {
    assertEquals(0, i8a[i]);
  }
})();

(function TestGSABBasics() {
403
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
404
  assertFalse(gsab instanceof ArrayBuffer);
405
  assertTrue(gsab instanceof SharedArrayBuffer);
406 407 408 409 410
  assertEquals(10, gsab.byteLength);
  assertEquals(20, gsab.maxByteLength);
})();

(function TestGSABCtorByteLengthEqualsMax() {
411
  const gsab = CreateGrowableSharedArrayBuffer(10, 10);
412 413 414 415 416
  assertEquals(10, gsab.byteLength);
  assertEquals(10, gsab.maxByteLength);
})();

(function TestGSABCtorByteLengthZero() {
417
  const gsab = CreateGrowableSharedArrayBuffer(0, 10);
418 419 420 421 422
  assertEquals(0, gsab.byteLength);
  assertEquals(10, gsab.maxByteLength);
})();

(function TestGSABCtorByteLengthAndMaxZero() {
423
  const gsab = CreateGrowableSharedArrayBuffer(0, 0);
424 425 426 427 428
  assertEquals(0, gsab.byteLength);
  assertEquals(0, gsab.maxByteLength);
})();

(function TestAllocatingOutrageouslyMuchThrows() {
429
  assertThrows(() => { CreateGrowableSharedArrayBuffer(0, 2 ** 100);},
430 431 432 433
               RangeError);
})();

(function TestGSABGrowToMax() {
434
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
435 436 437 438 439
  assertEquals(10, gsab.byteLength);
  growHelper(gsab, 20);
})();

(function TestGSABGrowToSameSize() {
440
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
441 442 443 444 445
  assertEquals(10, gsab.byteLength);
  growHelper(gsab, 10);
})();

(function TestGSABGrowToSmallerThrows() {
446
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
447 448 449 450 451 452
  assertEquals(10, gsab.byteLength);
  assertThrows(() => {gsab.grow(5)});
  assertEquals(10, gsab.byteLength);
})();

(function TestGSABGrowToZeroThrows() {
453
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
454 455 456 457 458 459
  assertEquals(10, gsab.byteLength);
  assertThrows(() => {gsab.grow(0)});
  assertEquals(10, gsab.byteLength);
})();

(function TestGSABGrowBeyondMaxThrows() {
460
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
461 462 463 464 465 466
  assertEquals(10, gsab.byteLength);
  assertThrows(() => {gsab.grow(21)});
  assertEquals(10, gsab.byteLength);
})();

(function TestGSABGrowMultipleTimes() {
467
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
468 469 470 471 472 473 474 475 476 477 478 479 480 481
  assertEquals(10, gsab.byteLength);
  const sizes = [15, 7, 7, 0, 8, 20, 20, 10];
  for (let s of sizes) {
    const current_size = gsab.byteLength;
    if (s < gsab.byteLength) {
      assertThrows(() => {gsab.grow(s)});
      assertEquals(current_size, gsab.byteLength);
    } else {
      growHelper(gsab, s);
    }
  }
})();

(function TestGSABGrowParameters() {
482
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
483 484 485 486 487 488 489 490 491
  gsab.grow('15');
  assertEquals(15, gsab.byteLength);
  gsab.grow({valueOf: function() { return 16; }});
  assertEquals(16, gsab.byteLength);
  gsab.grow(17.9);
  assertEquals(17, gsab.byteLength);
})();

(function TestGSABGrowInvalidParameters() {
492
  const gsab = CreateGrowableSharedArrayBuffer(0, 20);
493 494 495 496 497 498 499 500 501 502 503 504 505 506
  assertThrows(() => { gsab.grow(-1) }, RangeError);
  assertThrows(() => { gsab.grow({valueOf: function() {
      throw new Error('length param'); }})});
  assertEquals(0, gsab.byteLength);

  // Various non-numbers are converted to NaN which is treated as 0.
  gsab.grow('string');
  assertEquals(0, gsab.byteLength);
  gsab.grow();
  assertEquals(0, gsab.byteLength);
})();

(function TestGSABMemoryInitializedToZeroAfterGrow() {
  const maybe_page_size = 4096;
507
  const gsab = CreateGrowableSharedArrayBuffer(maybe_page_size,
508 509 510 511 512 513 514 515 516 517
                                             2 * maybe_page_size);
  const i8a = new Int8Array(gsab);
  gsab.grow(2 * maybe_page_size);
  assertEquals(2 * maybe_page_size, i8a.length);
  for (let i = 0; i < 2 * maybe_page_size; ++i) {
    assertEquals(0, i8a[i]);
  }
})();

(function GrowGSABOnADifferentThread() {
518
  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
519 520 521 522 523 524 525 526 527 528
  assertEquals(10, gsab.byteLength);
  function workerCode() {
    function assert(thing) {
      if (!thing) {
        postMessage('error');
      }
    }
    onmessage = function(params) {
      const gsab = params.gsab;
      assert(!(gsab instanceof ArrayBuffer));
529
      assert(gsab instanceof SharedArrayBuffer);
530
      assert(10 == gsab.byteLength);
531
      assert(20 == gsab.maxByteLength);
532 533 534 535 536 537 538 539 540
      gsab.grow(15);
      postMessage('ok');
    }
  }
  const w = new Worker(workerCode, {type: 'function'});
  w.postMessage({gsab: gsab});
  assertEquals('ok', w.getMessage());
  assertEquals(15, gsab.byteLength);
})();
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610

(function Slice() {
  const rab = CreateResizableArrayBuffer(10, 20);
  const sliced1 = rab.slice();
  assertEquals(10, sliced1.byteLength);
  assertTrue(sliced1 instanceof ArrayBuffer);
  assertFalse(sliced1 instanceof SharedArrayBuffer);
  assertFalse(sliced1.resizable);

  const gsab = CreateGrowableSharedArrayBuffer(10, 20);
  const sliced2 = gsab.slice();
  assertEquals(10, sliced2.byteLength);
  assertFalse(sliced2 instanceof ArrayBuffer);
  assertTrue(sliced2 instanceof SharedArrayBuffer);
  assertFalse(sliced2.growable);
})();

(function SliceSpeciesConstructorReturnsResizable() {
  class MyArrayBuffer extends ArrayBuffer {
    static get [Symbol.species]() { return MyResizableArrayBuffer; }
  }

  class MyResizableArrayBuffer extends ArrayBuffer {
    constructor(byteLength) {
      super(byteLength, {maxByteLength: byteLength * 2});
    }
  }

  const ab = new MyArrayBuffer(20);
  const sliced1 = ab.slice();
  assertTrue(sliced1.resizable);

  class MySharedArrayBuffer extends SharedArrayBuffer {
    static get [Symbol.species]() { return MyGrowableSharedArrayBuffer; }
  }

  class MyGrowableSharedArrayBuffer extends SharedArrayBuffer {
    constructor(byteLength) {
      super(byteLength, {maxByteLength: byteLength * 2});
    }
  }

  const sab = new MySharedArrayBuffer(20);
  const sliced2 = sab.slice();
  assertTrue(sliced2.growable);
})();

(function SliceSpeciesConstructorResizes() {
  let rab;
  let resizeWhenConstructorCalled = false;
  class MyArrayBuffer extends ArrayBuffer {
    constructor(...params) {
      super(...params);
      if (resizeWhenConstructorCalled) {
        rab.resize(2);
      }
    }
  }
  rab = new MyArrayBuffer(4, {maxByteLength: 8});
  const taWrite = new Uint8Array(rab);
  for (let i = 0; i < 4; ++i) {
    taWrite[i] = 1;
  }
  assertEquals([1, 1, 1, 1], ToNumbers(taWrite));
  resizeWhenConstructorCalled = true;
  const sliced = rab.slice();
  assertEquals(2, rab.byteLength);
  assertEquals(4, sliced.byteLength);
  assertEquals([1, 1, 0, 0], ToNumbers(new Uint8Array(sliced)));
})();