UNPKG

11.4 kBJavaScriptView Raw
1'use strict';
2var global = require('../internals/global');
3var DESCRIPTORS = require('../internals/descriptors');
4var NATIVE_ARRAY_BUFFER = require('../internals/array-buffer-view-core').NATIVE_ARRAY_BUFFER;
5var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
6var redefineAll = require('../internals/redefine-all');
7var fails = require('../internals/fails');
8var anInstance = require('../internals/an-instance');
9var toInteger = require('../internals/to-integer');
10var toLength = require('../internals/to-length');
11var toIndex = require('../internals/to-index');
12var getOwnPropertyNames = require('../internals/object-get-own-property-names').f;
13var defineProperty = require('../internals/object-define-property').f;
14var arrayFill = require('../internals/array-fill');
15var setToStringTag = require('../internals/set-to-string-tag');
16var InternalStateModule = require('../internals/internal-state');
17
18var getInternalState = InternalStateModule.get;
19var setInternalState = InternalStateModule.set;
20var ARRAY_BUFFER = 'ArrayBuffer';
21var DATA_VIEW = 'DataView';
22var PROTOTYPE = 'prototype';
23var WRONG_LENGTH = 'Wrong length';
24var WRONG_INDEX = 'Wrong index';
25var NativeArrayBuffer = global[ARRAY_BUFFER];
26var $ArrayBuffer = NativeArrayBuffer;
27var $DataView = global[DATA_VIEW];
28var Math = global.Math;
29var RangeError = global.RangeError;
30// eslint-disable-next-line no-shadow-restricted-names
31var Infinity = 1 / 0;
32var abs = Math.abs;
33var pow = Math.pow;
34var floor = Math.floor;
35var log = Math.log;
36var LN2 = Math.LN2;
37
38// IEEE754 conversions based on https://github.com/feross/ieee754
39var packIEEE754 = function (number, mantissaLength, bytes) {
40 var buffer = new Array(bytes);
41 var exponentLength = bytes * 8 - mantissaLength - 1;
42 var eMax = (1 << exponentLength) - 1;
43 var eBias = eMax >> 1;
44 var rt = mantissaLength === 23 ? pow(2, -24) - pow(2, -77) : 0;
45 var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
46 var index = 0;
47 var exponent, mantissa, c;
48 number = abs(number);
49 // eslint-disable-next-line no-self-compare
50 if (number != number || number === Infinity) {
51 // eslint-disable-next-line no-self-compare
52 mantissa = number != number ? 1 : 0;
53 exponent = eMax;
54 } else {
55 exponent = floor(log(number) / LN2);
56 if (number * (c = pow(2, -exponent)) < 1) {
57 exponent--;
58 c *= 2;
59 }
60 if (exponent + eBias >= 1) {
61 number += rt / c;
62 } else {
63 number += rt * pow(2, 1 - eBias);
64 }
65 if (number * c >= 2) {
66 exponent++;
67 c /= 2;
68 }
69 if (exponent + eBias >= eMax) {
70 mantissa = 0;
71 exponent = eMax;
72 } else if (exponent + eBias >= 1) {
73 mantissa = (number * c - 1) * pow(2, mantissaLength);
74 exponent = exponent + eBias;
75 } else {
76 mantissa = number * pow(2, eBias - 1) * pow(2, mantissaLength);
77 exponent = 0;
78 }
79 }
80 for (; mantissaLength >= 8; buffer[index++] = mantissa & 255, mantissa /= 256, mantissaLength -= 8);
81 exponent = exponent << mantissaLength | mantissa;
82 exponentLength += mantissaLength;
83 for (; exponentLength > 0; buffer[index++] = exponent & 255, exponent /= 256, exponentLength -= 8);
84 buffer[--index] |= sign * 128;
85 return buffer;
86};
87
88var unpackIEEE754 = function (buffer, mantissaLength) {
89 var bytes = buffer.length;
90 var exponentLength = bytes * 8 - mantissaLength - 1;
91 var eMax = (1 << exponentLength) - 1;
92 var eBias = eMax >> 1;
93 var nBits = exponentLength - 7;
94 var index = bytes - 1;
95 var sign = buffer[index--];
96 var exponent = sign & 127;
97 var mantissa;
98 sign >>= 7;
99 for (; nBits > 0; exponent = exponent * 256 + buffer[index], index--, nBits -= 8);
100 mantissa = exponent & (1 << -nBits) - 1;
101 exponent >>= -nBits;
102 nBits += mantissaLength;
103 for (; nBits > 0; mantissa = mantissa * 256 + buffer[index], index--, nBits -= 8);
104 if (exponent === 0) {
105 exponent = 1 - eBias;
106 } else if (exponent === eMax) {
107 return mantissa ? NaN : sign ? -Infinity : Infinity;
108 } else {
109 mantissa = mantissa + pow(2, mantissaLength);
110 exponent = exponent - eBias;
111 } return (sign ? -1 : 1) * mantissa * pow(2, exponent - mantissaLength);
112};
113
114var unpackInt32 = function (buffer) {
115 return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
116};
117
118var packInt8 = function (number) {
119 return [number & 0xFF];
120};
121
122var packInt16 = function (number) {
123 return [number & 0xFF, number >> 8 & 0xFF];
124};
125
126var packInt32 = function (number) {
127 return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
128};
129
130var packFloat32 = function (number) {
131 return packIEEE754(number, 23, 4);
132};
133
134var packFloat64 = function (number) {
135 return packIEEE754(number, 52, 8);
136};
137
138var addGetter = function (Constructor, key) {
139 defineProperty(Constructor[PROTOTYPE], key, { get: function () { return getInternalState(this)[key]; } });
140};
141
142var get = function (view, count, index, isLittleEndian) {
143 var numIndex = +index;
144 var intIndex = toIndex(numIndex);
145 var store = getInternalState(view);
146 if (intIndex + count > store.byteLength) throw RangeError(WRONG_INDEX);
147 var bytes = getInternalState(store.buffer).bytes;
148 var start = intIndex + store.byteOffset;
149 var pack = bytes.slice(start, start + count);
150 return isLittleEndian ? pack : pack.reverse();
151};
152
153var set = function (view, count, index, conversion, value, isLittleEndian) {
154 var numIndex = +index;
155 var intIndex = toIndex(numIndex);
156 var store = getInternalState(view);
157 if (intIndex + count > store.byteLength) throw RangeError(WRONG_INDEX);
158 var bytes = getInternalState(store.buffer).bytes;
159 var start = intIndex + store.byteOffset;
160 var pack = conversion(+value);
161 for (var i = 0; i < count; i++) bytes[start + i] = pack[isLittleEndian ? i : count - i - 1];
162};
163
164if (!NATIVE_ARRAY_BUFFER) {
165 $ArrayBuffer = function ArrayBuffer(length) {
166 anInstance(this, $ArrayBuffer, ARRAY_BUFFER);
167 var byteLength = toIndex(length);
168 setInternalState(this, {
169 bytes: arrayFill.call(new Array(byteLength), 0),
170 byteLength: byteLength
171 });
172 if (!DESCRIPTORS) this.byteLength = byteLength;
173 };
174
175 $DataView = function DataView(buffer, byteOffset, byteLength) {
176 anInstance(this, $DataView, DATA_VIEW);
177 anInstance(buffer, $ArrayBuffer, DATA_VIEW);
178 var bufferLength = getInternalState(buffer).byteLength;
179 var offset = toInteger(byteOffset);
180 if (offset < 0 || offset > bufferLength) throw RangeError('Wrong offset');
181 byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);
182 if (offset + byteLength > bufferLength) throw RangeError(WRONG_LENGTH);
183 setInternalState(this, {
184 buffer: buffer,
185 byteLength: byteLength,
186 byteOffset: offset
187 });
188 if (!DESCRIPTORS) {
189 this.buffer = buffer;
190 this.byteLength = byteLength;
191 this.byteOffset = offset;
192 }
193 };
194
195 if (DESCRIPTORS) {
196 addGetter($ArrayBuffer, 'byteLength');
197 addGetter($DataView, 'buffer');
198 addGetter($DataView, 'byteLength');
199 addGetter($DataView, 'byteOffset');
200 }
201
202 redefineAll($DataView[PROTOTYPE], {
203 getInt8: function getInt8(byteOffset) {
204 return get(this, 1, byteOffset)[0] << 24 >> 24;
205 },
206 getUint8: function getUint8(byteOffset) {
207 return get(this, 1, byteOffset)[0];
208 },
209 getInt16: function getInt16(byteOffset /* , littleEndian */) {
210 var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
211 return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
212 },
213 getUint16: function getUint16(byteOffset /* , littleEndian */) {
214 var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
215 return bytes[1] << 8 | bytes[0];
216 },
217 getInt32: function getInt32(byteOffset /* , littleEndian */) {
218 return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined));
219 },
220 getUint32: function getUint32(byteOffset /* , littleEndian */) {
221 return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined)) >>> 0;
222 },
223 getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
224 return unpackIEEE754(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 23);
225 },
226 getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
227 return unpackIEEE754(get(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 52);
228 },
229 setInt8: function setInt8(byteOffset, value) {
230 set(this, 1, byteOffset, packInt8, value);
231 },
232 setUint8: function setUint8(byteOffset, value) {
233 set(this, 1, byteOffset, packInt8, value);
234 },
235 setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
236 set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
237 },
238 setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
239 set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
240 },
241 setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
242 set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
243 },
244 setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
245 set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
246 },
247 setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
248 set(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : undefined);
249 },
250 setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
251 set(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : undefined);
252 }
253 });
254} else {
255 if (!fails(function () {
256 NativeArrayBuffer(1);
257 }) || !fails(function () {
258 new NativeArrayBuffer(-1); // eslint-disable-line no-new
259 }) || fails(function () {
260 new NativeArrayBuffer(); // eslint-disable-line no-new
261 new NativeArrayBuffer(1.5); // eslint-disable-line no-new
262 new NativeArrayBuffer(NaN); // eslint-disable-line no-new
263 return NativeArrayBuffer.name != ARRAY_BUFFER;
264 })) {
265 $ArrayBuffer = function ArrayBuffer(length) {
266 anInstance(this, $ArrayBuffer);
267 return new NativeArrayBuffer(toIndex(length));
268 };
269 var ArrayBufferPrototype = $ArrayBuffer[PROTOTYPE] = NativeArrayBuffer[PROTOTYPE];
270 for (var keys = getOwnPropertyNames(NativeArrayBuffer), j = 0, key; keys.length > j;) {
271 if (!((key = keys[j++]) in $ArrayBuffer)) {
272 createNonEnumerableProperty($ArrayBuffer, key, NativeArrayBuffer[key]);
273 }
274 }
275 ArrayBufferPrototype.constructor = $ArrayBuffer;
276 }
277 // iOS Safari 7.x bug
278 var testView = new $DataView(new $ArrayBuffer(2));
279 var nativeSetInt8 = $DataView[PROTOTYPE].setInt8;
280 testView.setInt8(0, 2147483648);
281 testView.setInt8(1, 2147483649);
282 if (testView.getInt8(0) || !testView.getInt8(1)) redefineAll($DataView[PROTOTYPE], {
283 setInt8: function setInt8(byteOffset, value) {
284 nativeSetInt8.call(this, byteOffset, value << 24 >> 24);
285 },
286 setUint8: function setUint8(byteOffset, value) {
287 nativeSetInt8.call(this, byteOffset, value << 24 >> 24);
288 }
289 }, { unsafe: true });
290}
291
292setToStringTag($ArrayBuffer, ARRAY_BUFFER);
293setToStringTag($DataView, DATA_VIEW);
294
295module.exports = {
296 ArrayBuffer: $ArrayBuffer,
297 DataView: $DataView
298};