Coverage Report

Created: 2026-05-30 06:28

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