|
@@ -67,35 +67,39 @@ static ThrowCompletionOr<Value> get_view_value(VM& vm, Value request_index, Valu
|
|
|
// 4. Set isLittleEndian to ToBoolean(isLittleEndian).
|
|
|
auto little_endian = is_little_endian.to_boolean();
|
|
|
|
|
|
- // 5. Let buffer be view.[[ViewedArrayBuffer]].
|
|
|
- auto buffer = view->viewed_array_buffer();
|
|
|
+ // 5. Let viewOffset be view.[[ByteOffset]].
|
|
|
+ auto view_offset = view->byte_offset();
|
|
|
|
|
|
- // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
|
|
|
- if (buffer->is_detached())
|
|
|
- return vm.template throw_completion<TypeError>(ErrorType::DetachedArrayBuffer);
|
|
|
+ // 6. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
|
|
|
+ auto view_record = make_data_view_with_buffer_witness_record(*view, ArrayBuffer::Order::Unordered);
|
|
|
|
|
|
- // 7. Let viewOffset be view.[[ByteOffset]].
|
|
|
- auto view_offset = view->byte_offset();
|
|
|
+ // 7. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
|
|
|
+ // 8. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
|
|
|
+ if (is_view_out_of_bounds(view_record))
|
|
|
+ return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "DataView"sv);
|
|
|
|
|
|
- // 8. Let viewSize be view.[[ByteLength]].
|
|
|
- auto view_size = view->byte_length();
|
|
|
+ // 9. Let viewSize be GetViewByteLength(viewRecord).
|
|
|
+ auto view_size = get_view_byte_length(view_record);
|
|
|
|
|
|
- // 9. Let elementSize be the Element Size value specified in Table 68 for Element Type type.
|
|
|
+ // 10. Let elementSize be the Element Size value specified in Table 71 for Element Type type.
|
|
|
auto element_size = sizeof(T);
|
|
|
|
|
|
- // 11. Let bufferIndex be getIndex + viewOffset.
|
|
|
- Checked<size_t> buffer_index = get_index;
|
|
|
- buffer_index += view_offset;
|
|
|
-
|
|
|
+ // 11. If getIndex + elementSize > viewSize, throw a RangeError exception.
|
|
|
Checked<size_t> end_index = get_index;
|
|
|
end_index += element_size;
|
|
|
|
|
|
- // 10. If getIndex + elementSize > viewSize, throw a RangeError exception.
|
|
|
- if (buffer_index.has_overflow() || end_index.has_overflow() || end_index.value() > view_size)
|
|
|
+ if (end_index.has_overflow() || end_index.value() > view_size)
|
|
|
+ return vm.throw_completion<RangeError>(ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
|
|
|
+
|
|
|
+ // 12. Let bufferIndex be getIndex + viewOffset.
|
|
|
+ Checked<size_t> buffer_index = get_index;
|
|
|
+ buffer_index += view_offset;
|
|
|
+
|
|
|
+ if (buffer_index.has_overflow())
|
|
|
return vm.throw_completion<RangeError>(ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
|
|
|
|
|
|
- // 12. Return GetValueFromBuffer(buffer, bufferIndex, type, false, Unordered, isLittleEndian).
|
|
|
- return buffer->get_value<T>(buffer_index.value(), false, ArrayBuffer::Order::Unordered, little_endian);
|
|
|
+ // 13. Return GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian).
|
|
|
+ return view->viewed_array_buffer()->get_value<T>(buffer_index.value(), false, ArrayBuffer::Order::Unordered, little_endian);
|
|
|
}
|
|
|
|
|
|
// 25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value ), https://tc39.es/ecma262/#sec-setviewvalue
|
|
@@ -121,37 +125,41 @@ static ThrowCompletionOr<Value> set_view_value(VM& vm, Value request_index, Valu
|
|
|
// 6. Set isLittleEndian to ToBoolean(isLittleEndian).
|
|
|
auto little_endian = is_little_endian.to_boolean();
|
|
|
|
|
|
- // 7. Let buffer be view.[[ViewedArrayBuffer]].
|
|
|
- auto buffer = view->viewed_array_buffer();
|
|
|
+ // 7. Let viewOffset be view.[[ByteOffset]].
|
|
|
+ auto view_offset = view->byte_offset();
|
|
|
|
|
|
- // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
|
|
|
- if (buffer->is_detached())
|
|
|
- return vm.throw_completion<TypeError>(ErrorType::DetachedArrayBuffer);
|
|
|
+ // 8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
|
|
|
+ auto view_record = make_data_view_with_buffer_witness_record(*view, ArrayBuffer::Order::Unordered);
|
|
|
|
|
|
- // 9. Let viewOffset be view.[[ByteOffset]].
|
|
|
- auto view_offset = view->byte_offset();
|
|
|
+ // 9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
|
|
|
+ // 10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
|
|
|
+ if (is_view_out_of_bounds(view_record))
|
|
|
+ return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "DataView"sv);
|
|
|
|
|
|
- // 10. Let viewSize be view.[[ByteLength]].
|
|
|
- auto view_size = view->byte_length();
|
|
|
+ // 11. Let viewSize be GetViewByteLength(viewRecord).
|
|
|
+ auto view_size = get_view_byte_length(view_record);
|
|
|
|
|
|
- // 11. Let elementSize be the Element Size value specified in Table 68 for Element Type type.
|
|
|
+ // 12. Let elementSize be the Element Size value specified in Table 71 for Element Type type.
|
|
|
auto element_size = sizeof(T);
|
|
|
|
|
|
- // 13. Let bufferIndex be getIndex + viewOffset.
|
|
|
- Checked<size_t> buffer_index = get_index;
|
|
|
- buffer_index += view_offset;
|
|
|
-
|
|
|
+ // 13. If getIndex + elementSize > viewSize, throw a RangeError exception.
|
|
|
Checked<size_t> end_index = get_index;
|
|
|
end_index += element_size;
|
|
|
|
|
|
- // 12. If getIndex + elementSize > viewSize, throw a RangeError exception.
|
|
|
- if (buffer_index.has_overflow() || end_index.has_overflow() || end_index.value() > view_size)
|
|
|
+ if (end_index.has_overflow() || end_index.value() > view_size)
|
|
|
+ return vm.throw_completion<RangeError>(ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
|
|
|
+
|
|
|
+ // 14. Let bufferIndex be getIndex + viewOffset.
|
|
|
+ Checked<size_t> buffer_index = get_index;
|
|
|
+ buffer_index += view_offset;
|
|
|
+
|
|
|
+ if (buffer_index.has_overflow())
|
|
|
return vm.throw_completion<RangeError>(ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
|
|
|
|
|
|
- // 14. Perform SetValueInBuffer(buffer, bufferIndex, type, numberValue, false, Unordered, isLittleEndian).
|
|
|
- buffer->set_value<T>(buffer_index.value(), number_value, false, ArrayBuffer::Order::Unordered, little_endian);
|
|
|
+ // 15. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
|
|
|
+ view->viewed_array_buffer()->set_value<T>(buffer_index.value(), number_value, false, ArrayBuffer::Order::Unordered, little_endian);
|
|
|
|
|
|
- // 15. Return undefined.
|
|
|
+ // 16. Return undefined.
|
|
|
return js_undefined();
|
|
|
}
|
|
|
|
|
@@ -176,14 +184,18 @@ JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::byte_length_getter)
|
|
|
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
|
|
|
auto data_view = TRY(typed_this_value(vm));
|
|
|
|
|
|
- // 4. Let buffer be O.[[ViewedArrayBuffer]].
|
|
|
- // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
|
|
|
- if (data_view->viewed_array_buffer()->is_detached())
|
|
|
- return vm.throw_completion<TypeError>(ErrorType::DetachedArrayBuffer);
|
|
|
+ // 4. Let viewRecord be MakeDataViewWithBufferWitnessRecord(O, seq-cst).
|
|
|
+ auto view_record = make_data_view_with_buffer_witness_record(data_view, ArrayBuffer::Order::SeqCst);
|
|
|
+
|
|
|
+ // 5. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
|
|
|
+ if (is_view_out_of_bounds(view_record))
|
|
|
+ return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "DataView"sv);
|
|
|
+
|
|
|
+ // 6. Let size be GetViewByteLength(viewRecord).
|
|
|
+ auto size = get_view_byte_length(view_record);
|
|
|
|
|
|
- // 6. Let size be O.[[ByteLength]].
|
|
|
// 7. Return 𝔽(size).
|
|
|
- return Value(data_view->byte_length());
|
|
|
+ return Value { size };
|
|
|
}
|
|
|
|
|
|
// 25.3.4.3 get DataView.prototype.byteOffset, https://tc39.es/ecma262/#sec-get-dataview.prototype.byteoffset
|
|
@@ -194,14 +206,18 @@ JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::byte_offset_getter)
|
|
|
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
|
|
|
auto data_view = TRY(typed_this_value(vm));
|
|
|
|
|
|
- // 4. Let buffer be O.[[ViewedArrayBuffer]].
|
|
|
- // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
|
|
|
- if (data_view->viewed_array_buffer()->is_detached())
|
|
|
- return vm.throw_completion<TypeError>(ErrorType::DetachedArrayBuffer);
|
|
|
+ // 4. Let viewRecord be MakeDataViewWithBufferWitnessRecord(O, seq-cst).
|
|
|
+ auto view_record = make_data_view_with_buffer_witness_record(data_view, ArrayBuffer::Order::SeqCst);
|
|
|
+
|
|
|
+ // 5. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
|
|
|
+ if (is_view_out_of_bounds(view_record))
|
|
|
+ return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "DataView"sv);
|
|
|
|
|
|
// 6. Let offset be O.[[ByteOffset]].
|
|
|
+ auto offset = data_view->byte_offset();
|
|
|
+
|
|
|
// 7. Return 𝔽(offset).
|
|
|
- return Value(data_view->byte_offset());
|
|
|
+ return Value { offset };
|
|
|
}
|
|
|
|
|
|
// 25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getbigint64
|