Add resizable ArrayBuffers (#646)

This commit implements resizable ArrayBuffers - RABs for short - and
extends typed arrays (TAs) to support fixed-length and length-tracking
modes.

SharedArrayBuffers (SABs) also support the maxByteLength option now but
I cheated and allocate all memory upfront because atomically resizing
memory allocations is hard and this commit is already big and complex.

The lion's share is updating all the TA prototype methods to deal with
RABs resizing underneath them. Method arguments can be arbitrary objects
with arbitrary .valueOf methods and arbitrary side effects, like...
resizing the RAB we're currently operating on.

Fixes: https://github.com/quickjs-ng/quickjs/issues/477
This commit is contained in:
Ben Noordhuis 2024-11-05 21:55:42 +01:00 committed by GitHub
parent e569f39bf1
commit 37fe427d59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 716 additions and 254 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -176,6 +176,7 @@ DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out") DEF(timed_out, "timed-out")
DEF(ok, "ok") DEF(ok, "ok")
DEF(toJSON, "toJSON") DEF(toJSON, "toJSON")
DEF(maxByteLength, "maxByteLength")
/* class names */ /* class names */
DEF(Object, "Object") DEF(Object, "Object")
DEF(Array, "Array") DEF(Array, "Array")

918
quickjs.c

File diff suppressed because it is too large Load diff

View file

@ -173,7 +173,7 @@ regexp-named-groups
regexp-unicode-property-escapes regexp-unicode-property-escapes
regexp-v-flag regexp-v-flag
RegExp.escape=skip RegExp.escape=skip
resizable-arraybuffer=skip resizable-arraybuffer
rest-parameters rest-parameters
Set Set
set-methods set-methods

View file

@ -389,4 +389,7 @@ test262/test/language/expressions/assignment/target-super-computed-reference.js:
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated. test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated. test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js:13: SyntaxError: Could not find export 'check' in module 'test262/test/language/module-code/top-level-await/async-module-sync_FIXTURE.js' test262/test/language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js:13: SyntaxError: Could not find export 'check' in module 'test262/test/language/module-code/top-level-await/async-module-sync_FIXTURE.js'
test262/test/staging/ArrayBuffer/resizable/object-define-property-define-properties.js:55: strict mode: unexpected error: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/staging/ArrayBuffer/resizable/object-define-property-parameter-conversion-grows.js:67: strict mode: unexpected error: TypeError: out-of-bound index in typed array
test262/test/staging/ArrayBuffer/resizable/object-define-property-parameter-conversion-shrinks.js:59: strict mode: unexpected error: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/staging/top-level-await/tla-hang-entry.js:10: TypeError: $DONE() not called test262/test/staging/top-level-await/tla-hang-entry.js:10: TypeError: $DONE() not called

View file

@ -139,6 +139,41 @@ function bjson_test(a)
} }
} }
function bjson_test_arraybuffer()
{
var buf, array_buffer;
array_buffer = new ArrayBuffer(4);
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 4);
assert(array_buffer.resizable, false);
buf = bjson.write(array_buffer);
array_buffer = bjson.read(buf, 0, buf.byteLength);
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 4);
assert(array_buffer.resizable, false);
array_buffer = new ArrayBuffer(4, {maxByteLength: 4});
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 4);
assert(array_buffer.resizable, true);
buf = bjson.write(array_buffer);
array_buffer = bjson.read(buf, 0, buf.byteLength);
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 4);
assert(array_buffer.resizable, true);
array_buffer = new ArrayBuffer(4, {maxByteLength: 8});
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 8);
assert(array_buffer.resizable, true);
buf = bjson.write(array_buffer);
array_buffer = bjson.read(buf, 0, buf.byteLength);
assert(array_buffer.byteLength, 4);
assert(array_buffer.maxByteLength, 8);
assert(array_buffer.resizable, true);
}
/* test multiple references to an object including circular /* test multiple references to an object including circular
references */ references */
function bjson_test_reference() function bjson_test_reference()
@ -292,6 +327,7 @@ function bjson_test_all()
assert(e instanceof TypeError); assert(e instanceof TypeError);
} }
bjson_test_arraybuffer();
bjson_test_reference(); bjson_test_reference();
bjson_test_regexp(); bjson_test_regexp();
bjson_test_map(); bjson_test_map();