Coverage Report

Created: 2026-10-17 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsDataView.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2026  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#include "xsAll.h"
39
40
static txSlot* fxArgToInstance(txMachine* the, txInteger i);
41
42
static txSlot* fxCheckArrayBufferDetached(txMachine* the, txSlot* slot);
43
static txSlot* fxCheckArrayBufferInstance(txMachine* the, txSlot* slot);
44
static txSlot* fxCheckArrayBufferMutable(txMachine* the, txSlot* slot);
45
static txSlot* fxNewArrayBufferInstance(txMachine* the);
46
47
static txSlot* fxCheckDataViewInstance(txMachine* the, txSlot* slot, txBoolean mutable);
48
static txInteger fxCheckDataViewSize(txMachine* the, txSlot* view, txSlot* buffer, txBoolean mutable);
49
static txSlot* fxNewDataViewInstance(txMachine* the);
50
51
static void fxCallTypedArrayItem(txMachine* the, txSlot* function, txSlot* dispatch, txSlot* view, txSlot* data, txInteger index, txSlot* item);
52
static void fxCheckTypedArrayContentType(txMachine* the, txSlot* dispatch, txSlot* sourceDispatch);
53
static txSlot* fxCheckTypedArrayInstance(txMachine* the, txSlot* slot);
54
static txSlot* fxConstructTypedArray(txMachine* the);
55
static txSlot* fxNewTypedArrayInstance(txMachine* the, txTypeDispatch* dispatch, txTypeAtomics* atomics);
56
static void fxReduceTypedArrayItem(txMachine* the, txSlot* function, txSlot* dispatch, txSlot* view, txSlot* data, txInteger index);
57
58
static txBoolean fxTypedArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask);
59
static txBoolean fxTypedArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
60
static txBoolean fxTypedArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot);
61
static txSlot* fxTypedArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
62
static txBoolean fxTypedArrayGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver);
63
static txBoolean fxTypedArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
64
static void fxTypedArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys);
65
static txBoolean fxTypedArrayPreventExtensions(txMachine* the, txSlot* instance);
66
static txSlot* fxTypedArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
67
static txBoolean fxTypedArraySetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver);
68
69
static void fx_TypedArray_from_object(txMachine* the, txSlot* instance, txSlot* function, txSlot* _this);
70
71
const txBehavior ICACHE_FLASH_ATTR gxTypedArrayBehavior = {
72
  fxTypedArrayGetProperty,
73
  fxTypedArraySetProperty,
74
  fxOrdinaryCall,
75
  fxOrdinaryConstruct,
76
  fxTypedArrayDefineOwnProperty,
77
  fxTypedArrayDeleteProperty,
78
  fxTypedArrayGetOwnProperty,
79
  fxTypedArrayGetPropertyValue,
80
  fxOrdinaryGetPrototype,
81
  fxTypedArrayHasProperty,
82
  fxOrdinaryIsExtensible,
83
  fxTypedArrayOwnKeys,
84
  fxTypedArrayPreventExtensions,
85
  fxTypedArraySetPropertyValue,
86
  fxOrdinarySetPrototype,
87
};
88
89
void *fxArrayBuffer(txMachine* the, txSlot* slot, void* data, txInteger byteLength, txInteger maxByteLength)
90
1.40M
{
91
1.40M
  txSlot* instance;
92
1.40M
  txSlot* arrayBuffer;
93
1.40M
  txSlot* bufferInfo;
94
1.40M
  if (byteLength < 0)
95
0
    mxRangeError("invalid byteLength %ld", byteLength);
96
1.40M
  mxPush(mxArrayBufferPrototype);
97
1.40M
  instance = fxNewArrayBufferInstance(the);
98
1.40M
  arrayBuffer = instance->next;
99
1.40M
  arrayBuffer->value.arrayBuffer.address = fxNewChunk(the, byteLength);
100
1.40M
  bufferInfo = arrayBuffer->next;
101
1.40M
  bufferInfo->value.bufferInfo.length = byteLength;
102
1.40M
  bufferInfo->value.bufferInfo.maxLength = maxByteLength;
103
1.40M
  if (data != NULL)
104
38.0k
    c_memcpy(arrayBuffer->value.arrayBuffer.address, data, byteLength);
105
1.37M
  else
106
1.37M
    c_memset(arrayBuffer->value.arrayBuffer.address, 0, byteLength);
107
1.40M
  mxPullSlot(slot);
108
1.40M
  return arrayBuffer->value.arrayBuffer.address;
109
1.40M
}
110
111
void fxGetArrayBufferData(txMachine* the, txSlot* slot, txInteger byteOffset, void* data, txInteger byteLength)
112
0
{
113
0
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
114
0
  txSlot* arrayBuffer = instance->next;
115
0
  txSlot* bufferInfo = arrayBuffer->next;
116
0
  txInteger length = bufferInfo->value.bufferInfo.length;
117
0
  if ((byteOffset < 0) || (length < byteOffset))
118
0
    mxRangeError("invalid byteOffset %ld", byteOffset);
119
0
  if ((byteLength < 0) || (length < (byteOffset + byteLength)))
120
0
    mxRangeError("invalid byteLength %ld", byteLength);
121
0
  c_memcpy(data, arrayBuffer->value.arrayBuffer.address + byteOffset, byteLength);
122
0
}
123
124
txInteger fxGetArrayBufferLength(txMachine* the, txSlot* slot)
125
50.8M
{
126
50.8M
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
127
50.8M
  txSlot* arrayBuffer = instance->next;
128
50.8M
  txSlot* bufferInfo = arrayBuffer->next;
129
50.8M
  return bufferInfo->value.bufferInfo.length;
130
50.8M
}
131
132
txInteger fxGetArrayBufferMaxLength(txMachine* the, txSlot* slot)
133
0
{
134
0
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
135
0
  txSlot* arrayBuffer = instance->next;
136
0
  txSlot* bufferInfo = arrayBuffer->next;
137
0
  return bufferInfo->value.bufferInfo.maxLength;
138
0
}
139
140
void fxSetArrayBufferData(txMachine* the, txSlot* slot, txInteger byteOffset, void* data, txInteger byteLength)
141
0
{
142
0
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
143
0
  txSlot* arrayBuffer = instance->next;
144
0
  txSlot* bufferInfo = arrayBuffer->next;
145
0
  txInteger length = bufferInfo->value.bufferInfo.length;
146
0
  if ((byteOffset < 0) || (length < byteOffset))
147
0
    mxRangeError("invalid byteOffset %ld", byteOffset);
148
0
  if ((byteLength < 0) || (length < (byteOffset + byteLength)))
149
0
    mxRangeError("invalid byteLength %ld", byteLength);
150
0
  c_memcpy(arrayBuffer->value.arrayBuffer.address + byteOffset, data, byteLength);
151
0
}
152
153
void fxSetArrayBufferLength(txMachine* the, txSlot* slot, txInteger target)
154
2.56M
{
155
2.56M
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
156
2.56M
  txSlot* arrayBuffer = instance->next;
157
2.56M
  txSlot* bufferInfo = arrayBuffer->next;
158
2.56M
  txInteger length = bufferInfo->value.bufferInfo.length;
159
2.56M
  txByte* address = arrayBuffer->value.arrayBuffer.address;
160
2.56M
  if (bufferInfo->value.bufferInfo.maxLength < 0)
161
0
    fxReport(the, "# Use xsArrayBufferResizable instead of xsArrayBuffer\n");
162
2.56M
  if (length != target) {
163
2.56M
    if (address)
164
2.56M
      address = (txByte*)fxRenewChunk(the, address, target);
165
2.56M
    if (address) {
166
2.56M
      if (length < target)
167
2.55M
        c_memset(address + length, 0, target - length);
168
2.56M
    }
169
410
    else {
170
410
      address = (txByte*)fxNewChunk(the, target);
171
410
      if (length < target) {
172
410
        c_memcpy(address, arrayBuffer->value.arrayBuffer.address, length);
173
410
        c_memset(address + length, 0, target - length);
174
410
      }
175
0
      else
176
0
        c_memcpy(address, arrayBuffer->value.arrayBuffer.address, target);
177
410
    }
178
2.56M
    arrayBuffer->value.arrayBuffer.address = address;
179
2.56M
    bufferInfo->value.bufferInfo.length = target;
180
2.56M
  }
181
2.56M
}
182
183
void* fxToArrayBuffer(txMachine* the, txSlot* slot)
184
3.92M
{
185
3.92M
  txSlot* instance = fxCheckArrayBufferInstance(the, slot);
186
3.92M
  txSlot* arrayBuffer = instance->next;
187
3.92M
  return arrayBuffer->value.arrayBuffer.address;
188
3.92M
}
189
190
void fxBuildDataView(txMachine* the)
191
38.0k
{
192
38.0k
  txSlot* instance;
193
38.0k
    txSlot* slot;
194
38.0k
  txInteger index;
195
38.0k
  const txTypeDispatch *dispatch;
196
38.0k
  const txTypeAtomics *atomics;
197
38.0k
  txSlot* property;
198
38.0k
    txSlot* constructor;
199
  
200
38.0k
  mxPush(mxObjectPrototype);
201
38.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
202
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_get_byteLength), C_NULL, mxID(_byteLength), XS_DONT_ENUM_FLAG);
203
38.0k
#if mxECMAScript2023
204
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_get_detached), C_NULL, mxID(_detached), XS_DONT_ENUM_FLAG);
205
38.0k
#endif
206
38.0k
#if mxImmutableArrayBuffers
207
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_get_immutable), C_NULL, mxID(_immutable), XS_DONT_ENUM_FLAG);
208
38.0k
#endif
209
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_get_maxByteLength), C_NULL, mxID(_maxByteLength), XS_DONT_ENUM_FLAG);
210
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_get_resizable), C_NULL, mxID(_resizable), XS_DONT_ENUM_FLAG);
211
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_concat), 1, mxID(_concat), XS_DONT_ENUM_FLAG);
212
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_resize), 1, mxID(_resize), XS_DONT_ENUM_FLAG);
213
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_slice), 2, mxID(_slice), XS_DONT_ENUM_FLAG);
214
38.0k
#if mxImmutableArrayBuffers
215
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_sliceToImmutable), 2, mxID(_sliceToImmutable), XS_DONT_ENUM_FLAG);
216
38.0k
#endif
217
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_transfer), 0, mxID(_transfer), XS_DONT_ENUM_FLAG);
218
38.0k
#if mxECMAScript2024
219
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_transferToFixedLength), 0, mxID(_transferToFixedLength), XS_DONT_ENUM_FLAG);
220
38.0k
#endif
221
38.0k
#if mxImmutableArrayBuffers
222
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_prototype_transferToImmutable), 0, mxID(_transferToImmutable), XS_DONT_ENUM_FLAG);
223
38.0k
#endif
224
38.0k
  slot = fxNextStringXProperty(the, slot, "ArrayBuffer", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
225
38.0k
  mxArrayBufferPrototype = *the->stack;
226
38.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_ArrayBuffer), 1, mxID(_ArrayBuffer));
227
38.0k
  mxArrayBufferConstructor = *the->stack;
228
38.0k
  slot = fxLastProperty(the, slot);
229
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_fromBigInt), 1, mxID(_fromBigInt), XS_DONT_ENUM_FLAG);
230
#ifndef mxCESU8
231
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_fromString), 1, mxID(_fromString), XS_DONT_ENUM_FLAG);
232
#endif
233
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayBuffer_isView), 1, mxID(_isView), XS_DONT_ENUM_FLAG);
234
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
235
38.0k
  mxPop();
236
  
237
38.0k
  mxPush(mxObjectPrototype);
238
38.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
239
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getBigInt64), 1, mxID(_getBigInt64), XS_DONT_ENUM_FLAG);
240
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setBigInt64), 2, mxID(_setBigInt64), XS_DONT_ENUM_FLAG);
241
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getBigUint64), 1, mxID(_getBigUint64), XS_DONT_ENUM_FLAG);
242
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setBigUint64), 2, mxID(_setBigUint64), XS_DONT_ENUM_FLAG);
243
38.0k
#if mxFloat16
244
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getFloat16), 1, mxID(_getFloat16), XS_DONT_ENUM_FLAG);
245
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setFloat16), 2, mxID(_setFloat16), XS_DONT_ENUM_FLAG);
246
38.0k
#endif
247
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getFloat32), 1, mxID(_getFloat32), XS_DONT_ENUM_FLAG);
248
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setFloat32), 2, mxID(_setFloat32), XS_DONT_ENUM_FLAG);
249
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getFloat64), 1, mxID(_getFloat64), XS_DONT_ENUM_FLAG);
250
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setFloat64), 2, mxID(_setFloat64), XS_DONT_ENUM_FLAG);
251
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getInt8), 1, mxID(_getInt8), XS_DONT_ENUM_FLAG);
252
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setInt8), 2, mxID(_setInt8), XS_DONT_ENUM_FLAG);
253
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getInt16), 1, mxID(_getInt16), XS_DONT_ENUM_FLAG);
254
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setInt16), 2, mxID(_setInt16), XS_DONT_ENUM_FLAG);
255
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getInt32), 1, mxID(_getInt32), XS_DONT_ENUM_FLAG);
256
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setInt32), 2, mxID(_setInt32), XS_DONT_ENUM_FLAG);
257
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getUint8), 1, mxID(_getUint8), XS_DONT_ENUM_FLAG);
258
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setUint8), 2, mxID(_setUint8), XS_DONT_ENUM_FLAG);
259
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getUint16), 1, mxID(_getUint16), XS_DONT_ENUM_FLAG);
260
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setUint16), 2, mxID(_setUint16), XS_DONT_ENUM_FLAG);
261
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_getUint32), 1, mxID(_getUint32), XS_DONT_ENUM_FLAG);
262
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DataView_prototype_setUint32), 2, mxID(_setUint32), XS_DONT_ENUM_FLAG);
263
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DataView_prototype_buffer_get), C_NULL, mxID(_buffer), XS_DONT_ENUM_FLAG);
264
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DataView_prototype_byteLength_get), C_NULL, mxID(_byteLength), XS_DONT_ENUM_FLAG);
265
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DataView_prototype_byteOffset_get), C_NULL, mxID(_byteOffset), XS_DONT_ENUM_FLAG);
266
38.0k
  slot = fxNextStringXProperty(the, slot, "DataView", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
267
38.0k
  mxDataViewPrototype = *the->stack;
268
38.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DataView), 1, mxID(_DataView));
269
38.0k
  mxDataViewConstructor = *the->stack;
270
38.0k
  mxPop();
271
  
272
38.0k
  mxPush(mxObjectPrototype);
273
38.0k
  instance = fxNewObjectInstance(the);
274
  
275
38.0k
  fxNewHostFunction(the, mxCallback(fxTypedArrayGetter), 0, XS_NO_ID, XS_NO_ID);
276
38.0k
  property = mxFunctionInstanceHome(the->stack->value.reference);
277
38.0k
  property->value.home.object = instance;
278
38.0k
  fxNewHostFunction(the, mxCallback(fxTypedArraySetter), 1, XS_NO_ID, XS_NO_ID);
279
38.0k
  property = mxFunctionInstanceHome(the->stack->value.reference);
280
38.0k
  property->value.home.object = instance;
281
38.0k
  mxPushUndefined();
282
38.0k
  the->stack->flag = XS_DONT_DELETE_FLAG;
283
38.0k
  the->stack->kind = XS_ACCESSOR_KIND;
284
38.0k
  the->stack->value.accessor.getter = (the->stack + 2)->value.reference;
285
38.0k
  the->stack->value.accessor.setter = (the->stack + 1)->value.reference;
286
38.0k
  mxPull(mxTypedArrayAccessor);
287
38.0k
  mxPop();
288
38.0k
  mxPop();
289
  
290
38.0k
  slot = fxLastProperty(the, instance);
291
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_at), 1, mxID(_at), XS_DONT_ENUM_FLAG);
292
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_TypedArray_prototype_buffer_get), C_NULL, mxID(_buffer), XS_DONT_ENUM_FLAG);
293
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_TypedArray_prototype_byteLength_get), C_NULL, mxID(_byteLength), XS_DONT_ENUM_FLAG);
294
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_TypedArray_prototype_byteOffset_get), C_NULL, mxID(_byteOffset), XS_DONT_ENUM_FLAG);
295
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_TypedArray_prototype_length_get), C_NULL, mxID(_length), XS_DONT_ENUM_FLAG);
296
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_TypedArray_prototype_toStringTag_get), C_NULL, mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG);
297
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_copyWithin), 2, mxID(_copyWithin), XS_DONT_ENUM_FLAG);
298
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG);
299
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_every), 1, mxID(_every), XS_DONT_ENUM_FLAG);
300
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_fill), 1, mxID(_fill), XS_DONT_ENUM_FLAG);
301
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_filter), 1, mxID(_filter), XS_DONT_ENUM_FLAG);
302
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_find), 1, mxID(_find), XS_DONT_ENUM_FLAG);
303
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_findIndex), 1, mxID(_findIndex), XS_DONT_ENUM_FLAG);
304
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_findLast), 1, mxID(_findLast), XS_DONT_ENUM_FLAG);
305
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_findLastIndex), 1, mxID(_findLastIndex), XS_DONT_ENUM_FLAG);
306
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
307
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_includes), 1, mxID(_includes), XS_DONT_ENUM_FLAG);
308
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_indexOf), 1, mxID(_indexOf), XS_DONT_ENUM_FLAG);
309
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_join), 1, mxID(_join), XS_DONT_ENUM_FLAG);
310
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_keys), 0, mxID(_keys), XS_DONT_ENUM_FLAG);
311
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_lastIndexOf), 1, mxID(_lastIndexOf), XS_DONT_ENUM_FLAG);
312
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_map), 1, mxID(_map), XS_DONT_ENUM_FLAG);
313
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_reduce), 1, mxID(_reduce), XS_DONT_ENUM_FLAG);
314
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_reduceRight), 1, mxID(_reduceRight), XS_DONT_ENUM_FLAG);
315
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_reverse), 0, mxID(_reverse), XS_DONT_ENUM_FLAG);
316
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_set), 1, mxID(_set), XS_DONT_ENUM_FLAG);
317
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_slice), 2, mxID(_slice), XS_DONT_ENUM_FLAG);
318
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_some), 1, mxID(_some), XS_DONT_ENUM_FLAG);
319
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_sort), 1, mxID(_sort), XS_DONT_ENUM_FLAG);
320
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_subarray), 2, mxID(_subarray), XS_DONT_ENUM_FLAG);
321
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
322
38.0k
  property = mxBehaviorGetProperty(the, mxArrayPrototype.value.reference, mxID(_toString), 0, XS_OWN);
323
38.0k
  slot = fxNextSlotProperty(the, slot, property, mxID(_toString), XS_DONT_ENUM_FLAG);
324
38.0k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG);
325
38.0k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
326
38.0k
#if mxECMAScript2023
327
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_toReversed), 0, mxID(_toReversed), XS_DONT_ENUM_FLAG);
328
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_toSorted), 1, mxID(_toSorted), XS_DONT_ENUM_FLAG);
329
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_prototype_with), 2, mxID(_with), XS_DONT_ENUM_FLAG);
330
38.0k
#endif
331
38.0k
  mxTypedArrayPrototype = *the->stack; 
332
38.0k
  constructor = fxBuildHostConstructor(the, mxCallback(fx_TypedArray), 0, mxID(_TypedArray));
333
38.0k
  mxTypedArrayConstructor = *the->stack;
334
38.0k
  slot = fxLastProperty(the, constructor);
335
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_from), 1, mxID(_from), XS_DONT_ENUM_FLAG);
336
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_TypedArray_of), 0, mxID(_of), XS_DONT_ENUM_FLAG);
337
38.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
338
494k
  for (index = 0, dispatch = &gxTypeDispatches[0], atomics = &gxTypeAtomics[0]; index < mxTypeArrayCount; index++, dispatch++, atomics++) {
339
456k
    mxPush(mxTypedArrayPrototype);
340
456k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
341
456k
    slot = fxNextIntegerProperty(the, slot, dispatch->size, mxID(_BYTES_PER_ELEMENT), XS_GET_ONLY);
342
456k
    slot = fxBuildHostConstructor(the, mxCallback(fx_TypedArray), 3, mxID(dispatch->constructorID));
343
456k
    the->stackIntrinsics[-1 - (txInteger)dispatch->constructorID] = *the->stack; //@@
344
456k
    slot->value.instance.prototype = constructor;
345
456k
    property = mxFunctionInstanceHome(slot);
346
456k
    slot = property->next;
347
456k
    property = fxNextTypeDispatchProperty(the, property, (txTypeDispatch*)dispatch, (txTypeAtomics*)atomics, XS_NO_ID, XS_INTERNAL_FLAG);
348
456k
    property->next = slot;
349
456k
    slot = fxLastProperty(the, slot);
350
456k
    slot = fxNextIntegerProperty(the, slot, dispatch->size, mxID(_BYTES_PER_ELEMENT), XS_GET_ONLY);
351
456k
    mxPop();
352
456k
  }
353
38.0k
  mxPop();
354
  
355
38.0k
#if mxUint8ArrayBase64
356
38.0k
  mxPush(mxUint8ArrayConstructor);
357
38.0k
    instance = fxToInstance(the, the->stack);
358
38.0k
  slot = fxLastProperty(the, instance);
359
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_fromBase64), 1, mxID(_fromBase64), XS_DONT_ENUM_FLAG);
360
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_fromHex), 1, mxID(_fromHex), XS_DONT_ENUM_FLAG);
361
38.0k
    mxGetID(mxID(_prototype));
362
38.0k
    instance = fxToInstance(the, the->stack);
363
38.0k
  slot = fxLastProperty(the, instance);
364
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_prototype_setFromBase64), 1, mxID(_setFromBase64), XS_DONT_ENUM_FLAG);
365
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_prototype_setFromHex), 1, mxID(_setFromHex), XS_DONT_ENUM_FLAG);
366
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_prototype_toBase64), 0, mxID(_toBase64), XS_DONT_ENUM_FLAG);
367
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Uint8Array_prototype_toHex), 0, mxID(_toHex), XS_DONT_ENUM_FLAG);
368
38.0k
  mxPop();
369
38.0k
#endif
370
38.0k
}
371
372
txInteger fxArgToByteLength(txMachine* the, txInteger argi, txInteger length)
373
687k
{
374
687k
  txSlot *arg = mxArgv(argi);
375
687k
  if ((mxArgc > argi) && (arg->kind != XS_UNDEFINED_KIND)) {
376
626k
    txNumber value;
377
626k
    if (XS_INTEGER_KIND == arg->kind) {
378
10.8k
      txInteger value = arg->value.integer;
379
10.8k
      if (value < 0)
380
110
        mxRangeError("byteLength < 0");
381
10.7k
      return value;
382
10.8k
    }
383
615k
    value = c_trunc(fxToNumber(the, arg));
384
615k
    if (c_isnan(value))
385
2.46k
      return 0;
386
613k
    if (value < 0) 
387
215
      mxRangeError("byteLength < 0");
388
613k
    if (0x7FFFFFFF < value)
389
70
      mxRangeError("byteLength too big");
390
613k
    return (txInteger)value;
391
613k
  }
392
60.5k
  return length;
393
687k
}
394
395
txS8 fxArgToSafeByteLength(txMachine* the, txInteger argi, txInteger length)
396
867k
{
397
867k
  txSlot *arg = mxArgv(argi);
398
867k
  if ((mxArgc > argi) && (arg->kind != XS_UNDEFINED_KIND)) {
399
865k
    txNumber value;
400
865k
    if (XS_INTEGER_KIND == arg->kind) {
401
649k
      txS8 value = arg->value.integer;
402
649k
      if (value < 0)
403
20
        mxRangeError("byteLength < 0");
404
649k
      return value;
405
649k
    }
406
215k
    value = c_trunc(fxToNumber(the, arg));
407
215k
    if (c_isnan(value))
408
556
      return 0;
409
215k
    if (value < 0) 
410
783
      mxRangeError("byteLength < 0");
411
214k
    if (C_MAX_SAFE_INTEGER < value)
412
118
      mxRangeError("byteLength too big");
413
214k
    return (txS8)value;
414
214k
  }
415
2.04k
  return length;
416
867k
}
417
418
txSlot* fxArgToInstance(txMachine* the, txInteger i)
419
31
{
420
31
  if (mxArgc > i)
421
20
    return fxToInstance(the, mxArgv(i));
422
31
  mxTypeError("cannot coerce undefined to object");
423
0
  return C_NULL;
424
31
}
425
426
txSlot* fxCheckArrayBufferDetached(txMachine* the, txSlot* slot)
427
225k
{
428
225k
  slot = slot->value.reference->next;
429
225k
  if (slot->value.arrayBuffer.address == C_NULL)
430
5
    mxTypeError("detached buffer");
431
225k
  return slot;
432
225k
}
433
434
txSlot* fxCheckArrayBufferInstance(txMachine* the, txSlot* slot)
435
57.4M
{
436
57.4M
  if (slot->kind == XS_REFERENCE_KIND) {
437
57.4M
    txSlot* instance = slot->value.reference;
438
57.4M
    txSlot* arrayBuffer = instance->next;
439
57.4M
    if (arrayBuffer && (arrayBuffer->flag & XS_INTERNAL_FLAG) && (arrayBuffer->kind == XS_ARRAY_BUFFER_KIND))
440
57.4M
      return instance;
441
57.4M
  }
442
188
  if (slot == mxThis)
443
188
    mxTypeError("this: not an ArrayBuffer instance");
444
188
  mxTypeError("not an ArrayBuffer instance");
445
0
  return C_NULL;
446
188
}
447
448
txSlot* fxCheckArrayBufferMutable(txMachine* the, txSlot* slot)
449
224k
{
450
224k
  slot = slot->value.reference->next;
451
224k
  if (slot->flag & XS_DONT_SET_FLAG)
452
11
    mxTypeError("ArrayBuffer instance is read-only");
453
224k
  return slot;
454
224k
}
455
456
void fxConstructArrayBufferResult(txMachine* the, txSlot* constructor, txInteger length)
457
62.3k
{
458
62.3k
  txSlot* instance;
459
62.3k
  if (constructor)
460
58.6k
    mxPushSlot(constructor);
461
3.65k
  else {
462
3.65k
    mxPushSlot(mxThis);
463
3.65k
    mxGetID(mxID(_constructor));
464
3.65k
    fxToSpeciesConstructor(the, &mxArrayBufferConstructor);
465
3.65k
  }
466
62.3k
  mxNew();
467
62.3k
  mxPushInteger(length);
468
62.3k
  mxRunCount(1);
469
62.3k
  if (the->stack->kind != XS_REFERENCE_KIND)
470
0
    mxTypeError("not an object");
471
62.3k
  instance = the->stack->value.reference;
472
62.3k
  if (!(instance->next) || (instance->next->kind != XS_ARRAY_BUFFER_KIND))
473
4
    mxTypeError("not an ArrayBuffer instance");
474
62.3k
  if (instance->next->value.arrayBuffer.address == C_NULL)
475
1
    mxTypeError("detached buffer");
476
62.3k
  if (instance->next->flag & XS_DONT_SET_FLAG)
477
7
    mxTypeError("read-only buffer");
478
62.3k
  if (!constructor && (mxThis->value.reference == instance))
479
1
    mxTypeError("same ArrayBuffer instance");
480
62.3k
  if (instance->next->next->value.bufferInfo.length < length)
481
2
    mxTypeError("smaller ArrayBuffer instance");
482
62.3k
  mxPullSlot(mxResult);
483
62.3k
}
484
485
txSlot* fxNewArrayBufferInstance(txMachine* the)
486
2.25M
{
487
2.25M
  txSlot* instance;
488
2.25M
  txSlot* property;
489
2.25M
  instance = fxNewObjectInstance(the);
490
2.25M
  property = instance->next = fxNewSlot(the);
491
2.25M
  property->flag = XS_INTERNAL_FLAG;
492
2.25M
  property->kind = XS_ARRAY_BUFFER_KIND;
493
2.25M
  property->value.arrayBuffer.address = C_NULL;
494
2.25M
  property->value.arrayBuffer.detachKey = C_NULL;
495
2.25M
  property = property->next = fxNewSlot(the);
496
2.25M
  property->flag = XS_INTERNAL_FLAG;
497
2.25M
  property->kind = XS_BUFFER_INFO_KIND;
498
2.25M
  property->value.bufferInfo.length = 0;
499
2.25M
  property->value.bufferInfo.maxLength = -1;
500
2.25M
  return instance;
501
2.25M
}
502
503
void fx_ArrayBuffer(txMachine* the)
504
843k
{
505
843k
  txSlot* instance;
506
843k
  txS8 byteLength;
507
843k
  txS8 maxByteLength = -1;
508
843k
  txSlot* property;
509
843k
  if (!mxHasTarget)
510
3
    mxTypeError("call: ArrayBuffer");
511
843k
  byteLength = fxArgToSafeByteLength(the, 0, 0);
512
843k
  if ((mxArgc > 1) && mxIsReference(mxArgv(1))) {
513
1.32k
    mxPushSlot(mxArgv(1));
514
1.32k
    mxGetID(mxID(_maxByteLength));
515
1.32k
    mxPullSlot(mxArgv(1));
516
1.32k
    maxByteLength = fxArgToSafeByteLength(the, 1, -1);
517
1.32k
  }
518
843k
  if (maxByteLength >= 0) {
519
542
    if (byteLength > maxByteLength)
520
3
      mxRangeError("byteLength > maxByteLength");
521
542
  }
522
843k
  mxPushSlot(mxTarget);
523
843k
  fxGetPrototypeFromConstructor(the, &mxArrayBufferPrototype);
524
843k
  instance = fxNewArrayBufferInstance(the);
525
843k
  mxPullSlot(mxResult);
526
843k
  if (byteLength > 0x7FFFFFFF)
527
3
    mxRangeError("byteLength too big");
528
843k
  if (maxByteLength > 0x7FFFFFFF)
529
5
    mxRangeError("maxByteLength too big");
530
843k
  property = instance->next;
531
843k
  property->value.arrayBuffer.address = fxNewChunk(the, (txSize)byteLength);
532
843k
  c_memset(property->value.arrayBuffer.address, 0, (txSize)byteLength);
533
843k
  property = property->next;
534
843k
  property->value.bufferInfo.length = (txSize)byteLength;
535
843k
  property->value.bufferInfo.maxLength = (txSize)maxByteLength;
536
843k
}
537
538
void fx_ArrayBuffer_fromBigInt(txMachine* the)
539
35.0k
{
540
35.0k
  txU4 minBytes = 0;
541
35.0k
  txBoolean sign = 0;
542
35.0k
  int endian = EndianBig;
543
35.0k
  if (mxArgc < 1)
544
1
    mxTypeError("no argument");
545
35.0k
  if (mxArgc > 1)
546
35.0k
    minBytes = (txU4)fxArgToByteLength(the, 1, 0);
547
35.0k
  if ((mxArgc > 2) && fxToBoolean(the, mxArgv(2)))
548
2
    sign = 1;
549
35.0k
  if ((mxArgc > 3) && fxToBoolean(the, mxArgv(3)))
550
2
    endian = EndianLittle;
551
35.0k
  if (gxTypeBigInt.toArrayBuffer) {
552
35.0k
    gxTypeBigInt.toArrayBuffer(the, mxArgv(0), minBytes, sign, endian);
553
35.0k
  }
554
0
  else {
555
0
    mxUnknownError("not built-in");
556
0
  }
557
35.0k
}
558
559
#ifndef mxCESU8
560
void fx_ArrayBuffer_fromString(txMachine* the)
561
{
562
  txSize length = 0;
563
  if (mxArgc < 1)
564
    mxTypeError("no argument");
565
  
566
  txString c = fxToString(the, mxArgv(0));
567
  txInteger nulls = 0;
568
  while (1) {
569
    uint8_t b = (uint8_t)c_read8(c++);
570
    if (!b) break;
571
572
    length += 1;
573
    if ((0xc0 == b) && (0x80 == (uint8_t)c_read8(c)))
574
      nulls += 1;
575
  } 
576
  
577
  fxConstructArrayBufferResult(the, mxThis, length - nulls);
578
  if (!nulls)
579
    c_memcpy(mxResult->value.reference->next->value.arrayBuffer.address, mxArgv(0)->value.string, length);
580
  else {
581
    txString c = mxArgv(0)->value.string, end = c + length;
582
    txByte *out = mxResult->value.reference->next->value.arrayBuffer.address;
583
    while (c < end) {
584
      uint8_t b = (uint8_t)c_read8(c++);
585
      if ((0xc0 == (uint8_t)b) && (0x80 == (uint8_t)c_read8(c))) {
586
        b = 0;
587
        c += 1;
588
      }
589
      *out++ = b;
590
    }
591
  }
592
}
593
#endif
594
595
void fx_ArrayBuffer_isView(txMachine* the)
596
282
{
597
282
  txSlot* slot;
598
282
  mxResult->kind = XS_BOOLEAN_KIND;
599
282
  mxResult->value.boolean = 0;
600
282
  if (mxArgc > 0) {
601
280
    slot = mxArgv(0);
602
280
    if (slot->kind == XS_REFERENCE_KIND) {
603
8
      slot = slot->value.reference;
604
8
      if (slot->next) {
605
5
        slot = slot->next;
606
5
        if ((slot->kind == XS_DATA_VIEW_KIND) || (slot->kind == XS_TYPED_ARRAY_KIND)) {
607
1
          mxResult->value.boolean = 1;
608
1
        }
609
5
      }
610
8
    }
611
280
  }
612
282
}
613
614
void fx_ArrayBuffer_prototype_get_byteLength(txMachine* the)
615
142
{
616
142
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
617
142
  txSlot* arrayBuffer = instance->next;
618
142
  txSlot* bufferInfo = arrayBuffer->next;
619
142
  mxResult->kind = XS_INTEGER_KIND;
620
142
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
621
3
    mxResult->value.integer = 0;
622
139
  else
623
139
    mxResult->value.integer = bufferInfo->value.bufferInfo.length;
624
142
}
625
626
void fx_ArrayBuffer_prototype_get_detached(txMachine* the)
627
23.6k
{
628
23.6k
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
629
23.6k
  txSlot* arrayBuffer = instance->next;
630
23.6k
  mxResult->kind = XS_BOOLEAN_KIND;
631
23.6k
  mxResult->value.boolean = (arrayBuffer->value.arrayBuffer.address == C_NULL) ? 1 : 0;
632
23.6k
}
633
634
void fx_ArrayBuffer_prototype_get_immutable(txMachine* the)
635
23.6k
{
636
23.6k
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
637
23.6k
  txSlot* arrayBuffer = instance->next;
638
23.6k
  mxResult->kind = XS_BOOLEAN_KIND;
639
23.6k
  mxResult->value.boolean = (arrayBuffer->flag & XS_DONT_SET_FLAG) ? 1 : 0;
640
23.6k
}
641
642
void fx_ArrayBuffer_prototype_get_maxByteLength(txMachine* the)
643
113
{
644
113
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
645
113
  txSlot* arrayBuffer = instance->next;
646
113
  txSlot* bufferInfo = arrayBuffer->next;
647
113
  mxResult->kind = XS_INTEGER_KIND;
648
113
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
649
0
    mxResult->value.integer = 0;
650
113
  else if (bufferInfo->value.bufferInfo.maxLength >= 0)
651
6
    mxResult->value.integer = bufferInfo->value.bufferInfo.maxLength;
652
107
  else
653
107
    mxResult->value.integer = bufferInfo->value.bufferInfo.length;
654
113
}
655
656
void fx_ArrayBuffer_prototype_get_resizable(txMachine* the)
657
77
{
658
77
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
659
77
  txSlot* arrayBuffer = instance->next;
660
77
  txSlot* bufferInfo = arrayBuffer->next;
661
77
  mxResult->kind = XS_BOOLEAN_KIND;
662
77
  mxResult->value.boolean = (bufferInfo->value.bufferInfo.maxLength >= 0) ? 1 : 0;
663
77
}
664
665
void fx_ArrayBuffer_prototype_concat(txMachine* the)
666
3.60k
{
667
3.60k
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
668
3.60k
  txSlot* arrayBuffer = instance->next;
669
3.60k
  txSlot* bufferInfo = arrayBuffer->next;
670
3.60k
  txInteger length = bufferInfo->value.bufferInfo.length;
671
3.60k
  txInteger c = mxArgc, i = 0;
672
3.60k
  txByte* address;
673
3.60k
  txSlot* slot;
674
3.62k
  while (i < c) {
675
18
    arrayBuffer = C_NULL;
676
18
    bufferInfo = C_NULL;
677
18
    slot = mxArgv(i);
678
18
    if (slot->kind == XS_REFERENCE_KIND) {
679
15
      slot = slot->value.reference->next;
680
15
      if (slot) {
681
14
        if (slot->kind == XS_ARRAY_BUFFER_KIND) {
682
13
          bufferInfo = slot->next;
683
13
        }
684
1
        else if ((slot->kind == XS_HOST_KIND) && !(slot->flag & XS_HOST_CHUNK_FLAG)) {
685
0
          slot = slot->next;
686
0
          if (slot && (slot->kind == XS_BUFFER_INFO_KIND)) {
687
0
            bufferInfo = slot;
688
0
          }
689
0
        }
690
14
      }
691
15
    }
692
18
    if (bufferInfo) 
693
13
      length = fxAddChunkSizes(the, length, bufferInfo->value.bufferInfo.length);
694
5
    else
695
5
      mxTypeError("arguments[%ld]: not an ArrayBuffer instance", i);
696
13
    i++;
697
13
  }
698
3.60k
  fxConstructArrayBufferResult(the, C_NULL, length);
699
3.60k
  address = mxResult->value.reference->next->value.arrayBuffer.address;
700
3.60k
  slot = instance->next;
701
3.60k
  i = -1;
702
3.61k
  while (length > 0) {
703
16
    txByte* from;
704
16
    txInteger count;
705
16
    if (slot->kind == XS_ARRAY_BUFFER_KIND)
706
16
      from = slot->value.arrayBuffer.address;
707
0
    else
708
0
      from = slot->value.host.data;
709
16
    count = (from) ? slot->next->value.bufferInfo.length : 0;
710
16
    if (count > length)
711
1
      count = length;
712
16
    if (count > 0)
713
15
      c_memmove(address, from, count);
714
16
    address += count;
715
16
    length -= count;
716
16
    if (++i >= c)
717
5
      break;
718
11
    slot = mxArgv(i)->value.reference->next;
719
11
  }
720
3.60k
}
721
722
void fx_ArrayBuffer_prototype_resize(txMachine* the)
723
1.00k
{
724
1.00k
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
725
1.00k
  txSlot* arrayBuffer = instance->next;
726
1.00k
  txSlot* bufferInfo = arrayBuffer->next;
727
1.00k
  fxCheckArrayBufferMutable(the, mxThis);
728
1.00k
  txInteger maxByteLength = bufferInfo->value.bufferInfo.maxLength;
729
1.00k
  if (maxByteLength < 0)
730
12
    mxTypeError("not resizable");
731
991
  txInteger newByteLength = fxArgToByteLength(the, 0, 0);
732
991
  fxCheckArrayBufferDetached(the, mxThis);
733
991
  txInteger oldByteLength;
734
991
  txByte* chunk;
735
991
  oldByteLength = bufferInfo->value.bufferInfo.length;
736
991
  if (newByteLength > maxByteLength)
737
1
    mxRangeError("newLength > maxByteLength");
738
990
  arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);
739
990
  chunk = (txByte*)fxRenewChunk(the, arrayBuffer->value.arrayBuffer.address, newByteLength);
740
990
  if (!chunk) {
741
3
    chunk = (txByte*)fxNewChunk(the, newByteLength);
742
3
    c_memcpy(chunk, arrayBuffer->value.arrayBuffer.address, (newByteLength < oldByteLength) ? newByteLength : oldByteLength);
743
3
  }
744
990
  if (newByteLength > oldByteLength)
745
55
    c_memset(chunk + oldByteLength, 0, newByteLength - oldByteLength);
746
990
  arrayBuffer->value.arrayBuffer.address = chunk;
747
990
  bufferInfo->value.bufferInfo.length = newByteLength;
748
990
}
749
750
void fx_ArrayBuffer_prototype_slice(txMachine* the)
751
60
{
752
60
  /* txSlot* instance = */ fxCheckArrayBufferInstance(the, mxThis);
753
60
  txSlot* arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);
754
60
  txSlot* bufferInfo = arrayBuffer->next;
755
60
  txInteger length = bufferInfo->value.bufferInfo.length;
756
60
  txInteger start = fxArgToIndexInteger(the, 0, 0, length);
757
60
  txInteger stop = fxArgToIndexInteger(the, 1, length, length);
758
60
  txSlot* resultBuffer;
759
60
  if (stop < start) 
760
6
    stop = start;
761
60
  fxConstructArrayBufferResult(the, C_NULL, stop - start);
762
60
  resultBuffer = mxResult->value.reference->next;
763
60
  arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);
764
60
  bufferInfo = arrayBuffer->next;
765
60
  length = bufferInfo->value.bufferInfo.length;
766
60
  if (start < length) {
767
22
    if (stop > length)
768
1
      stop = length;
769
22
    c_memcpy(resultBuffer->value.arrayBuffer.address, arrayBuffer->value.arrayBuffer.address + start, stop - start);
770
22
  }
771
60
}
772
773
void fx_ArrayBuffer_prototype_sliceToImmutable(txMachine* the)
774
14
{
775
14
  /* txSlot* instance = */ fxCheckArrayBufferInstance(the, mxThis);
776
14
  txSlot* arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);
777
14
  txSlot* bufferInfo = arrayBuffer->next;
778
14
  txInteger length = bufferInfo->value.bufferInfo.length;
779
14
  txInteger start = fxArgToIndexInteger(the, 0, 0, length);
780
14
  txInteger stop = fxArgToIndexInteger(the, 1, length, length);
781
14
  txSlot* resultBuffer;
782
14
  if (stop < start) 
783
2
    stop = start;
784
14
  arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);  
785
14
  bufferInfo = arrayBuffer->next;
786
14
  length = bufferInfo->value.bufferInfo.length;
787
14
  if (length < stop)
788
1
    mxRangeError("resized this");
789
13
  fxConstructArrayBufferResult(the,  &mxArrayBufferConstructor, stop - start);
790
13
  resultBuffer = fxCheckArrayBufferDetached(the, mxResult);
791
13
  c_memcpy(resultBuffer->value.arrayBuffer.address, arrayBuffer->value.arrayBuffer.address + start, stop - start);
792
13
  resultBuffer->flag |= XS_DONT_SET_FLAG;
793
13
}
794
795
static void fx_ArrayBuffer_prototype_transferAux(txMachine* the, txFlag flag)
796
23.7k
{
797
23.7k
  txSlot* instance = fxCheckArrayBufferInstance(the, mxThis);
798
23.7k
  txSlot* arrayBuffer = instance->next;
799
23.7k
  txSlot* bufferInfo = arrayBuffer->next;
800
23.7k
  txInteger oldByteLength = bufferInfo->value.bufferInfo.length;
801
23.7k
  txInteger maxByteLength = bufferInfo->value.bufferInfo.maxLength;
802
23.7k
  txInteger newByteLength = fxArgToByteLength(the, 0, oldByteLength);
803
23.7k
  txSlot* resultBuffer;
804
23.7k
  oldByteLength = bufferInfo->value.bufferInfo.length;  // ToIndex may have resized this
805
23.7k
  arrayBuffer = fxCheckArrayBufferDetached(the, mxThis);
806
23.7k
  fxCheckArrayBufferMutable(the, mxThis);
807
23.7k
  if (!(flag & 1) && (maxByteLength >= 0) && (newByteLength > maxByteLength))
808
1
    mxRangeError("newLength > maxByteLength");
809
23.7k
  fxConstructArrayBufferResult(the, &mxArrayBufferConstructor, newByteLength);
810
23.7k
  resultBuffer = mxResult->value.reference->next;
811
23.7k
  c_memcpy(resultBuffer->value.arrayBuffer.address, arrayBuffer->value.arrayBuffer.address, (newByteLength < oldByteLength) ? newByteLength : oldByteLength);
812
23.7k
  if (newByteLength > oldByteLength)
813
28
    c_memset(resultBuffer->value.arrayBuffer.address + oldByteLength, 0, newByteLength - oldByteLength);
814
23.7k
  arrayBuffer->value.arrayBuffer.address = C_NULL;
815
23.7k
  bufferInfo->value.bufferInfo.length = 0;
816
23.7k
  if (flag & 2)
817
23.6k
    resultBuffer->flag |= XS_DONT_SET_FLAG;
818
23.7k
  resultBuffer->next->value.bufferInfo.maxLength = (flag & 1) ? -1 : maxByteLength;
819
23.7k
}
820
821
void fx_ArrayBuffer_prototype_transfer(txMachine* the)
822
24
{
823
24
  fx_ArrayBuffer_prototype_transferAux(the, 0);
824
24
}
825
826
void fx_ArrayBuffer_prototype_transferToFixedLength(txMachine* the)
827
16
{
828
16
  fx_ArrayBuffer_prototype_transferAux(the, 1);
829
16
}
830
831
void fx_ArrayBuffer_prototype_transferToImmutable(txMachine* the)
832
23.6k
{
833
23.6k
  fx_ArrayBuffer_prototype_transferAux(the, 3);
834
23.6k
}
835
836
txSlot* fxCheckDataViewInstance(txMachine* the, txSlot* slot, txBoolean mutable)
837
5.98k
{
838
5.98k
  if (slot->kind == XS_REFERENCE_KIND) {
839
5.89k
    txSlot* instance = slot->value.reference;
840
5.89k
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DATA_VIEW_KIND)) {
841
5.73k
      if (mutable) {
842
3.67k
        txSlot* arrayBuffer = slot->next->value.reference->next;
843
3.67k
        if (arrayBuffer->flag & XS_DONT_SET_FLAG)
844
5
          mxTypeError("read-only buffer");
845
3.67k
      }
846
5.72k
      return instance;
847
5.73k
    }
848
5.89k
  }
849
5.98k
  mxTypeError("this: not a DataView instance");
850
0
  return C_NULL;
851
5.98k
}
852
853
txInteger fxCheckDataViewSize(txMachine* the, txSlot* view, txSlot* buffer, txBoolean mutable)
854
117k
{
855
117k
  txInteger size = view->value.dataView.size;
856
117k
  txSlot* arrayBuffer = buffer->value.reference->next;
857
117k
  txSlot* bufferInfo = arrayBuffer->next;
858
117k
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
859
2
    mxTypeError("detached buffer");
860
117k
  if (mutable && (arrayBuffer->flag & XS_DONT_SET_FLAG))
861
1
    mxTypeError("read-only buffer");
862
117k
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
863
2.28k
    txInteger offset = view->value.dataView.offset;
864
2.28k
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
865
2.28k
    if (offset > byteLength)
866
4
      mxTypeError("out of bounds view");
867
2.28k
    else if (size < 0)
868
2.23k
      size = byteLength - offset;
869
51
    else if (offset + size > byteLength)
870
8
      mxTypeError("out of bounds view");
871
2.28k
  }
872
117k
  return size;
873
117k
}
874
875
txSlot* fxGetBufferInfo(txMachine* the, txSlot* buffer)
876
32.6k
{
877
32.6k
  txSlot* arrayBuffer = buffer->value.reference->next;
878
32.6k
  txSlot* bufferInfo = arrayBuffer->next;
879
32.6k
  if (arrayBuffer->kind == XS_ARRAY_BUFFER_KIND) {
880
29.2k
    if (arrayBuffer->value.arrayBuffer.address == C_NULL)
881
1
      mxTypeError("detached buffer");
882
29.2k
    return bufferInfo;
883
29.2k
  }
884
3.46k
  if (arrayBuffer->kind == XS_HOST_KIND) {
885
3.46k
    if (bufferInfo && (bufferInfo->kind == XS_BUFFER_INFO_KIND))
886
3.46k
      return bufferInfo;
887
3.46k
  }
888
3.46k
  mxTypeError("invalid buffer");
889
0
  return C_NULL;
890
3.46k
}
891
892
txInteger fxGetDataViewSize(txMachine* the, txSlot* view, txSlot* buffer)
893
10.3M
{
894
10.3M
  txInteger size = view->value.dataView.size;
895
10.3M
  txSlot* arrayBuffer = buffer->value.reference->next;
896
10.3M
  txSlot* bufferInfo = arrayBuffer->next;
897
10.3M
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
898
17
    return 0;
899
10.3M
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
900
6.34k
    txInteger offset = view->value.dataView.offset;
901
6.34k
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
902
6.34k
    if (offset > byteLength)
903
9
      size = 0;
904
6.33k
    else if (size < 0)
905
6.32k
      size = byteLength - offset;
906
6
    else if (offset + size > byteLength)
907
1
      size = 0;
908
6.34k
  }
909
10.3M
  return size;
910
10.3M
}
911
912
txBoolean fxIsDataViewOutOfBound(txMachine* the, txSlot* view, txSlot* buffer)
913
179
{
914
179
  txInteger size = view->value.dataView.size;
915
179
  txSlot* arrayBuffer = buffer->value.reference->next;
916
179
  txSlot* bufferInfo = arrayBuffer->next;
917
179
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
918
0
    return 1;
919
179
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
920
35
    txInteger offset = view->value.dataView.offset;
921
35
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
922
35
    if (offset > byteLength)
923
1
      return 1;
924
34
    if ((size > 0) && (offset + size > byteLength))
925
0
      return 1;
926
34
  }
927
178
  return 0;
928
179
}
929
930
txSlot* fxNewDataViewInstance(txMachine* the)
931
791
{
932
791
  txSlot* instance;
933
791
  txSlot* property;
934
791
  instance = fxNewObjectInstance(the);
935
791
  property = instance->next = fxNewSlot(the);
936
791
  property->flag = XS_INTERNAL_FLAG;
937
791
  property->kind = XS_DATA_VIEW_KIND;
938
791
  property->value.dataView.offset = 0;
939
791
  property->value.dataView.size = 0;
940
791
  property = fxNextNullProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
941
791
  return instance;
942
791
}
943
944
void fx_DataView(txMachine* the)
945
1.27k
{
946
1.27k
  txSlot* slot;
947
1.27k
  txBoolean flag = 0;
948
1.27k
  txInteger offset, size;
949
1.27k
  txSlot* info;
950
1.27k
  txSlot* instance;
951
1.27k
  txSlot* view;
952
1.27k
  txSlot* buffer;
953
1.27k
  if (!mxHasTarget)
954
3
    mxTypeError("call: DataView");
955
1.27k
  if ((mxArgc > 0) && (mxArgv(0)->kind == XS_REFERENCE_KIND)) {
956
1.25k
    slot = mxArgv(0)->value.reference->next;
957
1.25k
    if (slot && ((slot->kind == XS_ARRAY_BUFFER_KIND) || (slot->kind == XS_HOST_KIND))) {
958
1.24k
      flag = 1;
959
1.24k
    }
960
1.25k
  }
961
1.27k
  if (!flag)
962
32
    mxTypeError("buffer: not an ArrayBuffer instance");
963
    
964
1.24k
  offset = fxArgToByteLength(the, 1, 0);
965
1.24k
  info = fxGetBufferInfo(the, mxArgv(0));
966
1.24k
  if (info->value.bufferInfo.length < offset)
967
227
    mxRangeError("invalid byteOffset %ld", offset);
968
1.01k
  size = fxArgToByteLength(the, 2, -1);
969
1.01k
  if (size >= 0) {
970
193
    txInteger end = offset + size;
971
193
    if ((info->value.bufferInfo.length < end) || (end < offset))
972
21
      mxRangeError("invalid byteLength %ld", size);
973
193
  }
974
821
  else {
975
821
    if (info->value.bufferInfo.maxLength < 0)
976
610
      size = info->value.bufferInfo.length - offset;
977
821
  }
978
993
  mxPushSlot(mxTarget);
979
993
  fxGetPrototypeFromConstructor(the, &mxDataViewPrototype);
980
993
  instance = fxNewDataViewInstance(the);
981
993
  mxPullSlot(mxResult);
982
993
  view = instance->next;
983
993
  buffer = view->next;
984
993
  buffer->kind = XS_REFERENCE_KIND;
985
993
  buffer->value.reference = mxArgv(0)->value.reference;
986
993
  info = fxGetBufferInfo(the, buffer);
987
993
  if (info->value.bufferInfo.maxLength >= 0) {
988
31
    if (info->value.bufferInfo.length < offset)
989
1
      mxRangeError("invalid byteOffset %ld", offset);
990
30
    else if (size >= 0) {
991
22
      txInteger end = offset + size;
992
22
      if ((info->value.bufferInfo.length < end) || (end < offset))
993
1
        mxRangeError("invalid byteLength %ld", size);
994
22
    }
995
31
  }
996
991
  view->value.dataView.offset = offset;
997
991
  view->value.dataView.size = size;
998
991
}
999
1000
void fx_DataView_prototype_buffer_get(txMachine* the)
1001
64
{
1002
64
  txSlot* instance = fxCheckDataViewInstance(the, mxThis, XS_IMMUTABLE);
1003
64
  txSlot* view = instance->next;
1004
64
  txSlot* buffer = view->next;
1005
64
  mxResult->kind = buffer->kind;
1006
64
  mxResult->value = buffer->value;
1007
64
}
1008
1009
void fx_DataView_prototype_byteLength_get(txMachine* the)
1010
111
{
1011
111
  txSlot* instance = fxCheckDataViewInstance(the, mxThis, XS_IMMUTABLE);
1012
111
  txSlot* view = instance->next;
1013
111
  txSlot* buffer = view->next;
1014
111
  txInteger size = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
1015
111
  mxResult->kind = XS_INTEGER_KIND;
1016
111
  mxResult->value.integer = size;
1017
111
}
1018
1019
void fx_DataView_prototype_byteOffset_get(txMachine* the)
1020
105
{
1021
105
  txSlot* instance = fxCheckDataViewInstance(the, mxThis, XS_IMMUTABLE);
1022
105
  txSlot* view = instance->next;
1023
105
  txSlot* buffer = view->next;
1024
105
  fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
1025
105
  mxResult->kind = XS_INTEGER_KIND;
1026
105
  mxResult->value.integer = view->value.dataView.offset;
1027
105
}
1028
1029
void fx_DataView_prototype_get(txMachine* the, txNumber delta, txTypeCallback getter)
1030
1.95k
{
1031
1.95k
  txSlot* instance = fxCheckDataViewInstance(the, mxThis, XS_IMMUTABLE);
1032
1.95k
  txSlot* view = instance->next;
1033
1.95k
  txSlot* buffer = view->next;
1034
1.95k
  txInteger offset = fxArgToByteLength(the, 0, 0);
1035
1.95k
  txInteger size;
1036
1.95k
  int endian = EndianBig;
1037
1.95k
  if ((mxArgc > 1) && fxToBoolean(the, mxArgv(1)))
1038
143
    endian = EndianLittle;
1039
1.95k
  size = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
1040
1.95k
  if ((size < delta) || ((size - delta) < offset))
1041
188
    mxRangeError("invalid byteOffset");
1042
1.76k
  offset += view->value.dataView.offset;
1043
1.76k
  (*getter)(the, buffer->value.reference->next, offset, mxResult, endian);
1044
1.76k
}
1045
1046
void fx_DataView_prototype_getBigInt64(txMachine* the)
1047
230
{
1048
230
  fx_DataView_prototype_get(the, 8, fxBigInt64Getter);
1049
230
}
1050
1051
void fx_DataView_prototype_getBigUint64(txMachine* the)
1052
254
{
1053
254
  fx_DataView_prototype_get(the, 8, fxBigUint64Getter);
1054
254
}
1055
1056
#if mxFloat16
1057
void fx_DataView_prototype_getFloat16(txMachine* the)
1058
97
{
1059
97
  fx_DataView_prototype_get(the, 2, fxFloat16Getter);
1060
97
}
1061
#endif
1062
1063
void fx_DataView_prototype_getFloat32(txMachine* the)
1064
103
{
1065
103
  fx_DataView_prototype_get(the, 4, fxFloat32Getter);
1066
103
}
1067
1068
void fx_DataView_prototype_getFloat64(txMachine* the)
1069
117
{
1070
117
  fx_DataView_prototype_get(the, 8, fxFloat64Getter);
1071
117
}
1072
1073
void fx_DataView_prototype_getInt8(txMachine* the)
1074
592
{
1075
592
  fx_DataView_prototype_get(the, 1, fxInt8Getter);
1076
592
}
1077
1078
void fx_DataView_prototype_getInt16(txMachine* the)
1079
132
{
1080
132
  fx_DataView_prototype_get(the, 2, fxInt16Getter);
1081
132
}
1082
1083
void fx_DataView_prototype_getInt32(txMachine* the)
1084
119
{
1085
119
  fx_DataView_prototype_get(the, 4, fxInt32Getter);
1086
119
}
1087
1088
void fx_DataView_prototype_getUint8(txMachine* the)
1089
69
{
1090
69
  fx_DataView_prototype_get(the, 1, fxUint8Getter);
1091
69
}
1092
1093
void fx_DataView_prototype_getUint16(txMachine* the)
1094
95
{
1095
95
  fx_DataView_prototype_get(the, 2, fxUint16Getter);
1096
95
}
1097
1098
void fx_DataView_prototype_getUint32(txMachine* the)
1099
147
{
1100
147
  fx_DataView_prototype_get(the, 4, fxUint32Getter);
1101
147
}
1102
1103
void fx_DataView_prototype_set(txMachine* the, txNumber delta, txTypeCoerce coercer, txTypeCallback setter)
1104
3.74k
{
1105
3.74k
  txSlot* instance = fxCheckDataViewInstance(the, mxThis, XS_MUTABLE);
1106
3.74k
  txSlot* view = instance->next;
1107
3.74k
  txSlot* buffer = view->next;
1108
3.74k
  txInteger offset = fxArgToByteLength(the, 0, 0);
1109
3.74k
  txInteger size;
1110
3.74k
  int endian = EndianBig;
1111
3.74k
  txSlot* value;
1112
3.74k
  if (mxArgc > 1)
1113
3.44k
    mxPushSlot(mxArgv(1));
1114
304
  else
1115
304
    mxPushUndefined();
1116
3.74k
  value = the->stack; 
1117
3.74k
  (*coercer)(the, value);
1118
3.74k
  if ((mxArgc > 2) && fxToBoolean(the, mxArgv(2)))
1119
93
    endian = EndianLittle;
1120
3.74k
  size = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE);
1121
3.74k
  if ((size < delta) || ((size - delta) < offset))
1122
81
    mxRangeError("invalid byteOffset");
1123
3.66k
  offset += view->value.dataView.offset;
1124
3.66k
  (*setter)(the, buffer->value.reference->next, offset, value, endian);
1125
3.66k
  mxPop();
1126
3.66k
}
1127
1128
void fx_DataView_prototype_setBigInt64(txMachine* the)
1129
117
{
1130
117
  fx_DataView_prototype_set(the, 8, fxBigIntCoerce, fxBigInt64Setter);
1131
117
}
1132
1133
void fx_DataView_prototype_setBigUint64(txMachine* the)
1134
8
{
1135
8
  fx_DataView_prototype_set(the, 8, fxBigIntCoerce, fxBigUint64Setter);
1136
8
}
1137
1138
#if mxFloat16
1139
void fx_DataView_prototype_setFloat16(txMachine* the)
1140
143
{
1141
143
  fx_DataView_prototype_set(the, 2, fxNumberCoerce, fxFloat16Setter);
1142
143
}
1143
#endif
1144
1145
void fx_DataView_prototype_setFloat32(txMachine* the)
1146
110
{
1147
110
  fx_DataView_prototype_set(the, 4, fxNumberCoerce, fxFloat32Setter);
1148
110
}
1149
1150
void fx_DataView_prototype_setFloat64(txMachine* the)
1151
125
{
1152
125
  fx_DataView_prototype_set(the, 8, fxNumberCoerce, fxFloat64Setter);
1153
125
}
1154
1155
void fx_DataView_prototype_setInt8(txMachine* the)
1156
100
{
1157
100
  fx_DataView_prototype_set(the, 1, fxIntCoerce, fxInt8Setter);
1158
100
}
1159
1160
void fx_DataView_prototype_setInt16(txMachine* the)
1161
110
{
1162
110
  fx_DataView_prototype_set(the, 2, fxIntCoerce, fxInt16Setter);
1163
110
}
1164
1165
void fx_DataView_prototype_setInt32(txMachine* the)
1166
112
{
1167
112
  fx_DataView_prototype_set(the, 4, fxIntCoerce, fxInt32Setter);
1168
112
}
1169
1170
void fx_DataView_prototype_setUint8(txMachine* the)
1171
2.54k
{
1172
2.54k
  fx_DataView_prototype_set(the, 1, fxUintCoerce, fxUint8Setter);
1173
2.54k
}
1174
1175
void fx_DataView_prototype_setUint16(txMachine* the)
1176
243
{
1177
243
  fx_DataView_prototype_set(the, 2, fxUintCoerce, fxUint16Setter);
1178
243
}
1179
1180
void fx_DataView_prototype_setUint32(txMachine* the)
1181
135
{
1182
135
  fx_DataView_prototype_set(the, 4, fxUintCoerce, fxUint32Setter);
1183
135
}
1184
1185
1186
#define mxTypedArrayDeclarations \
1187
64.9k
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis); \
1188
64.9k
  txSlot* dispatch = instance->next; \
1189
64.9k
  txSlot* view = dispatch->next; \
1190
64.9k
  txSlot* buffer = view->next; \
1191
64.9k
  txInteger length = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE) >> dispatch->value.typedArray.dispatch->shift
1192
1193
#define mxMutableTypedArrayDeclarations \
1194
3.68k
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis); \
1195
3.68k
  txSlot* dispatch = instance->next; \
1196
3.68k
  txSlot* view = dispatch->next; \
1197
3.68k
  txSlot* buffer = view->next; \
1198
3.68k
  txInteger length = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE) >> dispatch->value.typedArray.dispatch->shift
1199
1200
#define mxResultTypedArrayDeclarations \
1201
23.7k
  txSlot* resultInstance = fxCheckTypedArrayInstance(the, mxResult); \
1202
23.7k
  txSlot* resultDispatch = resultInstance->next; \
1203
23.7k
  txSlot* resultView = resultDispatch->next; \
1204
23.7k
  txSlot* resultBuffer = resultView->next; \
1205
23.7k
  txInteger resultLength = fxCheckDataViewSize(the, resultView, resultBuffer, XS_MUTABLE) >> resultDispatch->value.typedArray.dispatch->shift
1206
1207
void fxTypedArrayGetter(txMachine* the)
1208
5.27M
{
1209
5.27M
  txSlot* instance = fxToInstance(the, mxThis);
1210
5.27M
  txSlot* dispatch;
1211
5.27M
  while (instance) {
1212
5.27M
    if (instance->flag & XS_EXOTIC_FLAG) {
1213
5.27M
      dispatch = instance->next;
1214
5.27M
      if (dispatch->ID == XS_TYPED_ARRAY_BEHAVIOR)
1215
5.27M
        break;
1216
5.27M
    }
1217
0
    instance = fxGetPrototype(the, instance);
1218
0
  }
1219
5.27M
  if (instance) {
1220
5.27M
    txID id = the->scratch.value.at.id;
1221
5.27M
    txIndex index = the->scratch.value.at.index;
1222
5.27M
    txSlot* view = dispatch->next;
1223
5.27M
    txSlot* buffer = view->next;
1224
5.27M
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1225
5.27M
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1226
5.27M
    if ((!id) && (index < length)) {
1227
5.26M
      (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset + (index << shift), mxResult, EndianNative);
1228
5.26M
    }
1229
5.27M
  }
1230
5.27M
}
1231
1232
void fxTypedArraySetter(txMachine* the)
1233
501k
{
1234
501k
  txSlot* instance = fxToInstance(the, mxThis);
1235
501k
  while (instance) {
1236
501k
    if (instance->flag & XS_EXOTIC_FLAG) {
1237
501k
      if (instance->next->ID == XS_TYPED_ARRAY_BEHAVIOR)
1238
501k
        break;
1239
501k
    }
1240
0
    instance = fxGetPrototype(the, instance);
1241
0
  }
1242
501k
  if (instance) {
1243
501k
    txSlot* value = mxArgv(0);
1244
501k
    txID id = the->scratch.value.at.id;
1245
501k
    txIndex index = the->scratch.value.at.index;
1246
501k
        if (!fxTypedArraySetPropertyValue(the, instance, id, index, value, mxThis)) {
1247
0
            if (the->frame->next->flag & XS_STRICT_FLAG)
1248
0
        mxTypeError("not extensible or not writable");
1249
0
        }
1250
501k
  }
1251
501k
}
1252
1253
txBoolean fxTypedArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask) 
1254
19
{
1255
19
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1256
17
    txSlot* dispatch = instance->next;
1257
17
    txSlot* view = dispatch->next;
1258
17
    txSlot* buffer = view->next;
1259
17
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1260
17
    txSlot* arrayBuffer = buffer->value.reference->next;
1261
17
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1262
17
    if (id || (index >= length))
1263
1
      return 0;
1264
16
    if (arrayBuffer->flag & XS_DONT_SET_FLAG) {
1265
0
      if ((mask & XS_DONT_DELETE_FLAG) && !(slot->flag & XS_DONT_DELETE_FLAG))
1266
0
        return 0;
1267
0
      if ((mask & XS_DONT_ENUM_FLAG) && (slot->flag & XS_DONT_ENUM_FLAG))
1268
0
        return 0;
1269
0
      if (mask & XS_ACCESSOR_FLAG)
1270
0
        return 0;
1271
0
      if ((mask & XS_DONT_SET_FLAG) && !(slot->flag & XS_DONT_SET_FLAG))
1272
0
        return 0;
1273
0
      if (slot->kind != XS_UNINITIALIZED_KIND) {
1274
0
        txSlot* property;
1275
0
        txBoolean result = 1;
1276
0
        mxTemporary(property);
1277
0
        (*dispatch->value.typedArray.dispatch->getter)(the, arrayBuffer, view->value.dataView.offset + (index << shift), property, EndianNative);
1278
0
        result = fxIsSameValue(the, property, slot, 0);
1279
0
        mxPop();
1280
0
        return result;
1281
0
      }
1282
0
      return 1;
1283
0
    }
1284
16
    if ((mask & XS_DONT_DELETE_FLAG) && (slot->flag & XS_DONT_DELETE_FLAG))
1285
1
      return 0;
1286
15
    if ((mask & XS_DONT_ENUM_FLAG) && (slot->flag & XS_DONT_ENUM_FLAG))
1287
0
      return 0;
1288
15
    if (mask & XS_ACCESSOR_FLAG)
1289
0
      return 0;
1290
15
    if ((mask & XS_DONT_SET_FLAG) && (slot->flag & XS_DONT_SET_FLAG))
1291
0
      return 0;
1292
15
    if (slot->kind != XS_UNINITIALIZED_KIND) {
1293
15
      dispatch->value.typedArray.dispatch->coerce(the, slot);
1294
15
      length = fxGetDataViewSize(the, view, buffer) >> shift;
1295
15
      if (index < length)
1296
15
        (*dispatch->value.typedArray.dispatch->setter)(the, arrayBuffer, view->value.dataView.offset + (index << shift), slot, EndianNative);
1297
15
    }
1298
15
    return 1;
1299
15
  }
1300
2
  return fxOrdinaryDefineOwnProperty(the, instance, id, index, slot, mask);
1301
19
}
1302
1303
txBoolean fxTypedArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
1304
131k
{
1305
131k
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1306
79
    txSlot* dispatch = instance->next;
1307
79
    txSlot* view = dispatch->next;
1308
79
    txSlot* buffer = view->next;
1309
79
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1310
79
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1311
79
    return ((!id) && (index < length)) ? 0 : 1;
1312
79
  }
1313
131k
  return fxOrdinaryDeleteProperty(the, instance, id, index);
1314
131k
}
1315
1316
txBoolean fxTypedArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot)
1317
286k
{
1318
286k
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1319
286k
    txSlot* dispatch = instance->next;
1320
286k
    txSlot* view = dispatch->next;
1321
286k
    txSlot* buffer = view->next;
1322
286k
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1323
286k
    txSlot* arrayBuffer = buffer->value.reference->next;
1324
286k
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1325
286k
    if ((!id) && (index < length)) {
1326
286k
      (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset + (index << shift), slot, EndianNative);
1327
286k
      if (arrayBuffer->flag & XS_DONT_SET_FLAG)
1328
0
        slot->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG;
1329
286k
      return 1;
1330
286k
    }
1331
0
    slot->kind = XS_UNDEFINED_KIND;
1332
0
    slot->flag = XS_NO_FLAG;
1333
0
    return 0;
1334
286k
  }
1335
3
  return fxOrdinaryGetOwnProperty(the, instance, id, index, slot);
1336
286k
}
1337
1338
txSlot* fxTypedArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1339
5.49M
{
1340
5.49M
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1341
5.27M
    the->scratch.value.at.id = id;
1342
5.27M
    the->scratch.value.at.index = index;
1343
5.27M
    return &mxTypedArrayAccessor;
1344
5.27M
  }
1345
223k
  return fxOrdinaryGetProperty(the, instance, id, index, flag);
1346
5.49M
}
1347
1348
txBoolean fxTypedArrayGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* receiver, txSlot* value)
1349
0
{
1350
0
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1351
0
    txSlot* dispatch = instance->next;
1352
0
    txSlot* view = dispatch->next;
1353
0
    txSlot* buffer = view->next;
1354
0
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1355
0
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1356
0
    if ((!id) && (index < length)) {
1357
0
      (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset + (index << shift), value, EndianNative);
1358
0
      return 1;
1359
0
    }
1360
0
    value->kind = XS_UNDEFINED_KIND;
1361
0
    return 0;
1362
0
  }
1363
0
  return fxOrdinaryGetPropertyValue(the, instance, id, index, receiver, value);
1364
0
}
1365
1366
txBoolean fxTypedArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
1367
4.13M
{
1368
4.13M
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1369
4.13M
    txSlot* dispatch = instance->next;
1370
4.13M
    txSlot* view = dispatch->next;
1371
4.13M
    txSlot* buffer = view->next;
1372
4.13M
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1373
4.13M
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1374
4.13M
    return ((!id) && (index < length)) ? 1 : 0;
1375
4.13M
  }
1376
356
  return fxOrdinaryHasProperty(the, instance, id, index);
1377
4.13M
}
1378
1379
void fxTypedArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys)
1380
92.8k
{
1381
92.8k
  if (flag & XS_EACH_NAME_FLAG) {
1382
92.8k
    txSlot* dispatch = instance->next;
1383
92.8k
    txSlot* view = dispatch->next;
1384
92.8k
    txSlot* buffer = view->next;
1385
92.8k
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1386
92.8k
    txIndex length = fxGetDataViewSize(the, view, buffer) >> shift;
1387
92.8k
    if (length) {
1388
90.8k
      txIndex index;
1389
377k
      for (index = 0; index < length; index++)
1390
286k
        keys = fxQueueKey(the, 0, index, keys);
1391
90.8k
    }
1392
92.8k
  }
1393
92.8k
  fxOrdinaryOwnKeys(the, instance, flag, keys);
1394
92.8k
}
1395
1396
txBoolean fxTypedArrayPreventExtensions(txMachine* the, txSlot* instance)
1397
4
{
1398
4
  txSlot* dispatch = instance->next;
1399
4
  txSlot* view = dispatch->next;
1400
4
  txSlot* buffer = view->next;
1401
4
  txSlot* arrayBuffer = buffer->value.reference->next;
1402
4
  txSlot* bufferInfo = arrayBuffer->next;
1403
4
  if ((arrayBuffer->kind == XS_ARRAY_BUFFER_KIND) && (bufferInfo->value.bufferInfo.maxLength >= 0))
1404
0
    return 0;
1405
4
  return fxOrdinaryPreventExtensions(the, instance);
1406
4
}
1407
1408
txSlot* fxTypedArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1409
532k
{
1410
532k
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1411
501k
    the->scratch.value.at.id = id;
1412
501k
    the->scratch.value.at.index = index;
1413
501k
    return &mxTypedArrayAccessor;
1414
501k
  }
1415
31.0k
  return fxOrdinarySetProperty(the, instance, id, index, flag);
1416
532k
}
1417
1418
txBoolean fxTypedArraySetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver)
1419
501k
{
1420
501k
  if ((!id) || fxIsCanonicalIndex(the, id)) {
1421
501k
    txSlot* dispatch = instance->next;
1422
501k
    txSlot* view = dispatch->next;
1423
501k
    txSlot* buffer = view->next;
1424
501k
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1425
501k
    txSlot* arrayBuffer = buffer->value.reference->next;
1426
501k
    txIndex length;
1427
501k
    if (arrayBuffer->flag & XS_DONT_SET_FLAG)
1428
0
      return 0;
1429
501k
    if ((receiver->kind == XS_REFERENCE_KIND) && (receiver->value.reference == instance)) {
1430
501k
      dispatch->value.typedArray.dispatch->coerce(the, value);
1431
501k
      length = fxGetDataViewSize(the, view, buffer) >> shift;
1432
501k
      if ((!id) && (index < length)) {
1433
497k
        (*dispatch->value.typedArray.dispatch->setter)(the, buffer->value.reference->next, view->value.dataView.offset + (index << shift), value, EndianNative);
1434
497k
      }
1435
501k
      return 1;
1436
501k
    }
1437
3
    length = fxGetDataViewSize(the, view, buffer) >> shift;
1438
3
    if ((id) || (index >= length)) {
1439
2
      return 1;
1440
2
    }
1441
3
  }
1442
3
  return fxOrdinarySetPropertyValue(the, instance, id, index, value, receiver);
1443
501k
}
1444
1445
void fxCallTypedArrayItem(txMachine* the, txSlot* function, txSlot* dispatch, txSlot* view, txSlot* data, txInteger index, txSlot* item)
1446
3
{
1447
  /* THIS */
1448
3
  if (mxArgc > 1)
1449
0
    mxPushSlot(mxArgv(1));
1450
3
  else
1451
3
    mxPushUndefined();
1452
  /* FUNCTION */
1453
3
  mxPushSlot(function);
1454
3
  mxCall();
1455
  /* ARGUMENTS */
1456
3
  mxPushSlot(mxThis);
1457
3
  mxGetIndex(index);
1458
3
  if (item) {
1459
0
    item->kind = the->stack->kind;
1460
0
    item->value = the->stack->value;
1461
0
  }
1462
3
  mxPushInteger(index);
1463
3
  mxPushSlot(mxThis);
1464
3
  mxRunCount(3);
1465
3
}
1466
1467
void fxCheckTypedArrayContentType(txMachine* the, txSlot* dispatch, txSlot* sourceDispatch)
1468
26.1k
{
1469
26.1k
  txBoolean contentType = (dispatch->value.typedArray.dispatch->constructorID == _BigInt64Array)
1470
26.1k
      || (dispatch->value.typedArray.dispatch->constructorID == _BigUint64Array);
1471
26.1k
  txBoolean sourceContentType = (sourceDispatch->value.typedArray.dispatch->constructorID == _BigInt64Array)
1472
26.1k
      || (sourceDispatch->value.typedArray.dispatch->constructorID == _BigUint64Array);
1473
26.1k
  if (contentType != sourceContentType)
1474
3
    mxTypeError("incompatible content type");
1475
26.1k
}
1476
1477
txSlot* fxCheckTypedArrayInstance(txMachine* the, txSlot* slot)
1478
516k
{
1479
516k
  if (slot->kind == XS_REFERENCE_KIND) {
1480
515k
        txSlot* instance = slot->value.reference;
1481
515k
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_TYPED_ARRAY_KIND))
1482
515k
      return instance;
1483
515k
  }
1484
516k
  mxTypeError("this: not a TypedArray instance");
1485
0
  return C_NULL;
1486
516k
}
1487
1488
txSlot* fxConstructTypedArray(txMachine* the)
1489
788k
{
1490
788k
  txSlot* prototype;
1491
788k
  txSlot* dispatch;
1492
788k
  txSlot* instance;
1493
788k
  dispatch = mxFunctionInstanceHome(mxFunction->value.reference);
1494
788k
  dispatch = dispatch->next;
1495
788k
  prototype = mxBehaviorGetProperty(the, mxFunction->value.reference, mxID(_prototype), 0, XS_ANY);
1496
788k
  if (!dispatch || (dispatch->kind != XS_TYPED_ARRAY_KIND))
1497
16
    mxTypeError("new: TypedArray");
1498
788k
  mxPushSlot(mxTarget);
1499
788k
  fxGetPrototypeFromConstructor(the, prototype);
1500
788k
  instance = fxNewTypedArrayInstance(the, dispatch->value.typedArray.dispatch, dispatch->value.typedArray.atomics);
1501
788k
  mxPullSlot(mxResult);
1502
788k
  return instance;
1503
788k
}
1504
1505
void fxCreateTypedArraySpecies(txMachine* the)
1506
23.6k
{
1507
23.6k
  txSlot* instance = fxToInstance(the, mxThis);
1508
23.6k
  txSlot* dispatch = instance->next;
1509
23.6k
  txSlot* constructor = &the->stackIntrinsics[-1 - (txInteger)dispatch->value.typedArray.dispatch->constructorID];
1510
23.6k
  mxPushSlot(mxThis);
1511
23.6k
  mxGetID(mxID(_constructor));
1512
23.6k
  fxToSpeciesConstructor(the, constructor);
1513
23.6k
  mxNew();
1514
23.6k
}
1515
1516
void fxReduceTypedArrayItem(txMachine* the, txSlot* function, txSlot* dispatch, txSlot* view, txSlot* data, txInteger index)
1517
1.12M
{
1518
  /* THIS */
1519
1.12M
  mxPushUndefined();
1520
  /* FUNCTION */
1521
1.12M
  mxPushSlot(function);
1522
1.12M
  mxCall();
1523
  /* ARGUMENTS */
1524
1.12M
  mxPushSlot(mxResult);
1525
1.12M
  mxPushSlot(mxThis);
1526
1.12M
  mxGetIndex(index);
1527
1.12M
  mxPushInteger(index);
1528
1.12M
  mxPushSlot(mxThis);
1529
1.12M
  mxRunCount(4);
1530
1.12M
  mxPullSlot(mxResult);
1531
1.12M
}
1532
1533
txSlot* fxNewTypedArrayInstance(txMachine* the, txTypeDispatch* dispatch, txTypeAtomics* atomics)
1534
788k
{
1535
788k
  txSlot* instance;
1536
788k
  txSlot* property;
1537
788k
  instance = fxNewObjectInstance(the);
1538
788k
  instance->flag |= XS_EXOTIC_FLAG;
1539
788k
  property = fxNextTypeDispatchProperty(the, instance, dispatch, atomics, XS_TYPED_ARRAY_BEHAVIOR, XS_INTERNAL_FLAG);
1540
788k
  property = property->next = fxNewSlot(the);
1541
788k
  property->flag = XS_INTERNAL_FLAG;
1542
788k
  property->kind = XS_DATA_VIEW_KIND;
1543
788k
  property->value.dataView.offset = 0;
1544
788k
  property->value.dataView.size = 0;
1545
788k
  property = fxNextNullProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
1546
788k
  return instance;
1547
788k
}
1548
1549
void fx_TypedArray(txMachine* the)
1550
789k
{
1551
789k
  if (!mxHasTarget)
1552
497
    mxTypeError("call: TypedArray");
1553
788k
  if (mxArgc > 0) {
1554
787k
    if (mxArgv(0)->kind == XS_REFERENCE_KIND) {
1555
230k
      txSlot* instance = fxConstructTypedArray(the);
1556
230k
      txSlot* dispatch = instance->next;
1557
230k
      txSlot* view = dispatch->next;
1558
230k
      txSlot* buffer = view->next;
1559
230k
      txSlot* data = C_NULL;
1560
230k
      txU2 shift = dispatch->value.typedArray.dispatch->shift;
1561
230k
      txSlot* slot = mxArgv(0)->value.reference->next;
1562
230k
      if (slot && ((slot->kind == XS_ARRAY_BUFFER_KIND) || (slot->kind == XS_HOST_KIND))) {
1563
30.8k
        txInteger offset = fxArgToByteLength(the, 1, 0);
1564
30.8k
        txInteger size;
1565
30.8k
        txSlot* info;
1566
30.8k
        if (offset & ((1 << shift) - 1))
1567
1
          mxRangeError("invalid byteOffset %ld", offset);
1568
30.8k
        size = fxArgToByteLength(the, 2, -1);
1569
30.8k
        info = fxGetBufferInfo(the, mxArgv(0));
1570
30.8k
        if (size >= 0) {
1571
20
          txInteger delta = (size <= (INT_MAX >> shift)) ? size << shift : -1;
1572
20
          txInteger end = fxAddChunkSizes(the, offset, delta);
1573
20
          if ((info->value.bufferInfo.length < end) || (end < offset))
1574
1
            mxRangeError("invalid length %ld", size);
1575
19
          size = delta;
1576
19
        }
1577
30.8k
        else if (info->value.bufferInfo.maxLength >= 0) {
1578
2.11k
          if (info->value.bufferInfo.length < offset)
1579
1
            mxRangeError("invalid offset %ld", offset);
1580
2.11k
          size = -1;
1581
2.11k
        }
1582
28.6k
        else {
1583
28.6k
          if (info->value.bufferInfo.length & ((1 << shift) - 1))
1584
2.60k
            mxRangeError("invalid byteLength %ld", info->value.bufferInfo.length);
1585
26.0k
          size = info->value.bufferInfo.length - offset;
1586
26.0k
          if (size < 0)
1587
1
            mxRangeError("invalid byteLength %ld", size);
1588
26.0k
        }
1589
28.2k
        view->value.dataView.offset = offset;
1590
28.2k
        view->value.dataView.size = size;
1591
28.2k
        buffer->kind = XS_REFERENCE_KIND;
1592
28.2k
        buffer->value.reference = mxArgv(0)->value.reference;
1593
28.2k
      }
1594
199k
      else if (slot && (slot->kind == XS_TYPED_ARRAY_KIND)) {
1595
2.51k
        txSlot* sourceDispatch = slot;
1596
2.51k
        txSlot* sourceView = sourceDispatch->next;
1597
2.51k
        txSlot* sourceBuffer = sourceView->next;
1598
2.51k
        txU2 sourceShift = sourceDispatch->value.typedArray.dispatch->shift;
1599
2.51k
        txInteger sourceLength = fxCheckDataViewSize(the, sourceView, sourceBuffer, XS_IMMUTABLE) >> sourceShift;
1600
2.51k
        txSlot* sourceData = sourceBuffer->value.reference->next;
1601
2.51k
        txInteger sourceDelta = sourceDispatch->value.typedArray.dispatch->size;
1602
2.51k
        txInteger sourceOffset = sourceView->value.dataView.offset;
1603
2.51k
        txInteger offset = 0;
1604
2.51k
        if (sourceLength > (INT_MAX >> shift))
1605
0
          fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
1606
2.51k
        txInteger size = sourceLength << shift;
1607
        /* TARGET */
1608
2.51k
        mxPush(mxArrayBufferConstructor);
1609
        /* THIS */
1610
2.51k
        mxPushUninitialized();
1611
        /* FUNCTION */
1612
2.51k
        mxPush(mxArrayBufferConstructor);
1613
        /* RESULT */
1614
2.51k
        mxPushUndefined();
1615
        /* FRAME */
1616
2.51k
        mxPushUninitialized();
1617
2.51k
        the->stack->flag |= XS_TARGET_FLAG; 
1618
        /* ARGUMENTS */
1619
2.51k
        sourceLength = fxGetDataViewSize(the, sourceView, sourceBuffer) >> sourceShift;
1620
2.51k
        size = sourceLength << shift;
1621
2.51k
        mxPushInteger(size);
1622
2.51k
        mxRunCount(1);
1623
2.51k
        mxPullSlot(buffer);
1624
2.51k
        sourceLength = fxCheckDataViewSize(the, sourceView, sourceBuffer, XS_IMMUTABLE) >> sourceShift;
1625
2.51k
        size = sourceLength << shift;
1626
        
1627
2.51k
        data = fxCheckArrayBufferDetached(the, buffer);
1628
2.51k
        fxCheckArrayBufferMutable(the, buffer);
1629
2.51k
        view->value.dataView.offset = offset;
1630
2.51k
        view->value.dataView.size = size;
1631
2.51k
        if (dispatch == sourceDispatch)
1632
0
          c_memcpy(data->value.arrayBuffer.address + offset, sourceData->value.arrayBuffer.address + sourceOffset, size);
1633
2.51k
        else {
1634
2.51k
          fxCheckTypedArrayContentType(the, dispatch, sourceDispatch);
1635
2.51k
          mxPushUndefined();
1636
10.2k
          while (offset < size) {
1637
7.71k
            (*sourceDispatch->value.typedArray.dispatch->getter)(the, sourceData, sourceOffset, the->stack, EndianNative);
1638
7.71k
            (*dispatch->value.typedArray.dispatch->coerce)(the, the->stack);
1639
7.71k
            (*dispatch->value.typedArray.dispatch->setter)(the, data, offset, the->stack, EndianNative);
1640
7.71k
            sourceOffset += sourceDelta;
1641
7.71k
            offset += 1 << shift;
1642
7.71k
          }
1643
2.51k
          mxPop();
1644
2.51k
        }
1645
2.51k
      }
1646
197k
      else {
1647
197k
        fx_TypedArray_from_object(the, instance, C_NULL, C_NULL);
1648
197k
      }
1649
227k
      return;
1650
230k
    }
1651
556k
    fxToNumber(the, mxArgv(0));
1652
556k
  }
1653
558k
  {
1654
558k
        txInteger length = fxArgToByteLength(the, 0, 0);
1655
558k
    txSlot* instance = fxConstructTypedArray(the);
1656
558k
    txSlot* dispatch = instance->next;
1657
558k
    txSlot* view = dispatch->next;
1658
558k
    txSlot* buffer = view->next;
1659
558k
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
1660
558k
       if (length > (0x7FFFFFFF >> shift))
1661
1
      mxRangeError("byteLength too big");
1662
558k
        length <<= shift;
1663
558k
    mxPush(mxArrayBufferConstructor);
1664
558k
    mxNew();
1665
558k
    mxPushInteger(length);
1666
558k
    mxRunCount(1);
1667
558k
    mxPullSlot(buffer);
1668
558k
        view->value.dataView.offset = 0;
1669
558k
        view->value.dataView.size = length;
1670
558k
  }
1671
558k
}
1672
1673
void fx_TypedArray_from(txMachine* the)
1674
33
{
1675
33
  txSlot* function = C_NULL;
1676
33
  txSlot* _this = C_NULL;
1677
33
  if (!mxIsReference(mxThis) || !(mxIsConstructor(mxThis->value.reference)))
1678
2
    mxTypeError("this: not a constructor");
1679
31
  if (mxArgc > 1) {
1680
19
    txSlot* slot = mxArgv(1);
1681
19
    if (!mxIsUndefined(slot)) {
1682
18
      function = slot;
1683
18
      if (!fxIsCallable(the, function))
1684
11
        mxTypeError("map: not a function");
1685
7
      if (mxArgc > 2)
1686
0
        _this = mxArgv(2);
1687
7
    }
1688
19
  }
1689
20
  fx_TypedArray_from_object(the, C_NULL, function, _this);
1690
20
}
1691
1692
void fx_TypedArray_from_object(txMachine* the, txSlot* instance, txSlot* function, txSlot* _this)
1693
197k
{
1694
197k
  txSlot* stack = the->stack;
1695
197k
  txSlot* iterator;
1696
197k
  txSlot* next;
1697
197k
  txSlot* value;
1698
197k
  txSlot* list = C_NULL;
1699
197k
  txSlot* slot;
1700
197k
  txSlot* dispatch;
1701
197k
  txSlot* view;
1702
197k
  txSlot* buffer;
1703
197k
  txSlot* data;
1704
197k
  txNumber length;
1705
197k
  mxTemporary(iterator);
1706
197k
  mxTemporary(next);
1707
197k
  if (fxGetIterator(the, mxArgv(0), iterator, next, 1)) {
1708
168k
    list = fxNewInstance(the);
1709
168k
    slot = list;
1710
168k
    length = 0;
1711
168k
    mxTemporary(value);
1712
520k
    while (fxIteratorNext(the, iterator, next, value)) {
1713
352k
      slot = fxNextSlotProperty(the, slot, value, XS_NO_ID, XS_NO_FLAG);
1714
352k
      length++;
1715
352k
    }
1716
168k
  }
1717
29.0k
  else {
1718
29.0k
    mxPushSlot(mxArgv(0));
1719
29.0k
    mxGetID(mxID(_length));
1720
29.0k
    length = fxToLength(the, the->stack);
1721
29.0k
    mxPop();
1722
29.0k
  }
1723
197k
  if (instance) {
1724
197k
    dispatch = instance->next;
1725
197k
    view = dispatch->next;
1726
197k
    buffer = view->next;
1727
197k
    mxPush(mxArrayBufferConstructor);
1728
197k
    mxNew();
1729
197k
    mxPushNumber(length * dispatch->value.typedArray.dispatch->size);
1730
197k
    mxRunCount(1);
1731
197k
    mxPullSlot(buffer);
1732
197k
    data = fxCheckArrayBufferDetached(the, buffer);
1733
197k
    fxCheckArrayBufferMutable(the, buffer);
1734
197k
    view->value.dataView.offset = 0;
1735
197k
    view->value.dataView.size = data->next->value.bufferInfo.length;
1736
197k
  }
1737
20
  else {
1738
20
    mxPushSlot(mxThis);
1739
20
    mxNew();
1740
20
    mxPushNumber(length);
1741
20
    mxRunCount(1);
1742
20
    mxPullSlot(mxResult);
1743
20
    instance = fxToInstance(the, mxResult);
1744
20
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_TYPED_ARRAY_KIND)) {
1745
14
      dispatch = instance->next;
1746
14
      view = dispatch->next;
1747
14
      buffer = view->next;
1748
14
      data = fxCheckArrayBufferDetached(the, buffer);
1749
14
      fxCheckArrayBufferMutable(the, buffer);
1750
14
      if (length > (fxGetDataViewSize(the, view, buffer) >> dispatch->value.typedArray.dispatch->shift))
1751
0
        mxTypeError("result: too small TypedArray instance");
1752
14
    }
1753
6
    else
1754
6
      mxTypeError("result: not a TypedArray instance");
1755
20
  }
1756
197k
  if (list) {
1757
168k
    txInteger index = 0;
1758
168k
    slot = list->next;
1759
520k
    while (slot) {
1760
      /* ARG0 */
1761
352k
      if (function) {
1762
        /* THIS */
1763
12
        if (_this)
1764
0
          mxPushSlot(_this);
1765
12
        else
1766
12
          mxPushUndefined();
1767
        /* FUNCTION */
1768
12
        mxPushSlot(function);
1769
12
        mxCall();
1770
        /* ARGUMENTS */
1771
12
        mxPushSlot(slot);
1772
12
        mxPushInteger(index);
1773
12
        mxRunCount(2);
1774
12
      }
1775
352k
      else
1776
352k
        mxPushSlot(slot);
1777
352k
      mxPushSlot(mxResult);
1778
352k
      mxSetIndex(index);
1779
352k
      mxPop();
1780
352k
      index++;
1781
352k
      slot = slot->next;
1782
352k
    }
1783
168k
  }
1784
29.0k
  else {
1785
29.0k
    txInteger index = 0;
1786
29.0k
    txInteger count = (txInteger)length;
1787
108k
    while (index < count) {
1788
79.6k
      if (function) {
1789
        /* THIS */
1790
0
        if (_this)
1791
0
          mxPushSlot(_this);
1792
0
        else
1793
0
          mxPushUndefined();
1794
        /* FUNCTION */
1795
0
        mxPushSlot(function);
1796
0
        mxCall();
1797
        /* ARGUMENTS */
1798
0
        mxPushSlot(mxArgv(0));
1799
0
        mxGetIndex(index);
1800
0
        mxPushInteger(index);
1801
0
        mxRunCount(2);
1802
0
      }
1803
79.6k
      else {
1804
79.6k
        mxPushSlot(mxArgv(0));
1805
79.6k
        mxGetIndex(index);
1806
79.6k
      }
1807
79.6k
      mxPushSlot(mxResult);
1808
79.6k
      mxSetIndex(index);
1809
79.6k
      mxPop();
1810
79.6k
      index++;
1811
79.6k
    }  
1812
29.0k
  }
1813
197k
  the->stack = stack;
1814
197k
}
1815
1816
void fx_TypedArray_of(txMachine* the)
1817
6
{
1818
6
  txInteger count = mxArgc;
1819
6
  txInteger index = 0;
1820
6
  mxPushSlot(mxThis);
1821
6
  mxNew();
1822
6
  mxPushInteger(count);
1823
6
  mxRunCount(1);
1824
6
  mxPullSlot(mxResult);
1825
6
  {
1826
6
    mxResultTypedArrayDeclarations;
1827
6
    txU2 shift = resultDispatch->value.typedArray.dispatch->shift;
1828
6
    if (resultLength < count)
1829
1
      mxTypeError("result: too small TypedArray instance");
1830
12
    while (index < count) {
1831
7
      (*resultDispatch->value.typedArray.dispatch->coerce)(the, mxArgv(index));
1832
7
      if (resultBuffer->value.arrayBuffer.address == C_NULL)
1833
0
        mxTypeError("detached buffer");
1834
7
      (*resultDispatch->value.typedArray.dispatch->setter)(the, resultBuffer->value.reference->next, resultView->value.dataView.offset + (index << shift), mxArgv(index), EndianNative);
1835
7
      index++;
1836
7
    }
1837
5
  }
1838
5
}
1839
1840
void fx_TypedArray_prototype_at(txMachine* the)
1841
3
{
1842
3
  mxTypedArrayDeclarations;
1843
3
  txInteger index = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
1844
3
  if (index < 0)
1845
0
    index = length + index;
1846
3
  if ((0 <= index) && (index < length)) {
1847
0
    mxPushSlot(mxThis);
1848
0
    mxGetIndex(index);
1849
0
    mxPullSlot(mxResult);
1850
0
  }
1851
3
}
1852
1853
void fx_TypedArray_prototype_buffer_get(txMachine* the)
1854
54
{
1855
54
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
1856
54
  txSlot* dispatch = instance->next;
1857
54
  txSlot* view = dispatch->next;
1858
54
  txSlot* buffer = view->next;
1859
54
  mxResult->kind = buffer->kind;
1860
54
  mxResult->value = buffer->value;
1861
54
}
1862
1863
void fx_TypedArray_prototype_byteLength_get(txMachine* the)
1864
44
{
1865
44
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
1866
44
  txSlot* dispatch = instance->next;
1867
44
  txSlot* view = dispatch->next;
1868
44
  txSlot* buffer = view->next;
1869
44
  txU2 shift = dispatch->value.typedArray.dispatch->shift;
1870
44
  mxResult->kind = XS_INTEGER_KIND;
1871
44
  mxResult->value.integer = fxGetDataViewSize(the, view, buffer) & ~((1 << shift) - 1);
1872
44
}
1873
1874
void fx_TypedArray_prototype_byteOffset_get(txMachine* the)
1875
48
{
1876
48
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
1877
48
  txSlot* dispatch = instance->next;
1878
48
  txSlot* view = dispatch->next;
1879
48
  txSlot* buffer = view->next;
1880
48
  txInteger offset = view->value.dataView.offset;
1881
48
  txInteger size = view->value.dataView.size;
1882
48
  txSlot* arrayBuffer = buffer->value.reference->next;
1883
48
  txSlot* bufferInfo = arrayBuffer->next;
1884
48
  mxResult->kind = XS_INTEGER_KIND;
1885
48
  mxResult->value.integer = 0;
1886
48
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
1887
0
    return;
1888
48
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
1889
15
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
1890
15
    if (offset > byteLength)
1891
1
      return;
1892
14
    size = (size < 0) ? byteLength : offset + size;
1893
14
    if (size > byteLength)
1894
0
      return;
1895
14
    size -= offset;
1896
14
  }
1897
47
  mxResult->value.integer = offset;
1898
47
}
1899
1900
void fx_TypedArray_prototype_copyWithin(txMachine* the)
1901
20
{
1902
20
  mxMutableTypedArrayDeclarations;
1903
20
  txInteger delta = dispatch->value.typedArray.dispatch->size;
1904
20
  txInteger target = fxArgToIndexInteger(the, 0, 0, length);
1905
20
  txInteger start = fxArgToIndexInteger(the, 1, 0, length);
1906
20
  txInteger end = fxArgToIndexInteger(the, 2, length, length);
1907
20
  txInteger count = end - start;
1908
20
  if (count > length - target)
1909
0
    count = length - target;
1910
20
  if (count > 0) {
1911
0
    txByte* address = buffer->value.reference->next->value.arrayBuffer.address;
1912
0
    txInteger offset = view->value.dataView.offset;
1913
0
    if (fxIsDataViewOutOfBound(the, view, buffer))
1914
0
      mxTypeError("out of bound buffer");
1915
0
    txInteger size = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE) & ~(delta - 1);
1916
0
    target = offset + (target * delta);
1917
0
    start = offset + (start * delta);
1918
0
    end = offset + size;
1919
0
    count = count * delta;
1920
0
    if (count > end - target)
1921
0
      count = end - target;
1922
0
    if (count > end - start)
1923
0
      count = end - start;
1924
0
    if (count > 0) {
1925
0
      c_memmove(address + target, address + start, count);
1926
0
      mxMeterSome((txU4)count * 2);
1927
0
    }
1928
0
  }
1929
20
  mxResult->kind = mxThis->kind;
1930
20
  mxResult->value = mxThis->value;
1931
20
}
1932
1933
void fx_TypedArray_prototype_entries(txMachine* the)
1934
32
{
1935
32
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
1936
32
  txSlot* dispatch = instance->next;
1937
32
  txSlot* view = dispatch->next;
1938
32
  txSlot* buffer = view->next;
1939
32
  txSlot* property;
1940
32
  fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
1941
32
  mxPush(mxArrayIteratorPrototype);
1942
32
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
1943
32
  property = fxNextIntegerProperty(the, property, 2, XS_NO_ID, XS_INTERNAL_FLAG);
1944
32
  mxPullSlot(mxResult);
1945
32
}
1946
1947
void fx_TypedArray_prototype_every(txMachine* the)
1948
20
{
1949
20
  mxTypedArrayDeclarations;
1950
20
  txSlot* function = fxArgToCallback(the, 0);
1951
20
  txInteger index = 0;
1952
20
  mxResult->kind = XS_BOOLEAN_KIND;
1953
20
  mxResult->value.boolean = 1;
1954
23
  while (index < length) {
1955
3
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
1956
3
    mxResult->value.boolean = fxToBoolean(the, the->stack++);
1957
3
    if (!mxResult->value.boolean)
1958
0
      break;
1959
3
    index++;
1960
3
  }
1961
20
}
1962
1963
void fx_TypedArray_prototype_fill(txMachine* the)
1964
545
{
1965
545
  mxMutableTypedArrayDeclarations;
1966
545
  txInteger delta, start, end, offset;
1967
545
  if (mxArgc > 0)
1968
132
    mxPushSlot(mxArgv(0));
1969
413
  else
1970
413
    mxPushUndefined();
1971
545
  (*dispatch->value.typedArray.dispatch->coerce)(the, the->stack);
1972
545
  delta = dispatch->value.typedArray.dispatch->size;
1973
545
  start = fxArgToIndexInteger(the, 1, 0, length);
1974
545
  end = fxArgToIndexInteger(the, 2, length, length);
1975
545
  offset = view->value.dataView.offset;
1976
545
  start *= delta;
1977
545
  end *= delta;
1978
545
  start += offset;
1979
545
  end += offset;
1980
545
  txInteger size = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE) & ~(delta - 1);
1981
545
  if (end > offset + size)
1982
0
    end = offset + size;
1983
1.91k
  while (start < end) {
1984
1.36k
    (*dispatch->value.typedArray.dispatch->setter)(the, buffer->value.reference->next, start, the->stack, EndianNative);
1985
1.36k
    start += delta;
1986
1.36k
  }
1987
545
  mxPop();
1988
545
  mxResult->kind = mxThis->kind;
1989
545
  mxResult->value = mxThis->value;
1990
545
}
1991
1992
void fx_TypedArray_prototype_filter(txMachine* the)
1993
20
{
1994
20
  mxTypedArrayDeclarations;
1995
20
  txSlot* function = fxArgToCallback(the, 0);
1996
20
  txSlot* list = fxNewInstance(the);
1997
20
  txSlot* slot = list;
1998
20
  txInteger count = 0;
1999
20
  txInteger index = 0;
2000
20
  mxPushUndefined();
2001
20
  while (index < length) {
2002
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, the->stack);
2003
0
    if (fxToBoolean(the, the->stack++)) {
2004
0
      count++;
2005
0
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2006
0
    }
2007
0
    index++;
2008
0
  }
2009
20
  mxPop();
2010
20
  fxCreateTypedArraySpecies(the);
2011
20
  mxPushNumber(count);
2012
20
  mxRunCount(1);
2013
20
  mxPullSlot(mxResult);
2014
20
  {
2015
20
    mxResultTypedArrayDeclarations;
2016
20
    txInteger resultOffset = 0;
2017
20
    txInteger resultSize = resultDispatch->value.typedArray.dispatch->size;
2018
20
    fxCheckTypedArrayContentType(the, resultDispatch, dispatch);
2019
20
    if (resultLength < count)
2020
0
      mxTypeError("result: too small TypedArray instance");
2021
20
    slot = list->next;
2022
20
    while (slot) {
2023
0
      (*resultDispatch->value.typedArray.dispatch->coerce)(the, slot);
2024
0
      (*resultDispatch->value.typedArray.dispatch->setter)(the, resultBuffer->value.reference->next, resultOffset, slot, EndianNative);
2025
0
      resultOffset += resultSize;
2026
0
      slot = slot->next;
2027
0
    }
2028
20
  }
2029
20
  mxPop();
2030
20
}
2031
2032
void fx_TypedArray_prototype_find(txMachine* the)
2033
23
{
2034
23
  mxTypedArrayDeclarations;
2035
23
  txSlot* function = fxArgToCallback(the, 0);
2036
23
  txInteger index = 0;
2037
23
  mxPushUndefined();
2038
23
  while (index < length) {
2039
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, the->stack);
2040
0
    if (fxToBoolean(the, the->stack++)) {
2041
0
      mxResult->kind = the->stack->kind;
2042
0
      mxResult->value = the->stack->value;
2043
0
      break;
2044
0
    }
2045
0
    index++;
2046
0
  }
2047
23
  mxPop();
2048
23
}
2049
2050
void fx_TypedArray_prototype_findIndex(txMachine* the)
2051
32
{
2052
32
  mxTypedArrayDeclarations;
2053
32
  txSlot* function = fxArgToCallback(the, 0);
2054
32
  txInteger index = 0;
2055
32
  mxResult->kind = XS_INTEGER_KIND;
2056
32
  mxResult->value.integer = -1;
2057
32
  while (index < length) {
2058
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
2059
0
    if (fxToBoolean(the, the->stack++)) {
2060
0
      mxResult->value.integer = index;
2061
0
      break;
2062
0
    }
2063
0
    index++;
2064
0
  }
2065
32
}
2066
2067
void fx_TypedArray_prototype_findLast(txMachine* the)
2068
11
{
2069
11
  mxTypedArrayDeclarations;
2070
11
  txSlot* function = fxArgToCallback(the, 0);
2071
11
  txInteger index = length;
2072
11
  mxPushUndefined();
2073
11
  while (index > 0) {
2074
0
    index--;
2075
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, the->stack);
2076
0
    if (fxToBoolean(the, the->stack++)) {
2077
0
      mxResult->kind = the->stack->kind;
2078
0
      mxResult->value = the->stack->value;
2079
0
      break;
2080
0
    }
2081
0
  }
2082
11
  mxPop();
2083
11
}
2084
2085
void fx_TypedArray_prototype_findLastIndex(txMachine* the)
2086
32
{
2087
32
  mxTypedArrayDeclarations;
2088
32
  txSlot* function = fxArgToCallback(the, 0);
2089
32
  txInteger index = length;
2090
32
  mxResult->kind = XS_INTEGER_KIND;
2091
32
  mxResult->value.integer = -1;
2092
32
  while (index > 0) {
2093
0
    index--;
2094
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
2095
0
    if (fxToBoolean(the, the->stack++)) {
2096
0
      mxResult->value.integer = index;
2097
0
      break;
2098
0
    }
2099
0
  }
2100
32
}
2101
2102
void fx_TypedArray_prototype_forEach(txMachine* the)
2103
24
{
2104
24
  mxTypedArrayDeclarations;
2105
24
  txSlot* function = fxArgToCallback(the, 0);
2106
24
  txInteger index = 0;
2107
24
  while (index < length) {
2108
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
2109
0
    mxPop();
2110
0
    index++;
2111
0
  }
2112
24
}
2113
2114
void fx_TypedArray_prototype_includes(txMachine* the)
2115
3.68k
{
2116
3.68k
  mxTypedArrayDeclarations;
2117
3.68k
  fxBoolean(the, mxResult, 0);
2118
3.68k
  if (length) {
2119
3.64k
    txInteger index = fxArgToIndexInteger(the, 1, 0, length);
2120
3.64k
    txSlot* argument;
2121
3.64k
    if (mxArgc > 0)
2122
8
      mxPushSlot(mxArgv(0));
2123
3.63k
    else
2124
3.63k
      mxPushUndefined();
2125
3.64k
    argument = the->stack;
2126
3.65k
    while (index < length) {
2127
13
      mxPushSlot(mxThis);
2128
13
      mxGetIndex(index);
2129
13
      if (fxIsSameValue(the, the->stack++, argument, 1)) {
2130
0
        mxResult->value.boolean = 1;
2131
0
        break;
2132
0
      }
2133
13
      index++;
2134
13
      mxCheckMetering();
2135
13
    }
2136
3.64k
    mxPop();
2137
3.64k
  }
2138
3.68k
}
2139
2140
void fx_TypedArray_prototype_indexOf(txMachine* the)
2141
29
{
2142
29
  mxTypedArrayDeclarations;
2143
29
  fxInteger(the, mxResult, -1);
2144
29
  if (length) {
2145
0
    txInteger index = fxArgToIndexInteger(the, 1, 0, length);
2146
0
    txSlot* argument;
2147
0
    if (mxArgc > 0)
2148
0
      mxPushSlot(mxArgv(0));
2149
0
    else
2150
0
      mxPushUndefined();
2151
0
    argument = the->stack;
2152
0
    while (index < length) {
2153
0
      mxPushSlot(mxThis);
2154
0
      if (fxHasIndex(the, index)) {
2155
0
        mxPushSlot(mxThis);
2156
0
        mxGetIndex(index);
2157
0
        if (fxIsSameSlot(the, the->stack++, argument)) {
2158
0
          mxResult->value.integer = index;
2159
0
          break;
2160
0
        }
2161
0
      }
2162
0
      index++;
2163
0
      mxCheckMetering();
2164
0
    }
2165
0
    mxPop();
2166
0
  }
2167
29
}
2168
2169
void fx_TypedArray_prototype_join(txMachine* the)
2170
30.7k
{
2171
30.7k
  mxTypedArrayDeclarations;
2172
30.7k
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2173
30.7k
  txInteger offset = view->value.dataView.offset;
2174
30.7k
  txInteger limit = offset + (length << dispatch->value.typedArray.dispatch->shift);
2175
30.7k
  txString string;
2176
30.7k
  txSlot* list = fxNewInstance(the);
2177
30.7k
  txSlot* slot = list;
2178
30.7k
  txBoolean comma = 0;
2179
30.7k
  txInteger size = 0;
2180
30.7k
  if ((mxArgc > 0) && (mxArgv(0)->kind != XS_UNDEFINED_KIND)) {
2181
4
    mxPushSlot(mxArgv(0));
2182
4
    string = fxToString(the, the->stack);
2183
4
    the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2184
4
    the->stack->value.key.sum = mxStringLength(the->stack->value.string);
2185
4
  }
2186
30.7k
  else {
2187
30.7k
    mxPushStringX(",");
2188
30.7k
    the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2189
30.7k
    the->stack->value.key.sum = 1;
2190
30.7k
  }
2191
30.7k
  length = offset + fxGetDataViewSize(the, view, buffer);
2192
2.58M
  while (offset < limit) {
2193
2.55M
    if (comma) {
2194
2.52M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2195
2.52M
            size = fxAddChunkSizes(the, size, slot->value.key.sum);
2196
2.52M
    }
2197
28.2k
    else
2198
28.2k
      comma = 1;
2199
2.55M
    if (offset < length) {
2200
2.55M
      mxPushUndefined();
2201
2.55M
      (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, offset, the->stack, EndianNative);
2202
2.55M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2203
2.55M
      string = fxToString(the, slot);
2204
2.55M
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
2205
2.55M
      slot->value.key.sum = mxStringLength(string);
2206
2.55M
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2207
2.55M
      mxPop();
2208
2.55M
    }
2209
2.55M
    offset += delta;
2210
2.55M
  }
2211
30.7k
  mxPop();
2212
30.7k
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
2213
30.7k
  slot = list->next;
2214
5.11M
  while (slot) {
2215
5.08M
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
2216
5.08M
    string += slot->value.key.sum;
2217
5.08M
    slot = slot->next;
2218
5.08M
  }
2219
30.7k
  *string = 0;
2220
30.7k
  mxResult->kind = XS_STRING_KIND;
2221
30.7k
  mxPop();
2222
30.7k
}
2223
2224
void fx_TypedArray_prototype_keys(txMachine* the)
2225
22
{
2226
22
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
2227
22
  txSlot* dispatch = instance->next;
2228
22
  txSlot* view = dispatch->next;
2229
22
  txSlot* buffer = view->next;
2230
22
  txSlot* property;
2231
22
  fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
2232
22
  mxPush(mxArrayIteratorPrototype);
2233
22
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
2234
22
  property = fxNextIntegerProperty(the, property, 1, XS_NO_ID, XS_INTERNAL_FLAG);
2235
22
  mxPullSlot(mxResult);
2236
22
}
2237
2238
void fx_TypedArray_prototype_lastIndexOf(txMachine* the)
2239
26
{
2240
26
  mxTypedArrayDeclarations;
2241
26
  fxInteger(the, mxResult, -1);
2242
26
  if (length) {
2243
0
    txIndex index = (txIndex)fxArgToLastIndex(the, 1, length, length);
2244
0
    txSlot* argument;
2245
0
    if (mxArgc > 0)
2246
0
      mxPushSlot(mxArgv(0));
2247
0
    else
2248
0
      mxPushUndefined();
2249
0
    argument = the->stack;
2250
0
    while (index > 0) {
2251
0
      index--;
2252
0
      mxPushSlot(mxThis);
2253
0
      if (fxHasIndex(the, index)) {
2254
0
        mxPushSlot(mxThis);
2255
0
        mxGetIndex(index);
2256
0
        if (fxIsSameSlot(the, the->stack++, argument)) {
2257
0
          mxResult->value.integer = index;
2258
0
          break;
2259
0
        }
2260
0
      }
2261
0
      mxCheckMetering();
2262
0
    }
2263
0
    mxPop();
2264
0
  }
2265
26
}
2266
2267
void fx_TypedArray_prototype_length_get(txMachine* the)
2268
6.72k
{
2269
6.72k
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
2270
6.72k
  txSlot* dispatch = instance->next;
2271
6.72k
  txSlot* view = dispatch->next;
2272
6.72k
  txSlot* buffer = view->next;
2273
6.72k
  txU2 shift = dispatch->value.typedArray.dispatch->shift;
2274
6.72k
  mxResult->kind = XS_INTEGER_KIND;
2275
6.72k
  mxResult->value.integer = fxGetDataViewSize(the, view, buffer) >> shift;
2276
6.72k
}
2277
2278
void fx_TypedArray_prototype_map(txMachine* the)
2279
25
{
2280
25
  mxTypedArrayDeclarations;
2281
25
  txSlot* function = fxArgToCallback(the, 0);
2282
25
  fxCreateTypedArraySpecies(the);
2283
25
  mxPushNumber(length);
2284
25
  mxRunCount(1);
2285
25
  mxPullSlot(mxResult);
2286
25
  {
2287
25
    mxResultTypedArrayDeclarations;
2288
25
    txU2 shift = resultDispatch->value.typedArray.dispatch->shift;
2289
25
    txInteger index = 0;
2290
25
    fxCheckTypedArrayContentType(the, resultDispatch, dispatch);
2291
25
    if (resultLength < length)
2292
0
      mxTypeError("result: too small TypedArray instance");
2293
25
    while (index < length) {
2294
0
      fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
2295
0
      if (resultBuffer->value.arrayBuffer.address == C_NULL)
2296
0
        mxTypeError("detached buffer");
2297
0
      (*resultDispatch->value.typedArray.dispatch->coerce)(the, the->stack);
2298
0
      (*resultDispatch->value.typedArray.dispatch->setter)(the, resultBuffer->value.reference->next, resultView->value.dataView.offset + (index << shift), the->stack, EndianNative);
2299
0
      mxPop();
2300
0
      index++;
2301
0
    }
2302
25
  }
2303
25
}
2304
2305
void fx_TypedArray_prototype_reduce(txMachine* the)
2306
6.42k
{
2307
6.42k
  mxTypedArrayDeclarations;
2308
6.42k
  txSlot* function = fxArgToCallback(the, 0);
2309
6.42k
  txInteger index = 0;
2310
6.42k
  if (mxArgc > 1)
2311
1
    *mxResult = *mxArgv(1);
2312
6.42k
  else if (index < length) {
2313
6.39k
    (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset, mxResult, EndianNative);
2314
6.39k
    index++;
2315
6.39k
  }
2316
25
  else
2317
25
    mxTypeError("no initial value");
2318
1.13M
  while (index < length) {
2319
1.12M
    fxReduceTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index);
2320
1.12M
    index++;
2321
1.12M
  }
2322
6.39k
}
2323
2324
void fx_TypedArray_prototype_reduceRight(txMachine* the)
2325
28
{
2326
28
  mxTypedArrayDeclarations;
2327
28
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2328
28
  txSlot* function = fxArgToCallback(the, 0);
2329
28
  txInteger index = length - 1;
2330
28
  if (mxArgc > 1)
2331
0
    *mxResult = *mxArgv(1);
2332
28
  else if (index >= 0) {
2333
0
    (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset + (index * delta), mxResult, EndianNative);
2334
0
    index--;
2335
0
  }
2336
28
  else
2337
28
    mxTypeError("no initial value");
2338
0
  while (index >= 0) {
2339
0
    fxReduceTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index);
2340
0
    index--;
2341
0
  }
2342
0
}
2343
2344
void fx_TypedArray_prototype_reverse(txMachine* the)
2345
29
{
2346
29
  mxMutableTypedArrayDeclarations;
2347
29
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2348
29
  if (length) {
2349
0
    txByte tmp;
2350
0
    txByte* first = buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset;
2351
0
    txByte* last = first + (length << dispatch->value.typedArray.dispatch->shift) - delta;
2352
0
    txInteger offset;
2353
0
    while (first < last) {
2354
0
      for (offset = 0; offset < delta; offset++) {
2355
0
        tmp = last[offset];
2356
0
        last[offset] = first[offset];
2357
0
        first[offset] = tmp;
2358
0
      }
2359
0
      first += delta;
2360
0
      last -= delta;
2361
0
    }
2362
0
    mxMeterSome(length * 4);
2363
0
  }
2364
29
  mxResult->kind = mxThis->kind;
2365
29
  mxResult->value = mxThis->value;
2366
29
}
2367
2368
void fx_TypedArray_prototype_set(txMachine* the)
2369
77
{
2370
77
  mxMutableTypedArrayDeclarations;
2371
77
  txSlot* source = fxArgToInstance(the, 0);
2372
77
  if (source->next && (source->next->kind == XS_TYPED_ARRAY_KIND)) {
2373
0
    txSlot* data = buffer->value.reference->next;
2374
0
    txInteger delta = dispatch->value.typedArray.dispatch->size;
2375
0
    txInteger target = fxArgToByteLength(the, 1, 0);
2376
0
    txInteger offset = view->value.dataView.offset + (target * delta);  
2377
0
    length = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE) >> dispatch->value.typedArray.dispatch->shift;
2378
0
    txSlot* sourceDispatch = source->next;
2379
0
    txSlot* sourceView = sourceDispatch->next;
2380
0
    txSlot* sourceBuffer = sourceView->next;
2381
0
    txU2 shift = sourceDispatch->value.typedArray.dispatch->shift;
2382
0
    txInteger sourceLength = fxCheckDataViewSize(the, sourceView, sourceBuffer, XS_IMMUTABLE) >> shift;
2383
0
    txInteger sourceOffset = sourceView->value.dataView.offset; 
2384
0
    txSlot* sourceData = sourceBuffer->value.reference->next;
2385
0
    txInteger limit = offset + (sourceLength * delta);
2386
0
    if ((length - sourceLength < target))   //@@ target can never be negative?
2387
0
      mxRangeError("invalid offset");
2388
0
    if (data == sourceData) {
2389
0
      txSlot* resultBuffer;
2390
0
      mxPush(mxArrayBufferConstructor);
2391
0
      mxNew();
2392
0
      mxPushInteger(sourceLength << shift);
2393
0
      mxRunCount(1);
2394
0
      resultBuffer = the->stack->value.reference->next;
2395
0
      c_memcpy(resultBuffer->value.arrayBuffer.address, sourceData->value.arrayBuffer.address + sourceOffset, sourceLength << shift);
2396
0
      sourceData = resultBuffer;
2397
0
      sourceOffset = 0;
2398
0
    }
2399
0
    else 
2400
0
      mxPushUndefined();
2401
0
    if (dispatch->value.typedArray.dispatch == sourceDispatch->value.typedArray.dispatch) {
2402
0
      if (data->value.arrayBuffer.address == C_NULL)
2403
0
        mxTypeError("detached buffer");
2404
0
      c_memcpy(data->value.arrayBuffer.address + offset, sourceData->value.arrayBuffer.address + sourceOffset, limit - offset);
2405
0
      mxMeterSome(((txU4)(limit - offset)) * 2);
2406
0
    }
2407
0
    else {
2408
0
      txInteger sourceDelta = 1 << shift;
2409
0
      mxPushUndefined();
2410
0
      while (offset < limit) {
2411
0
        (*sourceDispatch->value.typedArray.dispatch->getter)(the, sourceData, sourceOffset, the->stack, EndianNative);
2412
0
        (*dispatch->value.typedArray.dispatch->coerce)(the, the->stack);
2413
0
                if (data->value.arrayBuffer.address == C_NULL)
2414
0
                    mxTypeError("detached buffer");
2415
0
        (*dispatch->value.typedArray.dispatch->setter)(the, data, offset, the->stack, EndianNative);
2416
0
        sourceOffset += sourceDelta;
2417
0
        offset += delta;
2418
0
      }
2419
0
      mxPop();
2420
0
    }
2421
0
    mxPop();
2422
0
  }
2423
77
  else {
2424
77
    txNumber targetOffset = 0, targetLength, sourceLength;
2425
77
    txSlot *arg = mxArgv(1);
2426
77
    if ((mxArgc > 1) && (arg->kind != XS_UNDEFINED_KIND)) {
2427
0
      targetOffset = c_trunc(fxToNumber(the, arg));
2428
0
      if (c_isnan(targetOffset))
2429
0
        targetOffset = 0;
2430
0
      if (targetOffset < 0) 
2431
0
        mxRangeError("offset < 0");
2432
0
    }
2433
77
    if (fxIsDataViewOutOfBound(the, view, buffer))
2434
0
      mxTypeError("out of bound buffer");
2435
77
    targetLength = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE) >> dispatch->value.typedArray.dispatch->shift;
2436
77
    mxPushSlot(mxArgv(0));
2437
77
    mxGetID(mxID(_length));
2438
77
    sourceLength = fxToLength(the, the->stack);
2439
77
    mxPop();
2440
77
    if (sourceLength + targetOffset > targetLength)
2441
1
      mxRangeError("invalid offset");
2442
76
    txIndex count = (txIndex)sourceLength;
2443
76
    txIndex index = 0;
2444
76
    txIndex delta = (txIndex)targetOffset;
2445
134
    while (index < count) {
2446
58
      mxPushSlot(mxArgv(0));
2447
58
      mxGetIndex(index);
2448
58
      mxPushSlot(mxThis);
2449
58
      mxPushInteger(delta + index);
2450
58
      mxSetAt();
2451
58
      mxPop();
2452
58
      index++;
2453
58
      mxCheckMetering();
2454
58
    }  
2455
76
  }
2456
77
}
2457
2458
void fx_TypedArray_prototype_slice(txMachine* the)
2459
23.6k
{
2460
23.6k
  mxTypedArrayDeclarations;
2461
23.6k
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2462
23.6k
  txInteger start = fxArgToIndexInteger(the, 0, 0, length);
2463
23.6k
  txInteger end = fxArgToIndexInteger(the, 1, length, length);
2464
23.6k
  txInteger count = (end > start) ? end - start : 0;
2465
23.6k
  txInteger index = 0;
2466
23.6k
  fxCreateTypedArraySpecies(the);
2467
23.6k
  mxPushNumber(count);
2468
23.6k
  mxRunCount(1);
2469
23.6k
  mxPullSlot(mxResult);
2470
23.6k
  {
2471
23.6k
    mxResultTypedArrayDeclarations;
2472
23.6k
    fxCheckTypedArrayContentType(the, resultDispatch, dispatch);
2473
23.6k
    if (resultLength < count)
2474
0
      mxTypeError("result: too small TypedArray instance");
2475
23.6k
    if (count) {
2476
13.8k
      length = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE) >> dispatch->value.typedArray.dispatch->shift;
2477
13.8k
      if ((end <= length) && (resultDispatch->value.typedArray.dispatch->constructorID == dispatch->value.typedArray.dispatch->constructorID) && (resultBuffer->value.reference != buffer->value.reference)) {
2478
13.8k
        txInteger shift = dispatch->value.typedArray.dispatch->shift;
2479
13.8k
        txSlot* data = buffer->value.reference->next;
2480
13.8k
        txSlot* resultData = resultBuffer->value.reference->next;
2481
13.8k
        txByte* address = data->value.arrayBuffer.address;
2482
13.8k
        txByte* resultAddress = resultData->value.arrayBuffer.address;
2483
13.8k
        address += view->value.dataView.offset;
2484
13.8k
        resultAddress += resultView->value.dataView.offset;
2485
13.8k
        c_memmove(resultAddress, address + (start << shift), count << shift);
2486
13.8k
        mxMeterSome(((txU4)(count)) * 2);
2487
13.8k
      }
2488
0
      else {
2489
0
        mxPushUndefined();
2490
0
        while ((start < length) && (start < end)) {
2491
0
          (*dispatch->value.typedArray.dispatch->getter)(the, buffer->value.reference->next, view->value.dataView.offset + (start * delta), the->stack, EndianNative);
2492
0
          (*resultDispatch->value.typedArray.dispatch->coerce)(the, the->stack);
2493
0
          (*resultDispatch->value.typedArray.dispatch->setter)(the, resultBuffer->value.reference->next, resultView->value.dataView.offset + (index << resultDispatch->value.typedArray.dispatch->shift), the->stack, EndianNative);
2494
0
          start++;
2495
0
          index++;
2496
0
        }
2497
0
        mxPop();
2498
0
      }
2499
13.8k
    }
2500
23.6k
  }
2501
23.6k
}
2502
2503
void fx_TypedArray_prototype_some(txMachine* the)
2504
25
{
2505
25
  mxTypedArrayDeclarations;
2506
25
  txSlot* function = fxArgToCallback(the, 0);
2507
25
  txInteger index = 0;
2508
25
  mxResult->kind = XS_BOOLEAN_KIND;
2509
25
  mxResult->value.boolean = 0;
2510
25
  while (index < length) {
2511
0
    fxCallTypedArrayItem(the, function, dispatch, view, buffer->value.reference->next, index, C_NULL);
2512
0
    mxResult->value.boolean = fxToBoolean(the, the->stack++);
2513
0
    if (mxResult->value.boolean)
2514
0
      break;
2515
0
    index++;
2516
0
  }
2517
25
}
2518
2519
void fx_TypedArray_prototype_sort(txMachine* the)
2520
3.01k
{
2521
3.01k
  mxMutableTypedArrayDeclarations;
2522
3.01k
  txSlot* data = buffer->value.reference->next;
2523
3.01k
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2524
3.01k
  txSlot* function = C_NULL;
2525
3.01k
  if (mxArgc > 0) {
2526
2.98k
    txSlot* slot = mxArgv(0);
2527
2.98k
    if (slot->kind != XS_UNDEFINED_KIND) {
2528
2.98k
      if (fxIsCallable(the, slot))
2529
2.97k
        function = slot;
2530
1
      else
2531
1
        mxTypeError("compare: not a function");
2532
2.98k
    }
2533
2.98k
  }
2534
3.01k
  if (function)
2535
2.97k
    fxSortArrayItems(the, function, C_NULL, length, mxThis);
2536
35
  else
2537
35
    c_qsort(data->value.arrayBuffer.address + view->value.dataView.offset, length, delta, dispatch->value.typedArray.dispatch->compare);
2538
3.01k
  mxResult->kind = mxThis->kind;
2539
3.01k
  mxResult->value = mxThis->value;
2540
3.01k
}
2541
2542
void fx_TypedArray_prototype_subarray(txMachine* the)
2543
49
{
2544
49
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
2545
49
  txSlot* dispatch = instance->next;
2546
49
  txSlot* view = dispatch->next;
2547
49
  txSlot* buffer = view->next;
2548
49
    txU2 shift = dispatch->value.typedArray.dispatch->shift;
2549
49
    txInteger length = fxGetDataViewSize(the, view, buffer) >> shift;
2550
49
  txInteger start = fxArgToIndexInteger(the, 0, 0, length);
2551
49
  if ((view->value.dataView.size < 0) && ((mxArgc < 2) || mxIsUndefined(mxArgv(1)))) {
2552
6
    fxCreateTypedArraySpecies(the);
2553
6
    mxPushSlot(buffer);
2554
6
    mxPushInteger(view->value.dataView.offset + (start << shift));
2555
6
    mxRunCount(2);
2556
6
  }
2557
43
  else {
2558
43
    txInteger stop = fxArgToIndexInteger(the, 1, length, length);
2559
43
    if (stop < start) 
2560
0
      stop = start;
2561
43
    fxCreateTypedArraySpecies(the);
2562
43
    mxPushSlot(buffer);
2563
43
    mxPushInteger(view->value.dataView.offset + (start << shift));
2564
43
    mxPushInteger(stop - start);
2565
43
    mxRunCount(3);
2566
43
  }
2567
49
  mxPullSlot(mxResult);
2568
49
  instance = fxCheckTypedArrayInstance(the, mxResult);
2569
49
  fxCheckTypedArrayContentType(the, instance->next, dispatch);
2570
49
}
2571
2572
void fx_TypedArray_prototype_toLocaleString(txMachine* the)
2573
21
{
2574
21
  mxTypedArrayDeclarations;
2575
21
  txInteger index = 0;
2576
21
  txString string;
2577
21
  txSlot* list = fxNewInstance(the);
2578
21
  txSlot* slot = list;
2579
21
  txBoolean comma = 0;
2580
21
  txInteger size = 0;
2581
21
  mxPushStringX(",");
2582
21
  the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2583
21
  the->stack->value.key.sum = 1;
2584
21
  while (index < length) {
2585
0
    if (comma) {
2586
0
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2587
0
      size += slot->value.key.sum;
2588
0
    }
2589
0
    else
2590
0
      comma = 1;
2591
0
    mxPushSlot(mxThis);
2592
0
    mxGetIndex(index);
2593
0
    if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) {
2594
0
      mxDub();
2595
0
      mxGetID(mxID(_toLocaleString));
2596
0
      mxCall();
2597
0
      mxRunCount(0);
2598
0
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2599
0
      string = fxToString(the, slot);
2600
0
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
2601
0
      slot->value.key.sum = mxStringLength(string);
2602
0
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2603
0
    }
2604
0
    mxPop();
2605
0
    index++;
2606
0
  }
2607
21
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
2608
21
  slot = list->next;
2609
21
  while (slot) {
2610
0
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
2611
0
    string += slot->value.key.sum;
2612
0
    slot = slot->next;
2613
0
  }
2614
21
  *string = 0;
2615
21
  mxResult->kind = XS_STRING_KIND;
2616
21
  mxPop();
2617
21
}
2618
2619
void fx_TypedArray_prototype_toReversed(txMachine* the)
2620
59
{
2621
59
  mxTypedArrayDeclarations;
2622
59
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2623
59
  txSlot* constructor = &the->stackIntrinsics[-1 - (txInteger)dispatch->value.typedArray.dispatch->constructorID];
2624
59
  mxPushSlot(constructor);
2625
59
  mxNew();
2626
59
  mxPushInteger(length);
2627
59
  mxRunCount(1);
2628
59
  mxPullSlot(mxResult);
2629
59
  if (length) {
2630
0
    mxResultTypedArrayDeclarations;
2631
0
    txByte* base = buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset;
2632
0
    txByte* from = base + (resultLength << dispatch->value.typedArray.dispatch->shift) - delta;
2633
0
    txByte* to = resultBuffer->value.reference->next->value.arrayBuffer.address;
2634
0
    while (from >= base) {
2635
0
      txInteger offset;
2636
0
      for (offset = 0; offset < delta; offset++)
2637
0
        *to++ = *from++;
2638
0
      from -= delta << 1;
2639
0
    }
2640
0
    mxMeterSome((txU4)length * 4);
2641
0
  }
2642
59
}
2643
2644
void fx_TypedArray_prototype_toSorted(txMachine* the)
2645
36
{
2646
36
  mxTypedArrayDeclarations;
2647
36
  txInteger delta = dispatch->value.typedArray.dispatch->size;
2648
36
  txSlot* constructor = &the->stackIntrinsics[-1 - (txInteger)dispatch->value.typedArray.dispatch->constructorID];
2649
36
  txSlot* function = C_NULL;
2650
36
  if (mxArgc > 0) {
2651
0
    txSlot* slot = mxArgv(0);
2652
0
    if (slot->kind != XS_UNDEFINED_KIND) {
2653
0
      if (fxIsCallable(the, slot))
2654
0
        function = slot;
2655
0
      else
2656
0
        mxTypeError("compare: not a function");
2657
0
    }
2658
0
  }
2659
36
  mxPushSlot(constructor);
2660
36
  mxNew();
2661
36
  mxPushInteger(length);
2662
36
  mxRunCount(1);
2663
36
  mxPullSlot(mxResult);
2664
36
  if (function)
2665
0
    fxSortArrayItems(the, function, C_NULL, length, mxResult);
2666
36
  else {
2667
36
    mxResultTypedArrayDeclarations;
2668
36
    txByte* from = buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset;
2669
36
    txByte* to = resultBuffer->value.reference->next->value.arrayBuffer.address;
2670
36
    c_memcpy(to, from,  resultLength << dispatch->value.typedArray.dispatch->shift);    
2671
36
    c_qsort(to, length, delta, dispatch->value.typedArray.dispatch->compare);
2672
36
  }
2673
36
}
2674
2675
void fx_TypedArray_prototype_toStringTag_get(txMachine* the)
2676
26
{
2677
26
  if (mxThis->kind == XS_REFERENCE_KIND) {
2678
18
        txSlot* instance = mxThis->value.reference;
2679
18
        txSlot* slot = instance->next;
2680
18
    if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_TYPED_ARRAY_KIND)) {
2681
0
      txTypeDispatch *dispatch = instance->next->value.typedArray.dispatch;
2682
0
      txSlot* key = fxGetKey(the, mxID(dispatch->constructorID));
2683
0
      if (key->kind == XS_KEY_X_KIND)
2684
0
        mxResult->kind = XS_STRING_X_KIND;
2685
0
      else
2686
0
        mxResult->kind = XS_STRING_KIND;
2687
0
      mxResult->value.string = key->value.key.string;
2688
0
    }
2689
18
  }
2690
26
}
2691
2692
void fx_TypedArray_prototype_values(txMachine* the)
2693
49
{
2694
49
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
2695
49
  txSlot* dispatch = instance->next;
2696
49
  txSlot* view = dispatch->next;
2697
49
  txSlot* buffer = view->next;
2698
49
  txSlot* property;
2699
49
  fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
2700
49
  mxPush(mxArrayIteratorPrototype);
2701
49
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
2702
49
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
2703
49
  mxPullSlot(mxResult);
2704
49
}
2705
2706
void fx_TypedArray_prototype_with(txMachine* the)
2707
59
{
2708
59
  mxTypedArrayDeclarations;
2709
59
  txSlot* constructor = &the->stackIntrinsics[-1 - (txInteger)dispatch->value.typedArray.dispatch->constructorID];
2710
59
  txInteger index = (txInteger)fxArgToRelativeIndex(the, 0, 0, length), count, i;
2711
59
  txSlot* value;
2712
59
  if (mxArgc > 1)
2713
7
    mxPushSlot(mxArgv(1));
2714
52
  else
2715
52
    mxPushUndefined();
2716
59
  value = the->stack; 
2717
59
  (*dispatch->value.typedArray.dispatch->coerce)(the, value);
2718
59
  count = fxGetDataViewSize(the, view, buffer) >> dispatch->value.typedArray.dispatch->shift;
2719
59
  if ((index < 0) || (count <= index))
2720
2
    mxRangeError("invalid index");
2721
57
  mxPushSlot(constructor);
2722
57
  mxNew();
2723
57
  mxPushInteger(length);
2724
57
  mxRunCount(1);
2725
57
  mxPullSlot(mxResult);
2726
57
  i = 0;
2727
66
  while (i < index) {
2728
9
    mxPushSlot(mxThis);
2729
9
    mxPushInteger(i);
2730
9
    mxGetAt();
2731
9
    mxPushSlot(mxResult);
2732
9
    mxPushInteger(i);
2733
9
    mxSetAt();
2734
9
    mxPop();
2735
9
    i++;
2736
9
    mxCheckMetering();
2737
9
  }
2738
57
  mxPushSlot(value);
2739
57
  mxPushSlot(mxResult);
2740
57
  mxPushInteger(i);
2741
57
  mxSetAt();
2742
57
  mxPop();
2743
57
  i++;
2744
104
  while (i < length) {
2745
47
    mxPushSlot(mxThis);
2746
47
    mxPushInteger(i);
2747
47
    mxGetAt();
2748
47
    mxPushSlot(mxResult);
2749
47
    mxPushInteger(i);
2750
47
    mxSetAt();
2751
47
    mxPop();
2752
47
    i++;
2753
47
    mxCheckMetering();
2754
47
  }
2755
57
  mxPop();
2756
57
}
2757
2758
#if mxBigEndian
2759
  #define mxEndianFloat16_BtoN(a) (a)
2760
  #define mxEndianFloat32_BtoN(a) (a)
2761
  #define mxEndianFloat64_BtoN(a) (a)
2762
  #define mxEndianS64_BtoN(a) (a)
2763
  #define mxEndianU64_BtoN(a) (a)
2764
  #define mxEndianS32_BtoN(a) (a)
2765
  #define mxEndianU32_BtoN(a) (a)
2766
  #define mxEndianS16_BtoN(a) (a)
2767
  #define mxEndianU16_BtoN(a) (a)
2768
2769
  #define mxEndianFloat16_NtoB(a) (a)
2770
  #define mxEndianFloat32_NtoB(a) (a)
2771
  #define mxEndianFloat64_NtoB(a) (a)
2772
  #define mxEndianS64_NtoB(a) (a)
2773
  #define mxEndianU64_NtoB(a) (a)
2774
  #define mxEndianS32_NtoB(a) (a)
2775
  #define mxEndianU32_NtoB(a) (a)
2776
  #define mxEndianS16_NtoB(a) (a)
2777
  #define mxEndianU16_NtoB(a) (a)
2778
#else
2779
19
  #define mxEndianFloat16_LtoN(a) (a)
2780
12
  #define mxEndianFloat32_LtoN(a) (a)
2781
13
  #define mxEndianFloat64_LtoN(a) (a)
2782
60
  #define mxEndianS64_LtoN(a) (a)
2783
34
  #define mxEndianU64_LtoN(a) (a)
2784
17
  #define mxEndianS32_LtoN(a) (a)
2785
32
  #define mxEndianU32_LtoN(a) (a)
2786
22
  #define mxEndianS16_LtoN(a) (a)
2787
13
  #define mxEndianU16_LtoN(a) (a)
2788
2789
  #define mxEndianFloat16_NtoL(a) (a)
2790
  #define mxEndianFloat32_NtoL(a) (a)
2791
  #define mxEndianFloat64_NtoL(a) (a)
2792
  #define mxEndianS64_NtoL(a) (a)
2793
  #define mxEndianU64_NtoL(a) (a)
2794
  #define mxEndianS32_NtoL(a) (a)
2795
  #define mxEndianU32_NtoL(a) (a)
2796
  #define mxEndianS16_NtoL(a) (a)
2797
  #define mxEndianU16_NtoL(a) (a)
2798
#endif
2799
2800
#if mxLittleEndian
2801
  #define mxEndianFloat16_BtoN(a) (mxEndianFloat16_Swap(a))
2802
92
  #define mxEndianFloat32_BtoN(a) (mxEndianFloat32_Swap(a))
2803
81
  #define mxEndianFloat64_BtoN(a) (mxEndianFloat64_Swap(a))
2804
134
  #define mxEndianS64_BtoN(a) ((txS8) mxEndian64_Swap(a))
2805
62
  #define mxEndianU64_BtoN(a) ((txU8) mxEndian64_Swap(a))
2806
86
  #define mxEndianS32_BtoN(a) ((txS4) mxEndian32_Swap(a))
2807
112
  #define mxEndianU32_BtoN(a) ((txU4) mxEndian32_Swap(a))
2808
100
  #define mxEndianS16_BtoN(a) ((txS2) mxEndian16_Swap(a))
2809
80
  #define mxEndianU16_BtoN(a) ((txU2) mxEndian16_Swap(a))
2810
2811
111
  #define mxEndianFloat16_NtoB(a) (mxEndianFloat16_Swap(a))
2812
94
  #define mxEndianFloat32_NtoB(a) (mxEndianFloat32_Swap(a))
2813
77
  #define mxEndianFloat64_NtoB(a) (mxEndianFloat64_Swap(a))
2814
85
  #define mxEndianS64_NtoB(a) ((txS8) mxEndian64_Swap(a))
2815
6
  #define mxEndianU64_NtoB(a) ((txU8) mxEndian64_Swap(a))
2816
88
  #define mxEndianS32_NtoB(a) ((txS4) mxEndian32_Swap(a))
2817
81
  #define mxEndianU32_NtoB(a) ((txU4) mxEndian32_Swap(a))
2818
96
  #define mxEndianS16_NtoB(a) ((txS2) mxEndian16_Swap(a))
2819
234
  #define mxEndianU16_NtoB(a) ((txU2) mxEndian16_Swap(a))
2820
#else
2821
  #define mxEndianFloat16_LtoN(a) (mxEndianFloat16_Swap(a))
2822
  #define mxEndianFloat32_LtoN(a) (mxEndianFloat32_Swap(a))
2823
  #define mxEndianFloat64_LtoN(a) (mxEndianFloat64_Swap(a))
2824
  #define mxEndianS64_LtoN(a) ((txS8) mxEndian64_Swap(a))
2825
  #define mxEndianU64_LtoN(a) ((txU8) mxEndian64_Swap(a))
2826
  #define mxEndianS32_LtoN(a) ((txS4) mxEndian32_Swap(a))
2827
  #define mxEndianU32_LtoN(a) ((txU4) mxEndian32_Swap(a))
2828
  #define mxEndianS16_LtoN(a) ((txS2) mxEndian16_Swap(a))
2829
  #define mxEndianU16_LtoN(a) ((txU2) mxEndian16_Swap(a))
2830
2831
  #define mxEndianFloat16_NtoL(a) (mxEndianFloat16_Swap(a))
2832
  #define mxEndianFloat32_NtoL(a) (mxEndianFloat32_Swap(a))
2833
  #define mxEndianFloat64_NtoL(a) (mxEndianFloat64_Swap(a))
2834
  #define mxEndianS64_NtoL(a) ((txS8) mxEndian64_Swap(a))
2835
  #define mxEndianU64_NtoL(a) ((txU8) mxEndian64_Swap(a))
2836
  #define mxEndianS32_NtoL(a) ((txS4) mxEndian32_Swap(a))
2837
  #define mxEndianU32_NtoL(a) ((txU4) mxEndian32_Swap(a))
2838
  #define mxEndianS16_NtoL(a) ((txS2) mxEndian16_Swap(a))
2839
  #define mxEndianU16_NtoL(a) ((txU2) mxEndian16_Swap(a))
2840
#endif
2841
2842
#if defined(__GNUC__) || defined(__llvm__)
2843
510
  #define mxEndian16_Swap(a) __builtin_bswap16(a)
2844
#else
2845
  static txU2 mxEndian16_Swap(txU2 a)
2846
  {
2847
    txU2 b;
2848
    txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
2849
    int i;
2850
    for (i = 0; i < 2; i++)
2851
      p2[i] = p1[1 - i];
2852
    return b;
2853
  }
2854
#endif
2855
2856
#if defined(__GNUC__) || defined(__llvm__)
2857
367
  #define mxEndian32_Swap(a) __builtin_bswap32(a)
2858
#else
2859
  static txU4 mxEndian32_Swap(txU4 a)
2860
  {
2861
    txU4 b;
2862
    txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
2863
    int i;
2864
    for (i = 0; i < 4; i++)
2865
      p2[i] = p1[3 - i];
2866
    return b;
2867
  }
2868
#endif
2869
2870
#if defined(__GNUC__) || defined(__llvm__)
2871
287
  #define mxEndian64_Swap(a) __builtin_bswap64(a)
2872
#else
2873
  static txU8 mxEndian64_Swap(txU8 a)
2874
  {
2875
    txU8 b;
2876
    txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
2877
    int i;
2878
    for (i = 0; i < 8; i++)
2879
      p2[i] = p1[7 - i];
2880
    return b;
2881
  }
2882
#endif
2883
2884
969
#define toNative(size, endian) mxEndian##size##_##endian##toN
2885
872
#define fromNative(size, endian) mxEndian##size##_Nto##endian
2886
8.12M
#define IMPORT(size) (endian == EndianBig ? toNative(size, B)(value) : endian == EndianLittle ? toNative(size, L)(value) : (value))
2887
413k
#define EXPORT(size) (endian == EndianBig ? fromNative(size, B)(value) : endian == EndianLittle ? toNative(size, L)(value) : (value))
2888
2889
int fxBigInt64Compare(const void* p, const void* q)
2890
0
{
2891
0
  txS8 a = *((txS8*)p);
2892
0
  txS8 b = *((txS8*)q);
2893
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
2894
0
}
2895
2896
void fxBigInt64Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
2897
230
{
2898
230
  txS8 value;
2899
#ifdef mxMisalignedSettersCrash
2900
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
2901
#else
2902
230
  value = *((txS8*)(data->value.arrayBuffer.address + offset));
2903
230
#endif
2904
230
  value = IMPORT(S64);
2905
230
  fxFromBigInt64(the, slot, value);
2906
230
  mxMeterOne();
2907
230
}
2908
2909
void fxBigInt64Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
2910
175
{
2911
175
  txS8 value = (txS8)fxToBigInt64(the, slot);
2912
#ifdef mxMisalignedSettersCrash
2913
  value = EXPORT(S64);
2914
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txS8));
2915
#else
2916
175
  *((txS8*)(data->value.arrayBuffer.address + offset)) = EXPORT(S64);
2917
175
#endif
2918
175
  mxMeterOne();
2919
175
}
2920
2921
int fxBigUint64Compare(const void* p, const void* q)
2922
0
{
2923
0
  txU8 a = *((txU8*)p);
2924
0
  txU8 b = *((txU8*)q);
2925
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
2926
0
}
2927
2928
void fxBigUint64Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
2929
121
{
2930
121
  txU8 value;
2931
#ifdef mxMisalignedSettersCrash
2932
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
2933
#else
2934
121
  value = *((txU8*)(data->value.arrayBuffer.address + offset));
2935
121
#endif
2936
121
  value = IMPORT(U64);
2937
121
  fxFromBigUint64(the, slot, value);
2938
121
  mxMeterOne();
2939
121
}
2940
2941
void fxBigUint64Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
2942
107
{
2943
107
  txU8 value = (txU8)fxToBigUint64(the, slot);
2944
#ifdef mxMisalignedSettersCrash
2945
  value = EXPORT(U64);
2946
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txU8));
2947
#else
2948
107
  *((txU8*)(data->value.arrayBuffer.address + offset)) = EXPORT(U64);
2949
107
#endif
2950
107
  mxMeterOne();
2951
107
}
2952
2953
#if mxFloat16
2954
2955
#ifdef mxUseFloat16
2956
typedef _Float16 txFloat16;
2957
#define mxFloat16to64(X) ((double)X) 
2958
#define mxFloat64to16(X) ((_Float16)X) 
2959
#else
2960
typedef uint16_t txFloat16;
2961
7.32M
#define mxFloat16to64(X) fxFloat16to64(X) 
2962
1.45k
#define mxFloat64to16(X) fxFloat64to16(X) 
2963
2964
// adapted from https://half.sourceforge.net
2965
2966
static double fxFloat16to64(uint16_t value)
2967
7.32M
{
2968
7.32M
  uint32_t hi, abs;
2969
7.32M
  uint64_t dbits;
2970
7.32M
  double out;
2971
  
2972
7.32M
  hi = (uint32_t)(value & 0x8000) << 16;
2973
7.32M
  abs = value & 0x7FFF;
2974
7.32M
  if (abs) {
2975
81
    hi |= 0x3F000000 << (abs >= 0x7C00);
2976
116
    for (; abs < 0x400; abs <<= 1, hi -= 0x100000);
2977
81
    hi += abs << 10;
2978
81
  }
2979
7.32M
  dbits = (uint64_t)(hi) << 32;
2980
7.32M
  c_memcpy(&out, &dbits, sizeof(double));
2981
7.32M
  return out;
2982
7.32M
}
2983
2984
113
static uint32_t fxRoundFloat16(uint32_t value, uint32_t g, uint32_t s) {
2985
113
  return value + (g & (s | value));
2986
113
}
2987
2988
static uint16_t fxFloat64to16(double value)
2989
725
{
2990
725
  uint64_t dbits;
2991
725
  uint32_t hi, lo, sign;
2992
  
2993
725
  c_memcpy(&dbits, &value, sizeof(double));
2994
725
  hi = dbits >> 32;
2995
725
  lo = dbits & 0xFFFFFFFF;
2996
725
  sign = (hi >> 16) & 0x8000;
2997
725
  hi &= 0x7FFFFFFF;
2998
725
  if (hi >= 0x7FF00000)
2999
1
    return sign | 0x7C00 | ((dbits & 0xFFFFFFFFFFFFF) ? (0x200 | ((hi >> 10) & 0x3FF)) : 0);
3000
724
  if (hi >= 0x40F00000)
3001
1
    return sign | 0x7C00;
3002
723
  if (hi >= 0x3F100000)
3003
110
    return fxRoundFloat16(sign | (((hi >> 20) - 1008) << 10) | ((hi >> 10) & 0x3FF), (hi >> 9) & 1, ((hi & 0x1FF) | lo) != 0);
3004
613
  if (hi >= 0x3E600000) {
3005
3
    int i = 1018 - (hi >> 20);
3006
3
    hi = (hi & 0xFFFFF) | 0x100000;
3007
3
    return fxRoundFloat16(sign | (hi >> (i + 1)), (hi >> i) & 1, ((hi & (((uint32_t)(1) << i) - 1)) | lo) != 0);
3008
3
  }
3009
610
  return sign;
3010
613
}
3011
3012
#endif
3013
3014
#if mxCanonicalNaN
3015
  #if mxBigEndian
3016
    static uint8_t gxCanonicalNaN16Bytes[2] = { 0x7E, 0 };
3017
  #else
3018
    static uint8_t gxCanonicalNaN16Bytes[2] = { 0, 0x7E };
3019
  #endif
3020
  static txFloat16* gxCanonicalNaN16 = (txFloat16*)gxCanonicalNaN16Bytes;
3021
#endif
3022
3023
static txFloat16 mxEndianFloat16_Swap(txFloat16 a)
3024
190
{
3025
190
#if defined(__GNUC__) || defined(__llvm__)
3026
190
  uint32_t result = __builtin_bswap16(*(uint16_t *)&a);
3027
190
  return *(txFloat16 *)&result;
3028
#else
3029
  txFloat16 b;
3030
  txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
3031
  int i;
3032
  for (i = 0; i < 2; i++)
3033
    p2[i] = p1[1 - i];
3034
  return b;
3035
#endif
3036
190
}
3037
3038
int fxFloat16Compare(const void* p, const void* q)
3039
3.66M
{
3040
3.66M
  double a = mxFloat16to64(*((txFloat16*)p));
3041
3.66M
  double b = mxFloat16to64(*((txFloat16*)q));
3042
3.66M
  if (c_isnan(a)) {
3043
0
    if (c_isnan(b)) 
3044
0
      return 0;
3045
0
    return 1;
3046
0
  }
3047
3.66M
  if (c_isnan(b))
3048
0
    return -1;
3049
3.66M
  if (a < b)
3050
0
    return -1;
3051
3.66M
  if (a > b)
3052
0
    return 1;
3053
3.66M
  if (a == 0) {
3054
3.66M
    if (c_signbit(a)) {
3055
0
      if (c_signbit(b)) 
3056
0
        return 0;
3057
0
      return -1;
3058
0
    }
3059
3.66M
    if (c_signbit(b))
3060
0
      return 1;
3061
3.66M
  }
3062
3.66M
  return 0;
3063
3.66M
}
3064
3065
void fxFloat16Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3066
687
{
3067
687
  txFloat16 value;
3068
687
  slot->kind = XS_NUMBER_KIND;
3069
#ifdef mxMisalignedSettersCrash
3070
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
3071
#else
3072
687
  value = *((txFloat16*)(data->value.arrayBuffer.address + offset));
3073
687
#endif
3074
687
  slot->value.number = mxFloat16to64(IMPORT(Float16));
3075
687
  mxMeterOne();
3076
687
}
3077
3078
void fxFloat16Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3079
728
{
3080
728
#if mxCanonicalNaN
3081
728
  txFloat16 value = (c_isnan(slot->value.number)) ? *gxCanonicalNaN16 : mxFloat64to16(slot->value.number);
3082
#else
3083
  txFloat16 value = mxFloat64to16(slot->value.number);
3084
#endif
3085
#ifdef mxMisalignedSettersCrash
3086
  value = EXPORT(Float16);
3087
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(value));
3088
#else
3089
728
  *((txFloat16*)(data->value.arrayBuffer.address + offset)) = EXPORT(Float16);
3090
728
#endif
3091
728
  mxMeterOne();
3092
728
}
3093
3094
void fx_Math_f16round(txMachine* the)
3095
0
{
3096
0
  txFloat16 value = mxFloat64to16((mxArgc < 1) ? C_NAN : fxToNumber(the, mxArgv(0)));
3097
0
  mxResult->kind = XS_NUMBER_KIND;
3098
0
  mxResult->value.number = mxFloat16to64(value);
3099
0
}
3100
3101
#endif
3102
3103
#if mxCanonicalNaN
3104
  #if mxBigEndian
3105
    static uint8_t gxCanonicalNaN32Bytes[4] = { 0x7F, 0xC0, 0, 0 };
3106
  #else
3107
    static uint8_t gxCanonicalNaN32Bytes[4] = { 0, 0, 0xC0, 0x7F };
3108
  #endif
3109
  static float* gxCanonicalNaN32 = (float*)gxCanonicalNaN32Bytes;
3110
#endif
3111
3112
static float mxEndianFloat32_Swap(float a)
3113
186
{
3114
186
#if defined(__GNUC__) || defined(__llvm__)
3115
186
  uint32_t result = __builtin_bswap32(*(uint32_t *)&a);
3116
186
  return *(float *)&result;
3117
#else
3118
  float b;
3119
  txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
3120
  int i;
3121
  for (i = 0; i < 4; i++)
3122
    p2[i] = p1[3 - i];
3123
  return b;
3124
#endif
3125
186
}
3126
3127
int fxFloat32Compare(const void* p, const void* q)
3128
3.66M
{
3129
3.66M
  float a = *((float*)p);
3130
3.66M
  float b = *((float*)q);
3131
3.66M
  if (c_isnan(a)) {
3132
0
    if (c_isnan(b)) 
3133
0
      return 0;
3134
0
    return 1;
3135
0
  }
3136
3.66M
  if (c_isnan(b))
3137
0
    return -1;
3138
3.66M
  if (a < b)
3139
0
    return -1;
3140
3.66M
  if (a > b)
3141
0
    return 1;
3142
3.66M
  if (a == 0) {
3143
3.66M
    if (c_signbit(a)) {
3144
0
      if (c_signbit(b)) 
3145
0
        return 0;
3146
0
      return -1;
3147
0
    }
3148
3.66M
    if (c_signbit(b))
3149
0
      return 1;
3150
3.66M
  }
3151
3.66M
  return 0;
3152
3.66M
}
3153
3154
void fxFloat32Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3155
136k
{
3156
136k
  float value;
3157
136k
  slot->kind = XS_NUMBER_KIND;
3158
#ifdef mxMisalignedSettersCrash
3159
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
3160
#else
3161
136k
  value = *((float*)(data->value.arrayBuffer.address + offset));
3162
136k
#endif
3163
136k
  slot->value.number = IMPORT(Float32);
3164
136k
  mxMeterOne();
3165
136k
}
3166
3167
void fxFloat32Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3168
914
{
3169
914
#if mxCanonicalNaN
3170
914
  float value = (c_isnan(slot->value.number)) ? *gxCanonicalNaN32 : (float)slot->value.number;
3171
#else
3172
  float value = (float)slot->value.number;
3173
#endif
3174
#ifdef mxMisalignedSettersCrash
3175
  value = EXPORT(Float32);
3176
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(value));
3177
#else
3178
914
  *((float*)(data->value.arrayBuffer.address + offset)) = EXPORT(Float32);
3179
914
#endif
3180
914
  mxMeterOne();
3181
914
}
3182
3183
#if mxCanonicalNaN
3184
  #if mxBigEndian
3185
    static uint8_t gxCanonicalNaN64Bytes[8] = { 0x7F, 0xF8, 0, 0, 0, 0, 0, 0 };
3186
  #else
3187
    static uint8_t gxCanonicalNaN64Bytes[8] = { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F };
3188
  #endif
3189
  double* gxCanonicalNaN64 = (double*)gxCanonicalNaN64Bytes;
3190
#endif
3191
3192
static double mxEndianFloat64_Swap(double a)
3193
158
{
3194
158
#if defined(__GNUC__) || defined(__llvm__)
3195
158
  uint64_t result = __builtin_bswap64(*(uint64_t *)&a);
3196
158
  return *(double *)&result;
3197
#else
3198
  double b;
3199
  txU1 *p1 = (txU1 *) &a, *p2 = (txU1 *) &b;
3200
  int i;
3201
  for (i = 0; i < 8; i++)
3202
    p2[i] = p1[7 - i];
3203
  return b;
3204
#endif
3205
158
}
3206
3207
int fxFloat64Compare(const void* p, const void* q)
3208
0
{
3209
0
  double a = *((double*)p);
3210
0
  double b = *((double*)q);
3211
0
  if (c_isnan(a)) {
3212
0
    if (c_isnan(b)) 
3213
0
      return 0;
3214
0
    return 1;
3215
0
  }
3216
0
  if (c_isnan(b))
3217
0
    return -1;
3218
0
  if (a < b)
3219
0
    return -1;
3220
0
  if (a > b)
3221
0
    return 1;
3222
0
  if (a == 0) {
3223
0
    if (c_signbit(a)) {
3224
0
      if (c_signbit(b)) 
3225
0
        return 0;
3226
0
      return -1;
3227
0
    }
3228
0
    if (c_signbit(b))
3229
0
      return 1;
3230
0
  }
3231
0
  return 0;
3232
0
}
3233
3234
void fxFloat64Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3235
631
{
3236
631
  double value;
3237
631
  slot->kind = XS_NUMBER_KIND;
3238
#ifdef mxMisalignedSettersCrash
3239
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
3240
#else
3241
631
  value = *((double*)(data->value.arrayBuffer.address + offset));
3242
631
#endif
3243
631
  slot->value.number = IMPORT(Float64);
3244
631
  mxMeterOne();
3245
631
}
3246
3247
void fxFloat64Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3248
626
{
3249
626
#if mxCanonicalNaN
3250
626
  double value = (c_isnan(slot->value.number)) ? *gxCanonicalNaN32 : slot->value.number;
3251
#else
3252
  double value = slot->value.number;
3253
#endif
3254
#ifdef mxMisalignedSettersCrash
3255
  value = EXPORT(Float64);
3256
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(value));
3257
#else
3258
626
  *((double*)(data->value.arrayBuffer.address + offset)) = EXPORT(Float64);
3259
626
#endif
3260
626
  mxMeterOne();
3261
626
}
3262
3263
void fxIntCoerce(txMachine* the, txSlot* slot)
3264
23.5k
{
3265
23.5k
  fxToInteger(the, slot);
3266
23.5k
}
3267
3268
void fxUintCoerce(txMachine* the, txSlot* slot)
3269
486k
{
3270
486k
  fxToUnsigned(the, slot);
3271
486k
}
3272
3273
int fxInt8Compare(const void* p, const void* q)
3274
0
{
3275
0
  txS1 a = *((txS1*)p);
3276
0
  txS1 b = *((txS1*)q);
3277
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3278
0
}
3279
3280
void fxInt8Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3281
1.56k
{
3282
1.56k
  slot->kind = XS_INTEGER_KIND;
3283
1.56k
  slot->value.integer = *((txS1*)(data->value.arrayBuffer.address + offset));
3284
1.56k
  mxMeterOne();
3285
1.56k
}
3286
3287
void fxInt8Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3288
20.6k
{
3289
20.6k
  *((txS1*)(data->value.arrayBuffer.address + offset)) = (txS1)slot->value.integer;
3290
20.6k
  mxMeterOne();
3291
20.6k
}
3292
3293
int fxInt16Compare(const void* p, const void* q)
3294
0
{
3295
0
  txS2 a = *((txS2*)p);
3296
0
  txS2 b = *((txS2*)q);
3297
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3298
0
}
3299
3300
void fxInt16Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3301
850k
{
3302
850k
  txS2 value;
3303
850k
  slot->kind = XS_INTEGER_KIND;
3304
#ifdef mxMisalignedSettersCrash
3305
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
3306
#else
3307
850k
  value = *((txS2*)(data->value.arrayBuffer.address + offset));
3308
850k
#endif
3309
850k
  slot->value.integer = IMPORT(S16);
3310
850k
  mxMeterOne();
3311
850k
}
3312
3313
void fxInt16Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3314
1.22k
{
3315
1.22k
  txS2 value = (txS2)slot->value.integer;
3316
#ifdef mxMisalignedSettersCrash
3317
  value = EXPORT(S16);
3318
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txS2));
3319
#else
3320
1.22k
  *((txS2*)(data->value.arrayBuffer.address + offset)) = EXPORT(S16);
3321
1.22k
#endif
3322
1.22k
  mxMeterOne();
3323
1.22k
}
3324
3325
int fxInt32Compare(const void* p, const void* q)
3326
0
{
3327
0
  txS4 a = *((txS4*)p);
3328
0
  txS4 b = *((txS4*)q);
3329
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3330
0
}
3331
3332
void fxInt32Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3333
2.62M
{
3334
2.62M
  txS4 value;
3335
2.62M
  slot->kind = XS_INTEGER_KIND;
3336
#ifdef mxMisalignedSettersCrash
3337
  value = c_read32(data->value.arrayBuffer.address + offset);
3338
#else
3339
2.62M
  value = *((txS4*)(data->value.arrayBuffer.address + offset));
3340
2.62M
#endif
3341
2.62M
  slot->value.integer = IMPORT(S32);
3342
2.62M
  mxMeterOne();
3343
2.62M
}
3344
3345
void fxInt32Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3346
373
{
3347
373
  txS4 value = (txS4)slot->value.integer;
3348
#ifdef mxMisalignedSettersCrash
3349
  value = EXPORT(S32);
3350
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txS4));
3351
#else
3352
373
  *((txS4*)(data->value.arrayBuffer.address + offset)) = EXPORT(S32);
3353
373
#endif
3354
373
  mxMeterOne();
3355
373
}
3356
3357
int fxUint8Compare(const void* p, const void* q)
3358
0
{
3359
0
  txU1 a = c_read8((txU1*)p);
3360
0
  txU1 b = c_read8((txU1*)q);
3361
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3362
0
}
3363
3364
void fxUint8Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3365
2.90k
{
3366
2.90k
  slot->kind = XS_INTEGER_KIND;
3367
2.90k
  slot->value.integer = c_read8((txU1*)(data->value.arrayBuffer.address + offset));
3368
2.90k
  mxMeterOne();
3369
2.90k
}
3370
3371
void fxUint8Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3372
75.1k
{
3373
75.1k
  txUnsigned tmp = (slot->kind == XS_INTEGER_KIND) ? (txUnsigned)slot->value.integer : (txUnsigned)slot->value.number;
3374
75.1k
  *((txU1*)(data->value.arrayBuffer.address + offset)) = (txU1)tmp;
3375
75.1k
  mxMeterOne();
3376
75.1k
}
3377
3378
int fxUint16Compare(const void* p, const void* q)
3379
505k
{
3380
505k
  txU2 a = *((txU2*)p);
3381
505k
  txU2 b = *((txU2*)q);
3382
505k
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3383
505k
}
3384
3385
void fxUint16Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3386
4.43M
{
3387
4.43M
  txU2 value;
3388
4.43M
  slot->kind = XS_INTEGER_KIND;
3389
#ifdef mxMisalignedSettersCrash
3390
  c_memcpy(&value, data->value.arrayBuffer.address + offset, sizeof(value));
3391
#else
3392
4.43M
  value = *((txU2*)(data->value.arrayBuffer.address + offset));
3393
4.43M
#endif
3394
4.43M
  slot->value.integer = IMPORT(U16);
3395
4.43M
  mxMeterOne();
3396
4.43M
}
3397
3398
void fxUint16Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3399
207k
{
3400
207k
  txUnsigned tmp = (slot->kind == XS_INTEGER_KIND) ? (txUnsigned)slot->value.integer : (txUnsigned)slot->value.number;
3401
207k
  txU2 value = (txU2)tmp;
3402
#ifdef mxMisalignedSettersCrash
3403
  value = EXPORT(U16);
3404
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txU2));
3405
#else
3406
207k
  *((txU2*)(data->value.arrayBuffer.address + offset)) = EXPORT(U16);
3407
207k
#endif
3408
207k
  mxMeterOne();
3409
207k
}
3410
3411
int fxUint32Compare(const void* p, const void* q)
3412
0
{
3413
0
  txU4 a = *((txU4*)p);
3414
0
  txU4 b = *((txU4*)q);
3415
0
  return (a < b) ? -1 : (a > b) ? 1 : 0;
3416
0
}
3417
3418
void fxUint32Getter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3419
72.4k
{
3420
#ifdef mxMisalignedSettersCrash
3421
  txUnsigned value = c_read32(data->value.arrayBuffer.address + offset);
3422
#else
3423
72.4k
  txUnsigned value = *((txU4*)(data->value.arrayBuffer.address + offset));
3424
72.4k
#endif
3425
72.4k
  value = IMPORT(U32);
3426
72.4k
  if (((txInteger)value) >= 0) {
3427
70.6k
    slot->kind = XS_INTEGER_KIND;
3428
70.6k
    slot->value.integer = value;
3429
70.6k
  }
3430
1.78k
  else {
3431
1.78k
    slot->kind = XS_NUMBER_KIND;
3432
1.78k
    slot->value.number = value;
3433
1.78k
  }
3434
72.4k
  mxMeterOne();
3435
72.4k
}
3436
3437
void fxUint32Setter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3438
202k
{
3439
202k
  txU4 value = (slot->kind == XS_INTEGER_KIND) ? (txU4)slot->value.integer : (txU4)slot->value.number;
3440
#ifdef mxMisalignedSettersCrash
3441
  value = EXPORT(U32);
3442
  c_memcpy(data->value.arrayBuffer.address + offset, &value, sizeof(txU4));
3443
#else
3444
202k
  *((txU4*)(data->value.arrayBuffer.address + offset)) = EXPORT(U32);
3445
202k
#endif
3446
202k
  mxMeterOne();
3447
202k
}
3448
3449
void fxUint8ClampedSetter(txMachine* the, txSlot* data, txInteger offset, txSlot* slot, int endian)
3450
22
{
3451
22
  txNumber value = fxToNumber(the, slot);
3452
22
  if (value <= 0)
3453
2
    value = 0;
3454
20
  else if (value >= 255)
3455
11
    value = 255;
3456
9
  else if (c_isnan(value))
3457
3
    value = 0;
3458
6
  else
3459
6
    value = c_nearbyint(value);
3460
22
  *((txU1*)(data->value.arrayBuffer.address + offset)) = (txU1)value;
3461
22
  mxMeterOne();
3462
22
}
3463
3464
#if mxUint8ArrayBase64
3465
3466
static const char gxBase64Alphabet[] ICACHE_FLASH_ATTR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3467
static const char gxBase64URLAlphabet[] ICACHE_FLASH_ATTR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3468
static const char gxHexAlphabet[] ICACHE_FLASH_ATTR = "0123456789abcdef";
3469
3470
enum {
3471
  mxBase64Loose,
3472
  mxBase64StopBeforePartial,
3473
  mxBase64Strict,
3474
};
3475
3476
static txU1 fxSkipAsciiWhitespace(txU1** src)
3477
1.30M
{
3478
1.30M
  txU1* p = *src;
3479
1.30M
  txU1 c;
3480
1.99M
  while ((c = c_read8(p))) {
3481
1.88M
    if ((c != 0x09) && (c != 0x0A) && (c != 0x0C) && (c != 0x0D) && (c != 0x20))
3482
1.19M
       break;
3483
693k
    p++;
3484
693k
  }
3485
1.30M
  *src = p;
3486
1.30M
  return c;
3487
1.30M
}
3488
3489
static void fxUint8ArrayFromBase64(txMachine* the, txU1* srcStart, txU1* dstStart, txSize* read, txSize* written, txU1* alphabet, txInteger lastChunkHandling)
3490
414k
{
3491
414k
  txU1* src = srcStart;
3492
414k
  txU1* dst = dstStart;
3493
414k
  txSize remaining = *written;
3494
414k
  txBoolean url = (alphabet == (txU1*)gxBase64URLAlphabet) ? 1 : 0, done = 0;
3495
414k
  txU1 byte, buffer[4];
3496
414k
  txSize bufferIndex, bufferLength = 0;
3497
  
3498
414k
  if (remaining == 0) {
3499
381
    *read = 0;
3500
381
    return;
3501
381
  }
3502
1.26M
  for (;;) {
3503
1.26M
    byte = fxSkipAsciiWhitespace(&src);
3504
1.26M
    if (byte == 0) {
3505
112k
      if (bufferLength == 0)
3506
6.05k
        break;
3507
106k
      if (lastChunkHandling == mxBase64StopBeforePartial)
3508
16
        break;
3509
106k
      if ((lastChunkHandling == mxBase64Strict) || (bufferLength == 1))
3510
103k
        mxSyntaxError("invalid string");
3511
2.48k
      if (bufferLength == 2)
3512
1.14k
        buffer[2] = 0;
3513
2.48k
      buffer[3] = 0;
3514
2.48k
      done = 1;
3515
2.48k
    }
3516
1.15M
    else if (byte == '=') {
3517
74.8k
      if (bufferLength < 2)  
3518
51.7k
        mxSyntaxError("invalid string");
3519
23.1k
      src++;
3520
23.1k
      byte = fxSkipAsciiWhitespace(&src);
3521
23.1k
      if (bufferLength == 2)  {
3522
21.7k
        if (byte == 0) {
3523
529
          if (lastChunkHandling == mxBase64StopBeforePartial)
3524
8
            break;
3525
529
          mxSyntaxError("invalid string");
3526
529
        }
3527
21.2k
        if (byte == '=') {
3528
13.7k
          src++;
3529
13.7k
          byte = fxSkipAsciiWhitespace(&src);
3530
13.7k
        }
3531
21.2k
        buffer[2] = 0;
3532
21.2k
      }
3533
22.6k
      if (byte != 0)
3534
22.1k
        mxSyntaxError("invalid string");
3535
454
      buffer[3] = 0;
3536
454
      done = 1;
3537
454
    } 
3538
1.08M
    else {
3539
1.08M
      if (('A' <= byte) && (byte <= 'Z'))
3540
162k
        byte = byte - 'A';
3541
918k
      else if (('a' <= byte) && (byte <= 'z'))
3542
246k
        byte = byte - 'a' + 26;
3543
672k
      else if (('0' <= byte) && (byte <= '9'))
3544
295k
        byte = byte - '0' + 52;
3545
376k
      else if ((byte == '+') && !url)
3546
107k
        byte = 62;
3547
268k
      else if ((byte == '-') && url)
3548
1
        byte = 62;
3549
268k
      else if ((byte == '/') && !url)
3550
42.2k
        byte = 63;
3551
226k
      else if ((byte == '_') && url)
3552
1
        byte = 63;
3553
226k
      else
3554
226k
        mxSyntaxError("invalid string");
3555
854k
      if (((remaining == 1) && (bufferLength == 2)) || ((remaining == 2) && (bufferLength == 3)))
3556
49
        break;
3557
854k
      buffer[bufferLength] = byte;
3558
854k
      bufferLength++;
3559
854k
      src++;
3560
854k
      if (bufferLength < 4)
3561
741k
        continue;
3562
854k
    }
3563
116k
    *read = (txSize)(src - srcStart);
3564
116k
    buffer[0] = (buffer[0] << 2) | ((buffer[1] & 0x30) >> 4);
3565
116k
    buffer[1] = ((buffer[1] & 0x0F) << 4) | ((buffer[2] & 0x3C) >> 2);
3566
116k
    buffer[2] = ((buffer[2] & 0x03) << 6) | (buffer[3] & 0x3F);
3567
116k
    bufferLength--;
3568
116k
    if ((lastChunkHandling == mxBase64Strict) && (bufferLength < 3) && (buffer[bufferLength] != 0))
3569
0
      mxSyntaxError("invalid string");
3570
116k
    bufferIndex = 0;
3571
463k
    while ((bufferIndex < bufferLength) && (remaining > 0)) {
3572
346k
      *dst++ = buffer[bufferIndex];
3573
346k
      bufferIndex++;
3574
346k
      remaining--;
3575
346k
    }
3576
116k
    bufferLength = 0;
3577
116k
    if ((done) || (remaining == 0))
3578
3.31k
      break;
3579
116k
  }
3580
9.44k
  *written = (txSize)(dst - dstStart);
3581
9.44k
}
3582
3583
static void fxUint8ArrayFromHex(txMachine* the, txU1* srcStart, txU1* dstStart, txSize* read, txSize* written)
3584
1.37k
{
3585
1.37k
#define mxFromHex(X) \
3586
11.9k
  if (('0' <= X) && (X <= '9')) X = X - '0'; \
3587
11.9k
  else if (('A' <= X) && (X <= 'F')) X = X - 'A' + 10; \
3588
11.7k
  else if (('a' <= X) && (X <= 'f')) X =  X - 'a' + 10; \
3589
3.33k
  else mxSyntaxError("invalid string")
3590
3591
1.37k
  txU1* src = srcStart;
3592
1.37k
  txU1* dst = dstStart;
3593
1.37k
  txSize srcSize = *read;
3594
1.37k
  txSize dstSize = *written;
3595
6.15k
  while ((srcSize > 0) && (dstSize > 0)) {
3596
6.13k
    txU1 high = c_read8(src++); 
3597
6.13k
    txU1 low = c_read8(src++); 
3598
6.13k
    mxFromHex(high);
3599
5.77k
    mxFromHex(low);
3600
4.77k
    *dst++ = (high << 4) + low;
3601
4.77k
    srcSize -= 2;
3602
4.77k
    dstSize--;
3603
4.77k
  }
3604
21
  *read = (txSize)(src - srcStart);
3605
21
  *written = (txSize)(dst - dstStart);
3606
21
}
3607
3608
static void fxUint8ArrayGetBase64Options(txMachine* the, txInteger argi, txU1** alphabet, txInteger* lastChunkHandling, txBoolean* omitPadding)
3609
415k
{
3610
415k
  if ((mxArgc > argi) && !mxIsUndefined(mxArgv(argi))) {
3611
1.29k
    if (!mxIsReference(mxArgv(argi)))
3612
1
      mxTypeError("options: not an object");
3613
1.29k
    mxPushSlot(mxArgv(argi));
3614
1.29k
    mxGetID(mxID(_alphabet));
3615
1.29k
    if (!mxIsUndefined(the->stack)) {
3616
57
      if (!mxIsStringPrimitive(the->stack))
3617
7
        mxTypeError("options.alphabet: not a string");
3618
50
      if (!c_strcmp(the->stack->value.string, "base64url"))
3619
40
        *alphabet = (txU1*)gxBase64URLAlphabet;
3620
10
      else if (c_strcmp(the->stack->value.string, "base64"))
3621
6
        mxTypeError("options.alphabet: neither 'base64' nor 'base64url'");
3622
50
    }
3623
1.27k
    mxPop();
3624
1.27k
    if (lastChunkHandling) {
3625
1.17k
      mxPushSlot(mxArgv(argi));
3626
1.17k
      mxGetID(mxID(_lastChunkHandling));
3627
1.17k
      if (!mxIsUndefined(the->stack)) {
3628
504
        if (!mxIsStringPrimitive(the->stack))
3629
11
          mxTypeError("options.lastChunkHandling: not a string");
3630
493
        if (!c_strcmp(the->stack->value.string, "stop-before-partial"))
3631
219
          *lastChunkHandling = mxBase64StopBeforePartial;
3632
274
        else if (!c_strcmp(the->stack->value.string, "strict"))
3633
38
          *lastChunkHandling = mxBase64Strict;
3634
236
        else if (c_strcmp(the->stack->value.string, "loose"))
3635
185
          mxTypeError("options.lastChunkHandling: neither 'loose' nor 'strict' nor 'stop-before-partial'");
3636
493
      }
3637
983
      mxPop();
3638
983
    }
3639
1.08k
    if (omitPadding) {
3640
99
      mxPushSlot(mxArgv(argi));
3641
99
      mxGetID(mxID(_omitPadding));
3642
99
      fxToBoolean(the, the->stack);
3643
99
      *omitPadding = the->stack->value.boolean;
3644
99
      mxPop();
3645
99
    }
3646
1.08k
  }
3647
415k
}
3648
3649
void fx_Uint8Array_fromBase64(txMachine* the)
3650
484k
{
3651
484k
  txSize srcSize;
3652
484k
  txSize dstSize;
3653
484k
  txU1* alphabet = (txU1*)gxBase64Alphabet;
3654
484k
  txInteger lastChunkHandling = mxBase64Loose;
3655
484k
  txU1* src;
3656
484k
  txU1* dst;
3657
484k
  if ((mxArgc < 1) || !mxIsStringPrimitive(mxArgv(0)))
3658
70.7k
    mxTypeError("string: not a string");
3659
413k
  fxUint8ArrayGetBase64Options(the, 1, &alphabet, &lastChunkHandling, NULL);
3660
413k
  srcSize = (txSize)c_strlen(mxArgv(0)->value.string);
3661
413k
  dstSize = (((srcSize + 3) / 4) * 3);
3662
413k
  mxPush(mxUint8ArrayConstructor);
3663
413k
  mxNew();
3664
413k
  mxPushInteger(dstSize);
3665
413k
  mxRunCount(1);
3666
413k
  mxPullSlot(mxResult);
3667
413k
  {
3668
413k
    txSlot* resultInstance = fxCheckTypedArrayInstance(the, mxResult); \
3669
413k
    txSlot* resultDispatch = resultInstance->next; \
3670
413k
    txSlot* resultView = resultDispatch->next; \
3671
413k
    txSlot* resultBuffer = resultView->next; \
3672
413k
    src = (txU1*)(mxArgv(0)->value.string);
3673
413k
    dst = (txU1*)(resultBuffer->value.reference->next->value.arrayBuffer.address + resultView->value.dataView.offset);
3674
413k
    resultBuffer->value.reference->next->next->value.bufferInfo.maxLength = dstSize;
3675
413k
    fxUint8ArrayFromBase64(the, src, dst, &srcSize, &dstSize, alphabet, lastChunkHandling);
3676
413k
    fxSetArrayBufferLength(the, resultBuffer, dstSize);
3677
413k
    resultBuffer->value.reference->next->next->value.bufferInfo.maxLength = -1;
3678
413k
    resultView->value.dataView.size = dstSize;
3679
413k
  }
3680
413k
}
3681
3682
void fx_Uint8Array_fromHex(txMachine* the)
3683
1.69k
{
3684
1.69k
  txSize srcSize;
3685
1.69k
  txSize dstSize;
3686
1.69k
  txU1* src;
3687
1.69k
  txU1* dst;
3688
1.69k
  if ((mxArgc < 1) || !mxIsStringPrimitive(mxArgv(0)))
3689
11
    mxTypeError("string: not a string");
3690
1.68k
  srcSize = (txSize)c_strlen(mxArgv(0)->value.string);
3691
1.68k
  if (srcSize & 1)
3692
333
    mxSyntaxError("string: odd length");
3693
1.35k
  dstSize = srcSize >> 1;
3694
1.35k
  mxPush(mxUint8ArrayConstructor);
3695
1.35k
  mxNew();
3696
1.35k
  mxPushInteger(dstSize);
3697
1.35k
  mxRunCount(1);
3698
1.35k
  mxPullSlot(mxResult);
3699
1.35k
  {
3700
1.35k
    txSlot* resultInstance = fxCheckTypedArrayInstance(the, mxResult); \
3701
1.35k
    txSlot* resultDispatch = resultInstance->next; \
3702
1.35k
    txSlot* resultView = resultDispatch->next; \
3703
1.35k
    txSlot* resultBuffer = resultView->next; \
3704
1.35k
    src = (txU1*)(mxArgv(0)->value.string);
3705
1.35k
    dst = (txU1*)(resultBuffer->value.reference->next->value.arrayBuffer.address + resultView->value.dataView.offset);
3706
1.35k
    fxUint8ArrayFromHex(the, src, dst, &srcSize, &dstSize);
3707
1.35k
  }
3708
1.35k
}
3709
3710
void fx_Uint8Array_prototype_setFromBase64(txMachine* the)
3711
1.30k
{
3712
1.30k
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
3713
1.30k
  txSlot* dispatch = instance->next;
3714
1.30k
  txSlot* view = dispatch->next;
3715
1.30k
  txSlot* buffer = view->next;
3716
1.30k
  txU1* alphabet = (txU1*)gxBase64Alphabet;
3717
1.30k
  txInteger lastChunkHandling = mxBase64Loose;
3718
1.30k
  txSize srcSize;
3719
1.30k
  txSize dstSize;
3720
1.30k
  txU1* src;
3721
1.30k
  txU1* dst;
3722
1.30k
  txSlot* property;
3723
1.30k
  if (dispatch->value.typedArray.dispatch->constructorID != mxID(_Uint8Array))
3724
0
    mxTypeError("this: not a Uint8Array instance");
3725
1.30k
  if ((mxArgc < 1) || !mxIsStringPrimitive(mxArgv(0)))
3726
100
    mxTypeError("string: not a string");
3727
1.20k
  fxUint8ArrayGetBase64Options(the, 1, &alphabet, &lastChunkHandling, NULL);
3728
1.20k
  srcSize = (txSize)c_strlen(mxArgv(0)->value.string);
3729
1.20k
  dstSize = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE);
3730
1.20k
  src = (txU1*)(mxArgv(0)->value.string);
3731
1.20k
  dst = (txU1*)(buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset);
3732
1.20k
  fxUint8ArrayFromBase64(the, src, dst, &srcSize, &dstSize, alphabet, lastChunkHandling);
3733
1.20k
  mxPush(mxObjectPrototype);
3734
1.20k
  property = fxLastProperty(the, fxNewObjectInstance(the));
3735
1.20k
  property = fxNextIntegerProperty(the, property, srcSize, mxID(_read_), XS_NO_FLAG);
3736
1.20k
  property = fxNextIntegerProperty(the, property, dstSize, mxID(_written), XS_NO_FLAG);
3737
1.20k
  mxPullSlot(mxResult);
3738
1.20k
}
3739
3740
void fx_Uint8Array_prototype_setFromHex(txMachine* the)
3741
58
{
3742
58
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
3743
58
  txSlot* dispatch = instance->next;
3744
58
  txSlot* view = dispatch->next;
3745
58
  txSlot* buffer = view->next;
3746
58
  txSize srcSize;
3747
58
  txSize dstSize;
3748
58
  txU1* src;
3749
58
  txU1* dst;
3750
58
  txSlot* property;
3751
58
  if (dispatch->value.typedArray.dispatch->constructorID != mxID(_Uint8Array))
3752
0
    mxTypeError("this: not a Uint8Array instance");
3753
58
  if ((mxArgc < 1) || !mxIsStringPrimitive(mxArgv(0)))
3754
9
    mxTypeError("string: not a string");
3755
49
  dstSize = fxCheckDataViewSize(the, view, buffer, XS_MUTABLE);
3756
49
  srcSize = (txSize)c_strlen(mxArgv(0)->value.string);
3757
49
  if (srcSize & 1)
3758
26
    mxSyntaxError("string: odd length");
3759
23
  src = (txU1*)(mxArgv(0)->value.string);
3760
23
  dst = (txU1*)(buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset);
3761
23
  fxUint8ArrayFromHex(the, src, dst, &srcSize, &dstSize);
3762
23
  mxPush(mxObjectPrototype);
3763
23
  property = fxLastProperty(the, fxNewObjectInstance(the));
3764
23
  property = fxNextIntegerProperty(the, property, srcSize, mxID(_read_), XS_NO_FLAG);
3765
23
  property = fxNextIntegerProperty(the, property, dstSize, mxID(_written), XS_NO_FLAG);
3766
23
  mxPullSlot(mxResult);
3767
23
}
3768
3769
void fx_Uint8Array_prototype_toBase64(txMachine* the)
3770
148
{
3771
148
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
3772
148
  txSlot* dispatch = instance->next;
3773
148
  txSlot* view = dispatch->next;
3774
148
  txSlot* buffer = view->next;
3775
148
  txU1* alphabet = (txU1*)gxBase64Alphabet;
3776
148
  txBoolean omitPadding = 0;
3777
148
  txU1* src;
3778
148
  txU1* dst;
3779
148
  txSize srcSize;
3780
148
  txSize dstSize;
3781
148
  txU1 a, b, c;
3782
148
  if (dispatch->value.typedArray.dispatch->constructorID != mxID(_Uint8Array))
3783
0
    mxTypeError("this: not a Uint8Array instance");
3784
148
  fxUint8ArrayGetBase64Options(the, 0, &alphabet, C_NULL, &omitPadding);
3785
148
  srcSize = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
3786
148
  if (srcSize > (((0x7FFFFFFF >> 2) * 3) - 2))
3787
0
    fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
3788
148
  dstSize = (((srcSize + 2) / 3) << 2);
3789
148
  fxStringBuffer(the, mxResult, C_NULL, dstSize);
3790
148
  src = (txU1*)buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset;
3791
148
  dst = (txU1*)mxResult->value.string;
3792
339
  while (srcSize > 2) {
3793
191
    a = c_read8(src++);
3794
191
    b = c_read8(src++);
3795
191
    c = c_read8(src++);
3796
191
    *dst++ = c_read8(alphabet + ((a & 0xfc) >> 2));
3797
191
    *dst++ = c_read8(alphabet + (((a & 0x3) << 4) | ((b & 0xf0) >> 4)));
3798
191
    *dst++ = c_read8(alphabet + (((b & 0xf) << 2) | ((c & 0xc0) >> 6)));
3799
191
    *dst++ = c_read8(alphabet + (c & 0x3f));
3800
191
    srcSize -= 3;
3801
191
  }
3802
148
  if (srcSize == 2) {
3803
77
    a = c_read8(src++);
3804
77
    b = c_read8(src++);
3805
77
    *dst++ = c_read8(alphabet + ((a & 0xfc) >> 2));
3806
77
    *dst++ = c_read8(alphabet + (((a & 0x3) << 4) | ((b & 0xf0) >> 4)));
3807
77
    *dst++ = c_read8(alphabet + ((b & 0xf) << 2));
3808
77
    if (!omitPadding)
3809
51
      *dst++ = '=';
3810
77
  }
3811
71
  else if (srcSize == 1) {
3812
31
    a = c_read8(src++);
3813
31
    *dst++ = c_read8(alphabet + ((a & 0xfc) >> 2));
3814
31
    *dst++ = c_read8(alphabet + ((a & 0x3) << 4));
3815
31
    if (!omitPadding) {
3816
7
      *dst++ = '=';
3817
7
      *dst++ = '=';
3818
7
    }
3819
31
  }
3820
148
  *dst++ = 0;
3821
148
}
3822
3823
void fx_Uint8Array_prototype_toHex(txMachine* the)
3824
206
{
3825
206
  txSlot* instance = fxCheckTypedArrayInstance(the, mxThis);
3826
206
  txSlot* dispatch = instance->next;
3827
206
  txSlot* view = dispatch->next;
3828
206
  txSlot* buffer = view->next;
3829
206
  txU1* alphabet = (txU1*)gxHexAlphabet;
3830
206
  txU1* src;
3831
206
  txU1* dst;
3832
206
  txSize srcSize;
3833
206
  txSize dstSize;
3834
206
  txU1 a;
3835
206
  if (dispatch->value.typedArray.dispatch->constructorID != mxID(_Uint8Array))
3836
0
    mxTypeError("this: not a Uint8Array instance");
3837
206
  srcSize = fxCheckDataViewSize(the, view, buffer, XS_IMMUTABLE);
3838
206
  if (srcSize > (0x7FFFFFFF >> 1))
3839
0
    fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
3840
206
  dstSize = (srcSize << 1);
3841
206
  fxStringBuffer(the, mxResult, C_NULL, dstSize);
3842
206
  src = (txU1*)buffer->value.reference->next->value.arrayBuffer.address + view->value.dataView.offset;
3843
206
  dst = (txU1*)mxResult->value.string;
3844
468
  while (srcSize > 0) {
3845
262
    a = c_read8(src++);
3846
262
    *dst++ = c_read8(alphabet + ((a & 0xf0) >> 4));
3847
262
    *dst++ = c_read8(alphabet + (a & 0x0f));
3848
262
    srcSize--;
3849
262
  }
3850
206
  *dst++ = 0;
3851
206
}
3852
3853
#endif