blob: 32c5a83d2f9cd6f0a2e939881e51fc3e871b4e47 [file] [log] [blame]
Ben Murdochf91f0612016-11-29 16:50:11 +00001// 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
5#include "src/builtins/builtins.h"
6#include "src/builtins/builtins-utils.h"
7
8namespace v8 {
9namespace internal {
10
11// -----------------------------------------------------------------------------
12// ES6 section 24.2 DataView Objects
13
14// ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
15BUILTIN(DataViewConstructor) {
16 HandleScope scope(isolate);
17 THROW_NEW_ERROR_RETURN_FAILURE(
18 isolate,
19 NewTypeError(MessageTemplate::kConstructorNotFunction,
20 isolate->factory()->NewStringFromAsciiChecked("DataView")));
21}
22
23// ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
24BUILTIN(DataViewConstructor_ConstructStub) {
25 HandleScope scope(isolate);
26 Handle<JSFunction> target = args.target<JSFunction>();
27 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
28 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
29 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
30 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
31
32 // 2. If Type(buffer) is not Object, throw a TypeError exception.
33 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
34 // TypeError exception.
35 if (!buffer->IsJSArrayBuffer()) {
36 THROW_NEW_ERROR_RETURN_FAILURE(
37 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
38 }
39 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
40
41 // 4. Let offset be ToIndex(byteOffset).
42 Handle<Object> offset;
43 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
44 isolate, offset,
45 Object::ToIndex(isolate, byte_offset,
46 MessageTemplate::kInvalidDataViewOffset));
47
48 // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
49 // We currently violate the specification at this point.
50
51 // 6. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
52 // internal slot.
53 double const buffer_byte_length = array_buffer->byte_length()->Number();
54
55 // 7. If offset > bufferByteLength, throw a RangeError exception
56 if (offset->Number() > buffer_byte_length) {
57 THROW_NEW_ERROR_RETURN_FAILURE(
58 isolate,
59 NewRangeError(MessageTemplate::kInvalidDataViewOffset, offset));
60 }
61
62 Handle<Object> view_byte_length;
63 if (byte_length->IsUndefined(isolate)) {
64 // 8. If byteLength is undefined, then
65 // a. Let viewByteLength be bufferByteLength - offset.
66 view_byte_length =
67 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
68 } else {
69 // 9. Else,
70 // a. Let viewByteLength be ? ToIndex(byteLength).
71 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
72 // exception
73 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
74 isolate, view_byte_length,
75 Object::ToIndex(isolate, byte_length,
76 MessageTemplate::kInvalidDataViewLength));
77 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
78 THROW_NEW_ERROR_RETURN_FAILURE(
79 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
80 }
81 }
82
83 // 10. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
84 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
85 // [[ByteLength]], [[ByteOffset]]»).
86 // 11. Set O's [[DataView]] internal slot to true.
87 Handle<JSObject> result;
88 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
89 JSObject::New(target, new_target));
90 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
91 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
92 }
93
94 // 12. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
95 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
96
97 // 13. Set O's [[ByteLength]] internal slot to viewByteLength.
98 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
99
100 // 14. Set O's [[ByteOffset]] internal slot to offset.
101 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
102
103 // 15. Return O.
104 return *result;
105}
106
107// ES6 section 24.2.4.1 get DataView.prototype.buffer
108BUILTIN(DataViewPrototypeGetBuffer) {
109 HandleScope scope(isolate);
110 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
111 return data_view->buffer();
112}
113
114// ES6 section 24.2.4.2 get DataView.prototype.byteLength
115BUILTIN(DataViewPrototypeGetByteLength) {
116 HandleScope scope(isolate);
117 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
118 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
119 // here if the JSArrayBuffer of the {data_view} was neutered.
120 return data_view->byte_length();
121}
122
123// ES6 section 24.2.4.3 get DataView.prototype.byteOffset
124BUILTIN(DataViewPrototypeGetByteOffset) {
125 HandleScope scope(isolate);
126 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
127 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
128 // here if the JSArrayBuffer of the {data_view} was neutered.
129 return data_view->byte_offset();
130}
131
132} // namespace internal
133} // namespace v8