blob: e86c86cb880c8bbb2f5b49e0d3be84370b121c5e [file] [log] [blame]
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28"use strict";
29
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000030// This file relies on the fact that the following declaration has been made
31// in runtime.js:
32// var $Array = global.Array;
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000033var $ArrayBuffer = global.ArrayBuffer;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +000034
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +000035
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000036// --------------- Typed Arrays ---------------------
verwaest@chromium.org057bd502013-11-06 12:03:29 +000037macro TYPED_ARRAYS(FUNCTION)
38// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
39FUNCTION(1, Uint8Array, 1)
40FUNCTION(2, Int8Array, 1)
41FUNCTION(3, Uint16Array, 2)
42FUNCTION(4, Int16Array, 2)
43FUNCTION(5, Uint32Array, 4)
44FUNCTION(6, Int32Array, 4)
45FUNCTION(7, Float32Array, 4)
46FUNCTION(8, Float64Array, 8)
47FUNCTION(9, Uint8ClampedArray, 1)
48endmacro
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000049
verwaest@chromium.org057bd502013-11-06 12:03:29 +000050macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000051 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
machenbach@chromium.org4452a492014-03-18 13:03:00 +000052 if (!IS_UNDEFINED(byteOffset)) {
53 byteOffset =
54 ToPositiveInteger(byteOffset, "invalid_typed_array_length");
55 }
56 if (!IS_UNDEFINED(length)) {
57 length = ToPositiveInteger(length, "invalid_typed_array_length");
58 }
59
machenbach@chromium.org2f599e52014-03-31 14:24:38 +000060 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000061 var offset;
62 if (IS_UNDEFINED(byteOffset)) {
63 offset = 0;
64 } else {
machenbach@chromium.org4452a492014-03-18 13:03:00 +000065 offset = byteOffset;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000066
verwaest@chromium.org057bd502013-11-06 12:03:29 +000067 if (offset % ELEMENT_SIZE !== 0) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000068 throw MakeRangeError("invalid_typed_array_alignment",
titzer@chromium.orgf5a24542014-03-04 09:06:17 +000069 ["start offset", "NAME", ELEMENT_SIZE]);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000070 }
verwaest@chromium.org057bd502013-11-06 12:03:29 +000071 if (offset > bufferByteLength) {
72 throw MakeRangeError("invalid_typed_array_offset");
73 }
verwaest@chromium.org057bd502013-11-06 12:03:29 +000074 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +000075
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000076 var newByteLength;
77 var newLength;
78 if (IS_UNDEFINED(length)) {
79 if (bufferByteLength % ELEMENT_SIZE !== 0) {
80 throw MakeRangeError("invalid_typed_array_alignment",
titzer@chromium.orgf5a24542014-03-04 09:06:17 +000081 ["byte length", "NAME", ELEMENT_SIZE]);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000082 }
83 newByteLength = bufferByteLength - offset;
84 newLength = newByteLength / ELEMENT_SIZE;
85 } else {
machenbach@chromium.org4452a492014-03-18 13:03:00 +000086 var newLength = length;
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000087 newByteLength = newLength * ELEMENT_SIZE;
verwaest@chromium.org057bd502013-11-06 12:03:29 +000088 }
machenbach@chromium.org37be4082013-11-26 13:50:38 +000089 if ((offset + newByteLength > bufferByteLength)
machenbach@chromium.orga2218802014-03-25 07:30:47 +000090 || (newLength > %_MaxSmi())) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000091 throw MakeRangeError("invalid_typed_array_length");
92 }
machenbach@chromium.orga2218802014-03-25 07:30:47 +000093 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000094 }
verwaest@chromium.org057bd502013-11-06 12:03:29 +000095
machenbach@chromium.orge8412be2013-11-08 10:23:52 +000096 function NAMEConstructByLength(obj, length) {
97 var l = IS_UNDEFINED(length) ?
98 0 : ToPositiveInteger(length, "invalid_typed_array_length");
machenbach@chromium.orga2218802014-03-25 07:30:47 +000099 if (l > %_MaxSmi()) {
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000100 throw MakeRangeError("invalid_typed_array_length");
101 }
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000102 var byteLength = l * ELEMENT_SIZE;
machenbach@chromium.org895f00d2014-03-27 01:04:43 +0000103 if (byteLength > %_TypedArrayMaxSizeInHeap()) {
104 var buffer = new $ArrayBuffer(byteLength);
105 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength);
106 } else {
107 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength);
108 }
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000109 }
110
111 function NAMEConstructByArrayLike(obj, arrayLike) {
112 var length = arrayLike.length;
113 var l = ToPositiveInteger(length, "invalid_typed_array_length");
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000114
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000115 if (l > %_MaxSmi()) {
yangguo@chromium.orgcc536052013-11-29 11:43:20 +0000116 throw MakeRangeError("invalid_typed_array_length");
117 }
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000118 if(!%TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l)) {
119 for (var i = 0; i < l; i++) {
120 // It is crucial that we let any execptions from arrayLike[i]
121 // propagate outside the function.
122 obj[i] = arrayLike[i];
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000123 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000124 }
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000125 }
126
127 function NAMEConstructor(arg1, arg2, arg3) {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000128 if (%_IsConstructCall()) {
129 if (IS_ARRAYBUFFER(arg1)) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000130 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000131 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
132 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000133 NAMEConstructByLength(this, arg1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000134 } else {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000135 NAMEConstructByArrayLike(this, arg1);
danno@chromium.orgf005df62013-04-30 16:36:45 +0000136 }
137 } else {
verwaest@chromium.org057bd502013-11-06 12:03:29 +0000138 throw MakeTypeError("constructor_not_function", ["NAME"])
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000139 }
140 }
verwaest@chromium.org057bd502013-11-06 12:03:29 +0000141
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000142 function NAME_GetBuffer() {
143 if (!(%_ClassOf(this) === 'NAME')) {
144 throw MakeTypeError('incompatible_method_receiver',
145 ["NAME.buffer", this]);
146 }
147 return %TypedArrayGetBuffer(this);
148 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000149
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000150 function NAME_GetByteLength() {
151 if (!(%_ClassOf(this) === 'NAME')) {
152 throw MakeTypeError('incompatible_method_receiver',
153 ["NAME.byteLength", this]);
154 }
155 return %_ArrayBufferViewGetByteLength(this);
156 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000157
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000158 function NAME_GetByteOffset() {
159 if (!(%_ClassOf(this) === 'NAME')) {
160 throw MakeTypeError('incompatible_method_receiver',
161 ["NAME.byteOffset", this]);
162 }
163 return %_ArrayBufferViewGetByteOffset(this);
164 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000165
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000166 function NAME_GetLength() {
167 if (!(%_ClassOf(this) === 'NAME')) {
168 throw MakeTypeError('incompatible_method_receiver',
169 ["NAME.length", this]);
170 }
171 return %_TypedArrayGetLength(this);
172 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000173
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000174 var $NAME = global.NAME;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000175
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000176 function NAMESubArray(begin, end) {
177 if (!(%_ClassOf(this) === 'NAME')) {
178 throw MakeTypeError('incompatible_method_receiver',
179 ["NAME.subarray", this]);
180 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000181 var beginInt = TO_INTEGER(begin);
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000182 if (!IS_UNDEFINED(end)) {
183 end = TO_INTEGER(end);
184 }
185
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000186 var srcLength = %_TypedArrayGetLength(this);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000187 if (beginInt < 0) {
188 beginInt = MathMax(0, srcLength + beginInt);
189 } else {
190 beginInt = MathMin(srcLength, beginInt);
191 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000192
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000193 var endInt = IS_UNDEFINED(end) ? srcLength : end;
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000194 if (endInt < 0) {
195 endInt = MathMax(0, srcLength + endInt);
196 } else {
197 endInt = MathMin(endInt, srcLength);
198 }
199 if (endInt < beginInt) {
200 endInt = beginInt;
201 }
202 var newLength = endInt - beginInt;
203 var beginByteOffset =
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000204 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
205 return new $NAME(%TypedArrayGetBuffer(this),
206 beginByteOffset, newLength);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000207 }
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000208endmacro
209
210TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
211
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000212
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000213function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
214 if (offset > 0) {
215 for (var i = 0; i < sourceLength; i++) {
216 target[offset + i] = source[i];
217 }
218 }
219 else {
220 for (var i = 0; i < sourceLength; i++) {
221 target[i] = source[i];
222 }
223 }
224}
225
226function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
227 var sourceElementSize = source.BYTES_PER_ELEMENT;
228 var targetElementSize = target.BYTES_PER_ELEMENT;
229 var sourceLength = source.length;
230
231 // Copy left part.
232 function CopyLeftPart() {
233 // First un-mutated byte after the next write
234 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
235 // Next read at sourcePtr. We do not care for memory changing before
236 // sourcePtr - we have already copied it.
237 var sourcePtr = source.byteOffset;
238 for (var leftIndex = 0;
239 leftIndex < sourceLength && targetPtr <= sourcePtr;
240 leftIndex++) {
241 target[offset + leftIndex] = source[leftIndex];
242 targetPtr += targetElementSize;
243 sourcePtr += sourceElementSize;
244 }
245 return leftIndex;
246 }
247 var leftIndex = CopyLeftPart();
248
249 // Copy rigth part;
250 function CopyRightPart() {
251 // First unmutated byte before the next write
252 var targetPtr =
253 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
254 // Next read before sourcePtr. We do not care for memory changing after
255 // sourcePtr - we have already copied it.
256 var sourcePtr =
257 source.byteOffset + sourceLength * sourceElementSize;
258 for(var rightIndex = sourceLength - 1;
259 rightIndex >= leftIndex && targetPtr >= sourcePtr;
260 rightIndex--) {
261 target[offset + rightIndex] = source[rightIndex];
262 targetPtr -= targetElementSize;
263 sourcePtr -= sourceElementSize;
264 }
265 return rightIndex;
266 }
267 var rightIndex = CopyRightPart();
268
269 var temp = new $Array(rightIndex + 1 - leftIndex);
270 for (var i = leftIndex; i <= rightIndex; i++) {
271 temp[i - leftIndex] = source[i];
272 }
273 for (i = leftIndex; i <= rightIndex; i++) {
274 target[offset + i] = temp[i - leftIndex];
275 }
276}
277
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000278function TypedArraySet(obj, offset) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000279 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
280 if (intOffset < 0) {
281 throw MakeTypeError("typed_array_set_negative_offset");
282 }
machenbach@chromium.org0a730362014-02-05 03:04:56 +0000283
machenbach@chromium.org9b95fd72014-03-26 01:04:35 +0000284 if (intOffset > %_MaxSmi()) {
machenbach@chromium.org0a730362014-02-05 03:04:56 +0000285 throw MakeRangeError("typed_array_set_source_too_large");
286 }
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000287 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
288 // These numbers should be synchronized with runtime.cc.
289 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
290 return;
291 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
292 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
293 return;
294 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
295 TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
296 return;
297 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
298 var l = obj.length;
299 if (IS_UNDEFINED(l)) {
300 if (IS_NUMBER(obj)) {
301 // For number as a first argument, throw TypeError
302 // instead of silently ignoring the call, so that
303 // the user knows (s)he did something wrong.
304 // (Consistent with Firefox and Blink/WebKit)
305 throw MakeTypeError("invalid_argument");
306 }
307 return;
308 }
309 if (intOffset + l > this.length) {
310 throw MakeRangeError("typed_array_set_source_too_large");
311 }
312 TypedArraySetFromArrayLike(this, obj, l, intOffset);
313 return;
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000314 }
315}
316
317// -------------------------------------------------------------------
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000318
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000319function SetupTypedArrays() {
320macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
danno@chromium.orgf005df62013-04-30 16:36:45 +0000321 %CheckIsBootstrapping();
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000322 %SetCode(global.NAME, NAMEConstructor);
323 %FunctionSetPrototype(global.NAME, new $Object());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000324
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000325 %SetProperty(global.NAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000326 READ_ONLY | DONT_ENUM | DONT_DELETE);
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000327 %SetProperty(global.NAME.prototype,
328 "constructor", global.NAME, DONT_ENUM);
329 %SetProperty(global.NAME.prototype,
330 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000331 READ_ONLY | DONT_ENUM | DONT_DELETE);
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000332 InstallGetter(global.NAME.prototype, "buffer", NAME_GetBuffer);
333 InstallGetter(global.NAME.prototype, "byteOffset", NAME_GetByteOffset);
334 InstallGetter(global.NAME.prototype, "byteLength", NAME_GetByteLength);
335 InstallGetter(global.NAME.prototype, "length", NAME_GetLength);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000336
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000337 InstallFunctions(global.NAME.prototype, DONT_ENUM, $Array(
338 "subarray", NAMESubArray,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000339 "set", TypedArraySet
340 ));
verwaest@chromium.org057bd502013-11-06 12:03:29 +0000341endmacro
342
343TYPED_ARRAYS(SETUP_TYPED_ARRAY)
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000344}
345
346SetupTypedArrays();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000347
348// --------------------------- DataView -----------------------------
349
350var $DataView = global.DataView;
351
352function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3
353 if (%_IsConstructCall()) {
354 if (!IS_ARRAYBUFFER(buffer)) {
355 throw MakeTypeError('data_view_not_array_buffer', []);
356 }
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000357 if (!IS_UNDEFINED(byteOffset)) {
358 byteOffset = ToPositiveInteger(byteOffset, 'invalid_data_view_offset');
359 }
360 if (!IS_UNDEFINED(byteLength)) {
361 byteLength = TO_INTEGER(byteLength);
362 }
363
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000364 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000365
366 var offset = IS_UNDEFINED(byteOffset) ? 0 : byteOffset;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000367 if (offset > bufferByteLength) {
368 throw MakeRangeError('invalid_data_view_offset');
369 }
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000370
371 var length = IS_UNDEFINED(byteLength)
372 ? bufferByteLength - offset
373 : byteLength;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000374 if (length < 0 || offset + length > bufferByteLength) {
375 throw new MakeRangeError('invalid_data_view_length');
376 }
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000377 %_DataViewInitialize(this, buffer, offset, length);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000378 } else {
379 throw MakeTypeError('constructor_not_function', ["DataView"]);
380 }
381}
382
383function DataViewGetBuffer() {
384 if (!IS_DATAVIEW(this)) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000385 throw MakeTypeError('incompatible_method_receiver',
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000386 ['DataView.buffer', this]);
387 }
388 return %DataViewGetBuffer(this);
389}
390
391function DataViewGetByteOffset() {
392 if (!IS_DATAVIEW(this)) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000393 throw MakeTypeError('incompatible_method_receiver',
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000394 ['DataView.byteOffset', this]);
395 }
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000396 return %_ArrayBufferViewGetByteOffset(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000397}
398
399function DataViewGetByteLength() {
400 if (!IS_DATAVIEW(this)) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000401 throw MakeTypeError('incompatible_method_receiver',
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000402 ['DataView.byteLength', this]);
403 }
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000404 return %_ArrayBufferViewGetByteLength(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000405}
406
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000407macro DATA_VIEW_TYPES(FUNCTION)
408 FUNCTION(Int8)
409 FUNCTION(Uint8)
410 FUNCTION(Int16)
411 FUNCTION(Uint16)
412 FUNCTION(Int32)
413 FUNCTION(Uint32)
414 FUNCTION(Float32)
415 FUNCTION(Float64)
416endmacro
417
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000418function ToPositiveDataViewOffset(offset) {
419 return ToPositiveInteger(offset, 'invalid_data_view_accessor_offset');
420}
421
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000422
423macro DATA_VIEW_GETTER_SETTER(TYPENAME)
424function DataViewGetTYPENAME(offset, little_endian) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000425 if (!IS_DATAVIEW(this)) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000426 throw MakeTypeError('incompatible_method_receiver',
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000427 ['DataView.getTYPENAME', this]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000428 }
danno@chromium.org169691d2013-07-15 08:01:13 +0000429 if (%_ArgumentsLength() < 1) {
430 throw MakeTypeError('invalid_argument');
431 }
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000432 return %DataViewGetTYPENAME(this,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000433 ToPositiveDataViewOffset(offset),
434 !!little_endian);
435}
436
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000437function DataViewSetTYPENAME(offset, value, little_endian) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000438 if (!IS_DATAVIEW(this)) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000439 throw MakeTypeError('incompatible_method_receiver',
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000440 ['DataView.setTYPENAME', this]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000441 }
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000442 if (%_ArgumentsLength() < 2) {
danno@chromium.org169691d2013-07-15 08:01:13 +0000443 throw MakeTypeError('invalid_argument');
444 }
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000445 %DataViewSetTYPENAME(this,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000446 ToPositiveDataViewOffset(offset),
447 TO_NUMBER_INLINE(value),
448 !!little_endian);
449}
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000450endmacro
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000451
machenbach@chromium.orgfeecfde2013-11-14 10:55:00 +0000452DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000453
454function SetupDataView() {
455 %CheckIsBootstrapping();
456
457 // Setup the DataView constructor.
458 %SetCode($DataView, DataViewConstructor);
459 %FunctionSetPrototype($DataView, new $Object);
460
461 // Set up constructor property on the DataView prototype.
462 %SetProperty($DataView.prototype, "constructor", $DataView, DONT_ENUM);
463
464 InstallGetter($DataView.prototype, "buffer", DataViewGetBuffer);
465 InstallGetter($DataView.prototype, "byteOffset", DataViewGetByteOffset);
466 InstallGetter($DataView.prototype, "byteLength", DataViewGetByteLength);
467
468 InstallFunctions($DataView.prototype, DONT_ENUM, $Array(
469 "getInt8", DataViewGetInt8,
470 "setInt8", DataViewSetInt8,
471
472 "getUint8", DataViewGetUint8,
473 "setUint8", DataViewSetUint8,
474
475 "getInt16", DataViewGetInt16,
476 "setInt16", DataViewSetInt16,
477
478 "getUint16", DataViewGetUint16,
479 "setUint16", DataViewSetUint16,
480
481 "getInt32", DataViewGetInt32,
482 "setInt32", DataViewSetInt32,
483
484 "getUint32", DataViewGetUint32,
485 "setUint32", DataViewSetUint32,
486
487 "getFloat32", DataViewGetFloat32,
488 "setFloat32", DataViewSetFloat32,
489
490 "getFloat64", DataViewGetFloat64,
491 "setFloat64", DataViewSetFloat64
492 ));
493}
494
495SetupDataView();