@@ -129,5 +129,209 @@ BUILTIN(DataViewPrototypeGetByteOffset) {
129129 return data_view->byte_offset ();
130130}
131131
132+ namespace {
133+
134+ bool NeedToFlipBytes (bool is_little_endian) {
135+ #ifdef V8_TARGET_LITTLE_ENDIAN
136+ return !is_little_endian;
137+ #else
138+ return is_little_endian;
139+ #endif
140+ }
141+
142+ template <size_t n>
143+ void CopyBytes (uint8_t * target, uint8_t const * source) {
144+ for (size_t i = 0 ; i < n; i++) {
145+ *(target++) = *(source++);
146+ }
147+ }
148+
149+ template <size_t n>
150+ void FlipBytes (uint8_t * target, uint8_t const * source) {
151+ source = source + (n - 1 );
152+ for (size_t i = 0 ; i < n; i++) {
153+ *(target++) = *(source--);
154+ }
155+ }
156+
157+ // ES6 section 24.2.1.1 GetViewValue (view, requestIndex, isLittleEndian, type)
158+ template <typename T>
159+ MaybeHandle<Object> GetViewValue (Isolate* isolate, Handle<JSDataView> data_view,
160+ Handle<Object> request_index,
161+ bool is_little_endian) {
162+ ASSIGN_RETURN_ON_EXCEPTION (
163+ isolate, request_index,
164+ Object::ToIndex (isolate, request_index,
165+ MessageTemplate::kInvalidDataViewAccessorOffset ),
166+ Object);
167+ size_t get_index = 0 ;
168+ if (!TryNumberToSize (*request_index, &get_index)) {
169+ THROW_NEW_ERROR (
170+ isolate, NewRangeError (MessageTemplate::kInvalidDataViewAccessorOffset ),
171+ Object);
172+ }
173+ Handle<JSArrayBuffer> buffer (JSArrayBuffer::cast (data_view->buffer ()),
174+ isolate);
175+ size_t const data_view_byte_offset = NumberToSize (data_view->byte_offset ());
176+ size_t const data_view_byte_length = NumberToSize (data_view->byte_length ());
177+ if (get_index + sizeof (T) > data_view_byte_length ||
178+ get_index + sizeof (T) < get_index) { // overflow
179+ THROW_NEW_ERROR (
180+ isolate, NewRangeError (MessageTemplate::kInvalidDataViewAccessorOffset ),
181+ Object);
182+ }
183+ union {
184+ T data;
185+ uint8_t bytes[sizeof (T)];
186+ } v;
187+ size_t const buffer_offset = data_view_byte_offset + get_index;
188+ DCHECK_GE (NumberToSize (buffer->byte_length ()), buffer_offset + sizeof (T));
189+ uint8_t const * const source =
190+ static_cast <uint8_t *>(buffer->backing_store ()) + buffer_offset;
191+ if (NeedToFlipBytes (is_little_endian)) {
192+ FlipBytes<sizeof (T)>(v.bytes , source);
193+ } else {
194+ CopyBytes<sizeof (T)>(v.bytes , source);
195+ }
196+ return isolate->factory ()->NewNumber (v.data );
197+ }
198+
199+ template <typename T>
200+ T DataViewConvertValue (double value);
201+
202+ template <>
203+ int8_t DataViewConvertValue<int8_t >(double value) {
204+ return static_cast <int8_t >(DoubleToInt32 (value));
205+ }
206+
207+ template <>
208+ int16_t DataViewConvertValue<int16_t >(double value) {
209+ return static_cast <int16_t >(DoubleToInt32 (value));
210+ }
211+
212+ template <>
213+ int32_t DataViewConvertValue<int32_t >(double value) {
214+ return DoubleToInt32 (value);
215+ }
216+
217+ template <>
218+ uint8_t DataViewConvertValue<uint8_t >(double value) {
219+ return static_cast <uint8_t >(DoubleToUint32 (value));
220+ }
221+
222+ template <>
223+ uint16_t DataViewConvertValue<uint16_t >(double value) {
224+ return static_cast <uint16_t >(DoubleToUint32 (value));
225+ }
226+
227+ template <>
228+ uint32_t DataViewConvertValue<uint32_t >(double value) {
229+ return DoubleToUint32 (value);
230+ }
231+
232+ template <>
233+ float DataViewConvertValue<float >(double value) {
234+ return static_cast <float >(value);
235+ }
236+
237+ template <>
238+ double DataViewConvertValue<double >(double value) {
239+ return value;
240+ }
241+
242+ // ES6 section 24.2.1.2 SetViewValue (view, requestIndex, isLittleEndian, type,
243+ // value)
244+ template <typename T>
245+ MaybeHandle<Object> SetViewValue (Isolate* isolate, Handle<JSDataView> data_view,
246+ Handle<Object> request_index,
247+ bool is_little_endian, Handle<Object> value) {
248+ ASSIGN_RETURN_ON_EXCEPTION (
249+ isolate, request_index,
250+ Object::ToIndex (isolate, request_index,
251+ MessageTemplate::kInvalidDataViewAccessorOffset ),
252+ Object);
253+ ASSIGN_RETURN_ON_EXCEPTION (isolate, value, Object::ToNumber (value), Object);
254+ size_t get_index = 0 ;
255+ if (!TryNumberToSize (*request_index, &get_index)) {
256+ THROW_NEW_ERROR (
257+ isolate, NewRangeError (MessageTemplate::kInvalidDataViewAccessorOffset ),
258+ Object);
259+ }
260+ Handle<JSArrayBuffer> buffer (JSArrayBuffer::cast (data_view->buffer ()),
261+ isolate);
262+ size_t const data_view_byte_offset = NumberToSize (data_view->byte_offset ());
263+ size_t const data_view_byte_length = NumberToSize (data_view->byte_length ());
264+ if (get_index + sizeof (T) > data_view_byte_length ||
265+ get_index + sizeof (T) < get_index) { // overflow
266+ THROW_NEW_ERROR (
267+ isolate, NewRangeError (MessageTemplate::kInvalidDataViewAccessorOffset ),
268+ Object);
269+ }
270+ union {
271+ T data;
272+ uint8_t bytes[sizeof (T)];
273+ } v;
274+ v.data = DataViewConvertValue<T>(value->Number ());
275+ size_t const buffer_offset = data_view_byte_offset + get_index;
276+ DCHECK (NumberToSize (buffer->byte_length ()) >= buffer_offset + sizeof (T));
277+ uint8_t * const target =
278+ static_cast <uint8_t *>(buffer->backing_store ()) + buffer_offset;
279+ if (NeedToFlipBytes (is_little_endian)) {
280+ FlipBytes<sizeof (T)>(target, v.bytes );
281+ } else {
282+ CopyBytes<sizeof (T)>(target, v.bytes );
283+ }
284+ return isolate->factory ()->undefined_value ();
285+ }
286+
287+ } // namespace
288+
289+ #define DATA_VIEW_PROTOTYPE_GET (Type, type ) \
290+ BUILTIN (DataViewPrototypeGet##Type) { \
291+ HandleScope scope (isolate); \
292+ CHECK_RECEIVER (JSDataView, data_view, " DataView.prototype.get" #Type); \
293+ Handle<Object> byte_offset = args.atOrUndefined (isolate, 1 ); \
294+ Handle<Object> is_little_endian = args.atOrUndefined (isolate, 2 ); \
295+ Handle<Object> result; \
296+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION ( \
297+ isolate, result, \
298+ GetViewValue<type>(isolate, data_view, byte_offset, \
299+ is_little_endian->BooleanValue ())); \
300+ return *result; \
301+ }
302+ DATA_VIEW_PROTOTYPE_GET (Int8, int8_t )
303+ DATA_VIEW_PROTOTYPE_GET (Uint8, uint8_t )
304+ DATA_VIEW_PROTOTYPE_GET (Int16, int16_t )
305+ DATA_VIEW_PROTOTYPE_GET (Uint16, uint16_t )
306+ DATA_VIEW_PROTOTYPE_GET (Int32, int32_t )
307+ DATA_VIEW_PROTOTYPE_GET (Uint32, uint32_t )
308+ DATA_VIEW_PROTOTYPE_GET (Float32, float )
309+ DATA_VIEW_PROTOTYPE_GET (Float64, double )
310+ #undef DATA_VIEW_PROTOTYPE_GET
311+
312+ #define DATA_VIEW_PROTOTYPE_SET (Type, type ) \
313+ BUILTIN (DataViewPrototypeSet##Type) { \
314+ HandleScope scope (isolate); \
315+ CHECK_RECEIVER (JSDataView, data_view, " DataView.prototype.set" #Type); \
316+ Handle<Object> byte_offset = args.atOrUndefined (isolate, 1 ); \
317+ Handle<Object> value = args.atOrUndefined (isolate, 2 ); \
318+ Handle<Object> is_little_endian = args.atOrUndefined (isolate, 3 ); \
319+ Handle<Object> result; \
320+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION ( \
321+ isolate, result, \
322+ SetViewValue<type>(isolate, data_view, byte_offset, \
323+ is_little_endian->BooleanValue (), value)); \
324+ return *result; \
325+ }
326+ DATA_VIEW_PROTOTYPE_SET (Int8, int8_t )
327+ DATA_VIEW_PROTOTYPE_SET (Uint8, uint8_t )
328+ DATA_VIEW_PROTOTYPE_SET (Int16, int16_t )
329+ DATA_VIEW_PROTOTYPE_SET (Uint16, uint16_t )
330+ DATA_VIEW_PROTOTYPE_SET (Int32, int32_t )
331+ DATA_VIEW_PROTOTYPE_SET (Uint32, uint32_t )
332+ DATA_VIEW_PROTOTYPE_SET (Float32, float )
333+ DATA_VIEW_PROTOTYPE_SET (Float64, double )
334+ #undef DATA_VIEW_PROTOTYPE_SET
335+
132336} // namespace internal
133337} // namespace v8
0 commit comments