Coverage Report

Created: 2025-09-04 06:38

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