mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:24:57 +00:00
LibJS: Stub out Atomics.notify
We don't have the facilities to implement this method fully (namely, a fully realized SharedArrayBuffer). But we can implement enough to validate the values passed in by the user.
This commit is contained in:
parent
78edaad97d
commit
026363024f
4 changed files with 104 additions and 0 deletions
|
@ -213,6 +213,7 @@ void AtomicsObject::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.sub, sub, 3, attr);
|
||||
define_native_function(realm, vm.names.wait, wait, 4, attr);
|
||||
define_native_function(realm, vm.names.waitAsync, wait_async, 4, attr);
|
||||
define_native_function(realm, vm.names.notify, notify, 3, attr);
|
||||
define_native_function(realm, vm.names.xor_, xor_, 3, attr);
|
||||
|
||||
// 25.4.15 Atomics [ @@toStringTag ], https://tc39.es/ecma262/#sec-atomics-@@tostringtag
|
||||
|
@ -486,6 +487,51 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::wait_async)
|
|||
return TRY(do_wait(vm, WaitMode::Async, *typed_array, index, value, timeout));
|
||||
}
|
||||
|
||||
// 25.4.15 Atomics.notify ( typedArray, index, count ), https://tc39.es/ecma262/#sec-atomics.notify
|
||||
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::notify)
|
||||
{
|
||||
auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
|
||||
auto index = vm.argument(1);
|
||||
auto count_value = vm.argument(2);
|
||||
|
||||
// 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, true).
|
||||
// FIXME: ValidateAtomicAccessOnIntegerTypedArray is a new AO from the resizable array buffer proposal. Use it when the proposal is implemented.
|
||||
TRY(validate_integer_typed_array(vm, *typed_array, true));
|
||||
auto byte_index_in_buffer = TRY(validate_atomic_access(vm, *typed_array, index));
|
||||
|
||||
// 2. If count is undefined, then
|
||||
double count = 0.0;
|
||||
if (count_value.is_undefined()) {
|
||||
// a. Let c be +∞.
|
||||
count = js_infinity().as_double();
|
||||
}
|
||||
// 3. Else,
|
||||
else {
|
||||
// a. Let intCount be ? ToIntegerOrInfinity(count).
|
||||
auto int_count = TRY(count_value.to_integer_or_infinity(vm));
|
||||
|
||||
// b. Let c be max(intCount, 0).
|
||||
count = max(int_count, 0.0);
|
||||
}
|
||||
|
||||
// 4. Let buffer be typedArray.[[ViewedArrayBuffer]].
|
||||
auto* buffer = typed_array->viewed_array_buffer();
|
||||
|
||||
// 5. Let block be buffer.[[ArrayBufferData]].
|
||||
auto& block = buffer->buffer();
|
||||
|
||||
// 6. If IsSharedArrayBuffer(buffer) is false, return +0𝔽.
|
||||
if (!buffer->is_shared_array_buffer())
|
||||
return Value { 0 };
|
||||
|
||||
// FIXME: Implement the remaining steps when we support SharedArrayBuffer.
|
||||
(void)byte_index_in_buffer;
|
||||
(void)count;
|
||||
(void)block;
|
||||
|
||||
return vm.throw_completion<InternalError>(ErrorType::NotImplemented, "SharedArrayBuffer"sv);
|
||||
}
|
||||
|
||||
// 25.4.14 Atomics.xor ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.xor
|
||||
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::xor_)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(sub);
|
||||
JS_DECLARE_NATIVE_FUNCTION(wait);
|
||||
JS_DECLARE_NATIVE_FUNCTION(wait_async);
|
||||
JS_DECLARE_NATIVE_FUNCTION(notify);
|
||||
JS_DECLARE_NATIVE_FUNCTION(xor_);
|
||||
};
|
||||
|
||||
|
|
|
@ -387,6 +387,7 @@ namespace JS {
|
|||
P(next) \
|
||||
P(normalize) \
|
||||
P(notation) \
|
||||
P(notify) \
|
||||
P(now) \
|
||||
P(numberingSystem) \
|
||||
P(numeric) \
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
describe("errors", () => {
|
||||
test("called on non-TypedArray", () => {
|
||||
expect(() => {
|
||||
Atomics.notify(Symbol.hasInstance, 0, 0);
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type TypedArray");
|
||||
});
|
||||
|
||||
test("detached buffer", () => {
|
||||
expect(() => {
|
||||
const typedArray = new Int32Array(4);
|
||||
detachArrayBuffer(typedArray.buffer);
|
||||
|
||||
Atomics.notify(typedArray, 0, 0);
|
||||
}).toThrowWithMessage(TypeError, "ArrayBuffer is detached");
|
||||
});
|
||||
|
||||
test("invalid TypedArray type", () => {
|
||||
expect(() => {
|
||||
const typedArray = new Float32Array(4);
|
||||
Atomics.notify(typedArray, 0, 0);
|
||||
}).toThrowWithMessage(
|
||||
TypeError,
|
||||
"Typed array Float32Array element type is not Int32 or BigInt64"
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid index", () => {
|
||||
expect(() => {
|
||||
const buffer = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
|
||||
const typedArray = new Int32Array(buffer);
|
||||
|
||||
Atomics.notify(typedArray, 4, 0);
|
||||
}).toThrowWithMessage(RangeError, "Index 4 is out of range of array length 4");
|
||||
});
|
||||
|
||||
test("invalid count", () => {
|
||||
expect(() => {
|
||||
const buffer = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
|
||||
const typedArray = new Int32Array(buffer);
|
||||
|
||||
Atomics.notify(typedArray, 0, Symbol.hasInstance);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert symbol to number");
|
||||
});
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
test("invariants", () => {
|
||||
expect(Atomics.notify).toHaveLength(3);
|
||||
});
|
||||
|
||||
test("non-shared ArrayBuffer", () => {
|
||||
const typedArray = new Int32Array(4);
|
||||
const waiters = Atomics.notify(typedArray, 0, 0);
|
||||
expect(waiters).toBe(0);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue