v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-dataview.cc
Go to the documentation of this file.
1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
8#include "src/heap/factory.h"
13
14namespace v8 {
15namespace internal {
16
17// -----------------------------------------------------------------------------
18// ES #sec-dataview-objects
19
20// ES #sec-dataview-constructor
21BUILTIN(DataViewConstructor) {
22 const char* const kMethodName = "DataView constructor";
23 HandleScope scope(isolate);
24 // 1. If NewTarget is undefined, throw a TypeError exception.
25 if (IsUndefined(*args.new_target(), isolate)) { // [[Call]]
27 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
28 isolate->factory()->NewStringFromAsciiChecked(
29 "DataView")));
30 }
31 // [[Construct]]
32 DirectHandle<JSFunction> target = args.target();
34 DirectHandle<Object> buffer = args.atOrUndefined(isolate, 1);
35 DirectHandle<Object> byte_offset = args.atOrUndefined(isolate, 2);
36 DirectHandle<Object> byte_length = args.atOrUndefined(isolate, 3);
37
38 // 2. Perform ? RequireInternalSlot(buffer, [[ArrayBufferData]]).
39 if (!IsJSArrayBuffer(*buffer)) {
41 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
42 }
43 auto array_buffer = Cast<JSArrayBuffer>(buffer);
44
45 // 3. Let offset be ? ToIndex(byteOffset).
47 isolate, byte_offset,
48 Object::ToIndex(isolate, byte_offset, MessageTemplate::kInvalidOffset));
49 size_t view_byte_offset = Object::NumberValue(*byte_offset);
50
51 // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
52 if (array_buffer->was_detached()) {
54 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
55 isolate->factory()->NewStringFromAsciiChecked(
56 kMethodName)));
57 }
58
59 // 5. Let bufferByteLength be ArrayBufferByteLength(buffer, SeqCst).
60 size_t buffer_byte_length = array_buffer->GetByteLength();
61
62 // 6. If offset > bufferByteLength, throw a RangeError exception.
63 if (view_byte_offset > buffer_byte_length) {
65 isolate, NewRangeError(MessageTemplate::kInvalidOffset, byte_offset));
66 }
67
68 // 7. Let bufferIsResizable be IsResizableArrayBuffer(buffer).
69 // 8. Let byteLengthChecked be empty.
70 // 9. If bufferIsResizable is true and byteLength is undefined, then
71 // a. Let viewByteLength be auto.
72 // 10. Else if byteLength is undefined, then
73 // a. Let viewByteLength be bufferByteLength - offset.
74 size_t view_byte_length;
75 bool length_tracking = false;
76 if (IsUndefined(*byte_length, isolate)) {
77 view_byte_length = buffer_byte_length - view_byte_offset;
78 length_tracking = array_buffer->is_resizable_by_js();
79 } else {
80 // 11. Else,
81 // a. Set byteLengthChecked be ? ToIndex(byteLength).
82 // b. Let viewByteLength be byteLengthChecked.
83 // c. If offset + viewByteLength > bufferByteLength, throw a
84 // RangeError exception.
86 isolate, byte_length,
87 Object::ToIndex(isolate, byte_length,
88 MessageTemplate::kInvalidDataViewLength));
89 if (view_byte_offset + Object::NumberValue(*byte_length) >
90 buffer_byte_length) {
92 isolate,
93 NewRangeError(MessageTemplate::kInvalidDataViewLength, byte_length));
94 }
95 view_byte_length = Object::NumberValue(*byte_length);
96 }
97
98 bool is_backed_by_rab =
99 array_buffer->is_resizable_by_js() && !array_buffer->is_shared();
100
101 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
102 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
103 // [[ByteLength]], [[ByteOffset]]»).
105
106 if (is_backed_by_rab || length_tracking) {
107 // Create a JSRabGsabDataView.
108 DirectHandle<Map> initial_map;
110 isolate, initial_map,
113 isolate, result,
114 JSObject::NewWithMap(isolate, initial_map, {},
116 } else {
117 // Create a JSDataView.
119 isolate, result,
121 }
123 {
124 // Must fully initialize the JSDataViewOrRabGsabDataView here so that it
125 // passes ObjectVerify, which may for example be triggered when allocating
126 // error objects below.
129
130 for (int i = 0; i < ArrayBufferView::kEmbedderFieldCount; ++i) {
131 // TODO(v8:10391, saelo): Handle external pointers in EmbedderDataSlot
132 raw->SetEmbedderField(i, Smi::zero());
133 }
134 raw->set_bit_field(0);
135 raw->set_is_backed_by_rab(is_backed_by_rab);
136 raw->set_is_length_tracking(length_tracking);
137 raw->set_byte_length(0);
138 raw->set_byte_offset(0);
139 raw->set_data_pointer(isolate, array_buffer->backing_store());
140 raw->set_buffer(*array_buffer);
141 }
142
143 // 13. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
144 if (array_buffer->was_detached()) {
146 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
147 isolate->factory()->NewStringFromAsciiChecked(
148 kMethodName)));
149 }
150
151 // 14. Let getBufferByteLength be
152 // MakeIdempotentArrayBufferByteLengthGetter(SeqCst).
153 // 15. Set bufferByteLength be getBufferByteLength(buffer).
154 buffer_byte_length = array_buffer->GetByteLength();
155
156 // 16. If offset > bufferByteLength, throw a RangeError exception.
157 if (view_byte_offset > buffer_byte_length) {
159 isolate, NewRangeError(MessageTemplate::kInvalidOffset, byte_offset));
160 }
161
162 // 17. If byteLengthChecked is not empty, then
163 // a. If offset + viewByteLength > bufferByteLength, throw a RangeError
164 // exception.
165 if (!length_tracking &&
166 view_byte_offset + view_byte_length > buffer_byte_length) {
168 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
169 }
170
171 // 18. Set O.[[ViewedArrayBuffer]] to buffer.
172 // Already done during initialization of the JSDataView above.
173
174 // 19. Set O.[[ByteLength]] to viewByteLength.
175 data_view->set_byte_length(length_tracking ? 0 : view_byte_length);
176
177 // 20. Set O.[[ByteOffset]] to offset.
178 data_view->set_byte_offset(view_byte_offset);
179 data_view->set_data_pointer(
180 isolate,
181 static_cast<uint8_t*>(array_buffer->backing_store()) + view_byte_offset);
182
183 // 21. Return O.
184 return *result;
185}
186
187} // namespace internal
188} // namespace v8
#define BUILTIN(name)
static const int kEmbedderFieldCount
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Map > GetDerivedRabGsabDataViewMap(Isolate *isolate, DirectHandle< JSReceiver > new_target)
static MaybeDirectHandle< JSObject > NewWithMap(Isolate *isolate, DirectHandle< Map > initial_map, DirectHandle< AllocationSite > site, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< JSObject > New(DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target, DirectHandle< AllocationSite > site, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToIndex(Isolate *isolate, HandleType< T > input, MessageTemplate error_index)
static double NumberValue(Tagged< Number > obj)
static constexpr Tagged< Smi > zero()
Definition smi.h:99
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
ZoneVector< RpoNumber > & result
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150