Coverage Report

Created: 2026-09-01 07:01

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