Coverage Report

Created: 2026-08-31 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsProperty.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2017  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
txSlot* fxLastProperty(txMachine* the, txSlot* slot)
41
82.5M
{
42
82.5M
  txSlot* property;
43
264M
  while ((property = slot->next))
44
182M
    slot = property;
45
82.5M
  return slot;
46
82.5M
}
47
48
#ifndef mxLink
49
txSlot* fxNextHostAccessorProperty(txMachine* the, txSlot* property, txCallback get, txCallback set, txID id, txFlag flag)
50
1.49M
{
51
1.49M
  txSlot *getter = NULL, *setter = NULL, *home = the->stack, *slot;
52
1.49M
  if (get) {
53
1.49M
    getter = fxBuildHostFunction(the, get, 0, XS_NO_ID);
54
1.49M
    slot = mxFunctionInstanceHome(getter);
55
1.49M
    slot->value.home.object = home->value.reference;
56
1.49M
    fxRenameFunction(the, getter, id, 0, XS_NO_ID, "get ");
57
1.49M
  }
58
1.49M
  if (set) {
59
124k
    setter = fxBuildHostFunction(the, set, 1, XS_NO_ID);
60
124k
    slot = mxFunctionInstanceHome(setter);
61
124k
    slot->value.home.object = home->value.reference;
62
124k
    fxRenameFunction(the, setter, id, 0, XS_NO_ID, "set ");
63
124k
  }
64
1.49M
  property = property->next = fxNewSlot(the);
65
1.49M
  property->flag = flag;
66
1.49M
  property->ID = id;
67
1.49M
  property->kind = XS_ACCESSOR_KIND;
68
1.49M
  property->value.accessor.getter = getter;
69
1.49M
  property->value.accessor.setter = setter;
70
1.49M
  if (set)
71
124k
    mxPop();
72
1.49M
  if (get)
73
1.49M
    mxPop();
74
1.49M
  return property;
75
1.49M
}
76
77
txSlot* fxNextHostFunctionProperty(txMachine* the, txSlot* property, txCallback call, txInteger length, txID id, txFlag flag)
78
14.1M
{
79
14.1M
  txSlot *function, *home = the->stack, *slot;
80
14.1M
  function = fxNewHostFunction(the, call, length, id, XS_NO_ID);
81
14.1M
  slot = mxFunctionInstanceHome(function);
82
14.1M
  slot->value.home.object = home->value.reference;
83
14.1M
  property = property->next = fxNewSlot(the);
84
14.1M
  property->flag = flag;
85
14.1M
  property->ID = id;
86
14.1M
  property->kind = the->stack->kind;
87
14.1M
  property->value = the->stack->value;
88
14.1M
  mxPop();
89
14.1M
  return property;
90
14.1M
}
91
#endif
92
93
txSlot* fxNextUndefinedProperty(txMachine* the, txSlot* property, txID id, txFlag flag)
94
3.04M
{
95
3.04M
  property = property->next = fxNewSlot(the);
96
3.04M
  property->flag = flag;
97
3.04M
  property->ID = id;
98
3.04M
  property->kind = XS_UNDEFINED_KIND;
99
3.04M
  return property;
100
3.04M
}
101
102
txSlot* fxNextNullProperty(txMachine* the, txSlot* property, txID id, txFlag flag)
103
799k
{
104
799k
  property = property->next = fxNewSlot(the);
105
799k
  property->flag = flag;
106
799k
  property->ID = id;
107
799k
  property->kind = XS_NULL_KIND;
108
799k
  return property;
109
799k
}
110
111
txSlot* fxNextBooleanProperty(txMachine* the, txSlot* property, txBoolean boolean, txID id, txFlag flag)
112
2.72M
{
113
2.72M
  property = property->next = fxNewSlot(the);
114
2.72M
  property->flag = flag;
115
2.72M
  property->ID = id;
116
2.72M
  property->kind = XS_BOOLEAN_KIND;
117
2.72M
  property->value.boolean = boolean;
118
2.72M
  return property;
119
2.72M
}
120
121
txSlot* fxNextIntegerProperty(txMachine* the, txSlot* property, txInteger integer, txID id, txFlag flag)
122
32.2M
{
123
32.2M
  property = property->next = fxNewSlot(the);
124
32.2M
  property->flag = flag;
125
32.2M
  property->ID = id;
126
32.2M
  property->kind = XS_INTEGER_KIND;
127
32.2M
  property->value.integer = integer;
128
32.2M
  return property;
129
32.2M
}
130
131
txSlot* fxNextNumberProperty(txMachine* the, txSlot* property, txNumber number, txID id, txFlag flag)
132
13.4M
{
133
13.4M
  property = property->next = fxNewSlot(the);
134
13.4M
  property->flag = flag;
135
13.4M
  property->ID = id;
136
13.4M
  property->kind = XS_NUMBER_KIND;
137
13.4M
  property->value.number = number;
138
13.4M
  return property;
139
13.4M
}
140
141
txSlot* fxNextReferenceProperty(txMachine* the, txSlot* property, txSlot* slot, txID id, txFlag flag)
142
283k
{
143
283k
  property = property->next = fxNewSlot(the);
144
283k
  property->flag = flag;
145
283k
  property->ID = id;
146
283k
  property->kind = XS_REFERENCE_KIND;
147
283k
  property->value.reference = slot;
148
283k
  return property;
149
283k
}
150
151
txSlot* fxNextSlotProperty(txMachine* the, txSlot* property, txSlot* slot, txID id, txFlag flag)
152
88.5M
{
153
88.5M
  property = property->next = fxNewSlot(the);
154
88.5M
  property->flag = flag;
155
88.5M
  property->ID = id;
156
88.5M
  property->kind = slot->kind;
157
88.5M
  property->value = slot->value;
158
88.5M
  return property;
159
88.5M
}
160
161
txSlot* fxNextStringProperty(txMachine* the, txSlot* property, txString string, txID id, txFlag flag)
162
2.02M
{
163
2.02M
  property = property->next = fxNewSlot(the);
164
2.02M
  property->flag = flag;
165
2.02M
  property->ID = id;
166
2.02M
  fxCopyStringC(the, property, string);
167
2.02M
  return property;
168
2.02M
}
169
170
txSlot* fxNextStringXProperty(txMachine* the, txSlot* property, txString string, txID id, txFlag flag)
171
2.08M
{
172
2.08M
  property = property->next = fxNewSlot(the);
173
2.08M
  property->flag = flag;
174
2.08M
  property->ID = id;
175
2.08M
#ifdef mxSnapshot
176
2.08M
  fxCopyStringC(the, property, string);
177
#else
178
  property->kind = XS_STRING_X_KIND;
179
  property->value.string = string;
180
#endif
181
2.08M
  return property;
182
2.08M
}
183
184
185
txSlot* fxNextSymbolProperty(txMachine* the, txSlot* property, txID symbol, txID id, txFlag flag)
186
1.22M
{
187
1.22M
  property = property->next = fxNewSlot(the);
188
1.22M
  property->flag = flag;
189
1.22M
  property->ID = id;
190
1.22M
  property->kind = XS_SYMBOL_KIND;
191
1.22M
  property->value.symbol = symbol;
192
1.22M
  return property;
193
1.22M
}
194
195
txSlot* fxNextTypeDispatchProperty(txMachine* the, txSlot* property, txTypeDispatch* dispatch, txTypeAtomics* atomics, txID id, txFlag flag)
196
1.01M
{
197
1.01M
  property = property->next = fxNewSlot(the);
198
1.01M
  property->flag = flag;
199
1.01M
  property->ID = id;
200
1.01M
  property->kind = XS_TYPED_ARRAY_KIND;
201
1.01M
  property->value.typedArray.dispatch = dispatch;
202
1.01M
  property->value.typedArray.atomics = atomics;
203
1.01M
  return property;
204
1.01M
}
205
206
txSlot* fxQueueKey(txMachine* the, txID id, txIndex index, txSlot* keys)
207
65.1M
{
208
65.1M
  keys = keys->next = fxNewSlot(the);
209
65.1M
  keys->kind = XS_AT_KIND;
210
65.1M
  keys->value.at.id = id;
211
65.1M
  keys->value.at.index = index;
212
65.1M
  return keys;
213
65.1M
}
214
215
txSlot* fxQueueIDKeys(txMachine* the, txSlot* first, txFlag flag, txSlot* keys)
216
1.99M
{
217
1.99M
  if (flag & XS_EACH_NAME_FLAG) {
218
1.99M
    txSlot* property = first;
219
16.8M
    while (property) {
220
14.8M
      if (!(property->flag & XS_INTERNAL_FLAG) && fxIsKeyName(the, property->ID))
221
13.9M
        keys = fxQueueKey(the, property->ID, 0, keys);
222
14.8M
      property = property->next;
223
14.8M
    }
224
1.99M
  }
225
1.99M
  if (flag & XS_EACH_SYMBOL_FLAG) {
226
156k
    txSlot* property = first;
227
282k
    while (property) {
228
125k
      if (!(property->flag & XS_INTERNAL_FLAG) && fxIsKeySymbol(the, property->ID))
229
3.61k
        keys = fxQueueKey(the, property->ID, 0, keys);
230
125k
      property = property->next;
231
125k
    }
232
156k
  }
233
1.99M
  return keys;
234
1.99M
}
235
236
// INDEX
237
238
static txSize fxSizeToCapacity(txMachine* the, txSize size)
239
1.67M
{
240
1.67M
  return fxAddChunkSizes(the, size, size / 3);
241
1.67M
}
242
243
txBoolean fxDeleteIndexProperty(txMachine* the, txSlot* array, txIndex index) 
244
3.38M
{
245
3.38M
  txSlot* address = array->value.array.address;
246
3.38M
  if (address) {
247
3.20M
    txIndex length = array->value.array.length;
248
3.20M
    txIndex size = (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot);
249
3.20M
    txSlot* result = address;
250
3.20M
    txSlot* limit = result + size;
251
3.20M
    if (length == size)
252
1.74M
      result = address + index;
253
1.45M
    else {
254
1.45M
      txIndex at;
255
4.09M
      while (result < limit) {
256
2.76M
        at = *((txIndex*)result);
257
2.76M
        if (at == index)
258
671
          break;
259
2.76M
        if (at > index)
260
136k
          return 1;
261
2.63M
        result++;
262
2.63M
      }
263
1.45M
    }
264
3.07M
    if (result < limit) {
265
728
      if (result->flag & XS_DONT_DELETE_FLAG)
266
2
        return 0;
267
726
      index = (txIndex)(result - address);
268
726
      size--;
269
726
      if (size > 0) {
270
577
        txSlot* chunk = (txSlot*)fxNewChunk(the, size * sizeof(txSlot));
271
577
        address = array->value.array.address;
272
577
        if (index > 0)
273
448
          c_memcpy(chunk, address, index * sizeof(txSlot));
274
577
        if (index < size)
275
273
          c_memcpy(chunk + index, address + index + 1, (size - index) * sizeof(txSlot));
276
577
        array->value.array.address = chunk;
277
577
      }
278
149
      else
279
149
        array->value.array.address = C_NULL;
280
726
    }
281
3.07M
  }
282
3.25M
  return 1;
283
3.38M
}
284
285
txSlot* fxGetIndexProperty(txMachine* the, txSlot* array, txIndex index) 
286
196M
{
287
196M
  txSlot* address = array->value.array.address;
288
196M
  if (address) {
289
156M
    txIndex length = array->value.array.length;
290
156M
    txIndex size = (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot);
291
156M
    if (length == size) {
292
123M
      if (index < length)
293
90.2M
        return address + index;
294
123M
    }
295
33.3M
    else {
296
33.3M
      txSlot* result = address;
297
33.3M
      txSlot* limit = result + size;
298
33.3M
      txIndex at;
299
592M
      while (result < limit) {
300
563M
        at = *((txIndex*)result);
301
563M
        if (at == index)
302
4.31M
          return result;
303
559M
        result++;
304
559M
      }
305
33.3M
    }
306
156M
  }
307
102M
  return C_NULL;
308
196M
}
309
310
txIndex fxGetIndexSize(txMachine* the, txSlot* array)
311
0
{
312
0
  txSlot* address = array->value.array.address;
313
0
  if (address)
314
0
    return (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot);
315
0
  return 0;
316
0
}
317
318
txSlot* fxQueueIndexKeys(txMachine* the, txSlot* array, txFlag flag, txSlot* keys)
319
139k
{
320
139k
  if (flag & XS_EACH_NAME_FLAG) {
321
139k
    if (array->value.array.address) {
322
113k
      txSize offset = 0;
323
113k
      txSize size = (((txChunk*)(((txByte*)array->value.array.address) - sizeof(txChunk)))->size) / sizeof(txSlot);
324
32.1M
      while (offset < size) {
325
32.0M
        txSlot* slot = array->value.array.address + offset;
326
32.0M
        txIndex index = *((txIndex*)slot);
327
32.0M
        keys = fxQueueKey(the, 0, index, keys);
328
32.0M
        offset++;
329
32.0M
      }
330
113k
    }
331
139k
  }
332
139k
  return keys;
333
139k
}
334
335
txSlot* fxSetIndexProperty(txMachine* the, txSlot* instance, txSlot* array, txIndex index) 
336
24.1M
{
337
24.1M
  txSlot* address = array->value.array.address;
338
24.1M
  txSlot* chunk = address;
339
24.1M
  txIndex length = array->value.array.length;
340
24.1M
  txIndex current;
341
24.1M
  txSize size;
342
24.1M
  txSlot* result;
343
24.1M
  txSlot* limit;
344
24.1M
  txIndex at;
345
24.1M
  if (address) {
346
18.3M
    current = (((txChunk*)(((txByte*)chunk) - sizeof(txChunk)))->size) / sizeof(txSlot);
347
18.3M
    if (length == current) {
348
12.3M
      if (index < length) 
349
0
        return address + index;
350
12.3M
      if (instance->flag & XS_DONT_PATCH_FLAG)
351
0
        return C_NULL;
352
12.3M
      if (array->flag & XS_DONT_SET_FLAG)
353
1
        return C_NULL;
354
12.3M
      current++;
355
12.3M
      size = fxMultiplyChunkSizes(the, current, sizeof(txSlot));
356
12.3M
      chunk = (txSlot*)fxRenewChunk(the, address, size);
357
12.3M
      if (!chunk) {
358
4.07M
      #ifndef mxNoArrayOverallocation
359
4.07M
        if (array->ID == XS_ARRAY_BEHAVIOR) {
360
1.67M
          txSize capacity = fxSizeToCapacity(the, size);
361
1.67M
          chunk = (txSlot*)fxNewGrowableChunk(the, size, capacity);
362
1.67M
        }
363
2.40M
        else
364
2.40M
      #endif
365
2.40M
          chunk = (txSlot*)fxNewChunk(the, size);
366
4.07M
        address = array->value.array.address;
367
4.07M
        c_memcpy(chunk, address, length * sizeof(txSlot));
368
4.07M
      }
369
12.3M
      result = chunk + length;
370
12.3M
    }
371
6.02M
    else {
372
6.02M
      result = address;
373
6.02M
      limit = result + current;
374
278M
      while (result < limit) {
375
274M
        at = *((txIndex*)result);
376
274M
        if (at == index)
377
0
          return result;
378
274M
        if (at > index)
379
1.72M
          break;
380
272M
        result++;
381
272M
      }
382
6.02M
      if (instance->flag & XS_DONT_PATCH_FLAG)
383
0
        return C_NULL;
384
6.02M
      if ((array->flag & XS_DONT_SET_FLAG) && (index >= length))
385
0
        return C_NULL;
386
6.02M
      at = mxPtrDiff(result - address);
387
6.02M
      current++;
388
6.02M
      size = fxMultiplyChunkSizes(the, current, sizeof(txSlot));
389
6.02M
      chunk = (txSlot*)fxNewChunk(the, size);
390
6.02M
      address = array->value.array.address;
391
6.02M
      result = address + at;
392
6.02M
      limit = address + current - 1;
393
6.02M
      if (result > address)
394
5.75M
        c_memcpy(chunk, address, (result - address) * sizeof(txSlot));
395
6.02M
      if (result < limit)
396
1.72M
        c_memcpy(chunk + (result - address) + 1, result, (limit - result) * sizeof(txSlot));
397
6.02M
      result = chunk + (result - address);
398
6.02M
    }
399
18.3M
  }
400
5.83M
  else {
401
5.83M
        if (instance->flag & XS_DONT_PATCH_FLAG)
402
0
            return C_NULL;
403
5.83M
    if ((array->flag & XS_DONT_SET_FLAG) && (index >= length))
404
0
      return C_NULL;
405
5.83M
    current = 1;
406
5.83M
    chunk = (txSlot*)fxNewChunk(the, sizeof(txSlot));
407
5.83M
    result = chunk;
408
5.83M
  }
409
24.1M
  result->next = C_NULL;
410
24.1M
  result->ID = XS_NO_ID;
411
24.1M
  result->flag = XS_NO_FLAG;
412
24.1M
  result->kind = XS_UNDEFINED_KIND;
413
24.1M
  *((txIndex*)result) = index;  
414
24.1M
  array->value.array.address = chunk;
415
24.1M
  if (index >= length) {
416
13.7M
    array->value.array.length = index + 1;
417
13.7M
  }
418
24.1M
  return result;
419
24.1M
}
420
421
void fxSetIndexSize(txMachine* the, txSlot* array, txIndex target, txBoolean growable)
422
8.40M
{
423
8.40M
  txSlot* address = array->value.array.address;
424
8.40M
  txSlot* chunk = C_NULL;
425
8.40M
  txIndex current = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0;
426
8.40M
  txSize size;
427
8.40M
  if (current != target) {
428
1.32M
    if (array->flag & XS_DONT_SET_FLAG)
429
0
      mxTypeError("set length: not writable");
430
1.32M
    size = fxMultiplyChunkSizes(the, target, sizeof(txSlot));
431
1.32M
    if (address) {
432
460k
      if (target) {
433
454k
        chunk = (txSlot*)fxRenewChunk(the, address, size);
434
454k
        if (!chunk) {
435
1.32k
        #ifndef mxNoArrayOverallocation
436
1.32k
          if (growable) {
437
1.32k
            txSize capacity = fxSizeToCapacity(the, size);
438
1.32k
            chunk = (txSlot*)fxNewGrowableChunk(the, size, capacity);
439
1.32k
          }
440
5
          else
441
5
        #endif
442
5
            chunk = (txSlot*)fxNewChunk(the, size);
443
1.32k
          address = array->value.array.address;
444
1.32k
          if (current < target)
445
1.32k
            c_memcpy(chunk, address, current * sizeof(txSlot));
446
0
          else
447
0
            c_memcpy(chunk, address, size);
448
1.32k
        }
449
454k
      }
450
460k
    }
451
861k
    else {
452
861k
    #ifndef mxNoArrayOverallocation
453
861k
      if (growable) {
454
591
        txSize capacity = fxSizeToCapacity(the, size);
455
591
        chunk = (txSlot*)fxNewGrowableChunk(the, size, capacity);
456
591
      }
457
861k
      else
458
861k
    #endif
459
861k
        chunk = (txSlot*)fxNewChunk(the, size);
460
861k
    }
461
1.32M
    if (current < target)
462
1.30M
      c_memset(chunk + current, 0, (target - current) * sizeof(txSlot));
463
1.32M
    array->value.array.length = target;
464
1.32M
    array->value.array.address = chunk;
465
1.32M
  }
466
8.40M
}
467
468
txBoolean fxDefinePrivateProperty(txMachine* the, txSlot* instance, txSlot* check, txID id, txSlot* slot, txFlag mask) 
469
21.8k
{
470
21.8k
  txSlot** address;
471
21.8k
  txSlot* property;
472
21.8k
  mxCheck(the, instance->kind == XS_INSTANCE_KIND);
473
#if mxAliasInstance
474
  if (instance->ID) {
475
    txSlot* alias = the->aliasArray[instance->ID];
476
    if (alias)
477
      instance = alias;
478
    else
479
      instance = fxAliasInstance(the, instance);
480
  }
481
  if (instance->flag & XS_MARK_FLAG)
482
    return 0;
483
#else
484
21.8k
  if (instance->flag & XS_DONT_MARSHALL_FLAG)
485
1
    return 0;
486
21.8k
#endif
487
21.8k
  if (mxIsModule(instance)) {
488
0
    instance = mxModuleInstanceExports(instance)->value.reference;
489
0
  }
490
21.8k
  address = &(instance->next);
491
29.1k
  while ((property = *address)) {
492
10.9k
    if (!(property->flag & XS_INTERNAL_FLAG)) {
493
21
      property = C_NULL;
494
21
      break;
495
21
    }
496
10.9k
    if (property->kind == XS_PRIVATE_KIND) {
497
3.65k
      if (property->value.private.check == check) {
498
3.64k
        break;
499
3.64k
      }
500
3.65k
    }
501
7.30k
    address = &(property->next);
502
7.30k
  }
503
21.8k
  if (!property) {
504
18.1k
    property = fxNewSlot(the);
505
18.1k
    property->next = *address;
506
18.1k
    property->flag = XS_INTERNAL_FLAG;
507
18.1k
    property->kind = XS_PRIVATE_KIND;
508
18.1k
    property->value.private.check = check;
509
18.1k
    property->value.private.first = C_NULL;
510
18.1k
    *address = property;
511
18.1k
  }
512
21.8k
  address = &(property->value.private.first);
513
25.4k
  while ((property = *address)) {
514
3.65k
    if (property->ID == id)
515
0
      break;
516
3.65k
    address = &(property->next);
517
3.65k
  }
518
21.8k
  if (mask & XS_ACCESSOR_FLAG) {
519
1
    if (property) {
520
0
      if (property->kind != XS_ACCESSOR_KIND)
521
0
        return 0;
522
0
    }
523
1
    else {
524
1
      *address = property = fxNewSlot(the);
525
1
      property->ID = id;
526
1
      property->kind = XS_ACCESSOR_KIND;
527
1
      property->value.accessor.getter = C_NULL;
528
1
      property->value.accessor.setter = C_NULL;
529
1
    }
530
1
    if (mask & XS_GETTER_FLAG) {
531
1
      txSlot* function = slot->value.accessor.getter;
532
1
      if (property->value.accessor.getter)
533
0
        return 0;
534
1
      property->value.accessor.getter = function;
535
1
      if (mxIsFunction(function)) {
536
1
        if (((mask & XS_METHOD_FLAG) && (function->flag & XS_MARK_FLAG) == 0)) {
537
1
          txSlot* home = mxFunctionInstanceHome(function);
538
1
          home->value.home.object = instance;
539
1
        }
540
1
        if ((mask & XS_NAME_FLAG) && ((function->flag & XS_MARK_FLAG) == 0))
541
1
          fxRenameFunction(the, function, id, 0, mxID(_get), "get ");
542
1
      }
543
1
    }
544
0
    else {
545
0
      txSlot* function = slot->value.accessor.setter;
546
0
      if (property->value.accessor.setter)
547
0
        return 0;
548
0
      property->value.accessor.setter = function;
549
0
      if (mxIsFunction(function)) {
550
0
        if (((mask & XS_METHOD_FLAG) && (function->flag & XS_MARK_FLAG) == 0)) {
551
0
          txSlot* home = mxFunctionInstanceHome(function);
552
0
          home->value.home.object = instance;
553
0
        }
554
0
        if ((mask & XS_NAME_FLAG) && ((function->flag & XS_MARK_FLAG) == 0))
555
0
          fxRenameFunction(the, function, id, 0, mxID(_set), "set ");
556
0
      }
557
0
    }
558
1
  }
559
21.8k
  else {
560
21.8k
    if (property)
561
0
      return 0;
562
21.8k
    *address = property = fxNewSlot(the);
563
21.8k
    property->flag = (mask & XS_METHOD_FLAG) ? XS_DONT_SET_FLAG : XS_NO_FLAG;
564
21.8k
    property->ID = id;
565
21.8k
    property->kind = slot->kind;
566
21.8k
    property->value = slot->value;
567
21.8k
    if (property->kind == XS_REFERENCE_KIND) {
568
17
      txSlot* function = slot->value.reference;
569
17
      if (mxIsFunction(function)) {
570
14
        if ((mask & XS_METHOD_FLAG) && ((function->flag & XS_MARK_FLAG) == 0)) {
571
13
          txSlot* home = mxFunctionInstanceHome(function);
572
13
          home->value.home.object = instance;
573
13
        }
574
14
        if ((mask & XS_NAME_FLAG) && ((function->flag & XS_MARK_FLAG) == 0))
575
14
          fxRenameFunction(the, function, id, 0, mxID(_value), C_NULL);
576
14
      }
577
17
    }
578
21.8k
  }
579
21.8k
  return 1;
580
21.8k
}
581
582
txSlot* fxGetPrivateProperty(txMachine* the, txSlot* instance, txSlot* check, txID id) 
583
9.03k
{
584
9.03k
    txSlot* result;
585
9.03k
  mxCheck(the, instance->kind == XS_INSTANCE_KIND);
586
#if mxAliasInstance
587
  if (instance->ID) {
588
    txSlot* alias = the->aliasArray[instance->ID];
589
    if (alias)
590
      instance = alias;
591
  }
592
#endif
593
9.03k
  if (mxIsModule(instance)) {
594
0
    instance = mxModuleInstanceExports(instance)->value.reference;
595
0
  }
596
9.03k
  result = instance->next;
597
9.07k
  while (result) {
598
9.07k
    if (result->kind == XS_PRIVATE_KIND) {
599
9.03k
      if (result->value.private.check == check)
600
9.03k
        break;
601
9.03k
    }
602
39
    result = result->next;
603
39
  }
604
9.03k
  if (result) {
605
9.03k
    result = result->value.private.first;
606
9.03k
    while (result) {
607
9.03k
      if (result->ID == id)
608
9.03k
        break;
609
0
      result = result->next;
610
0
    }
611
9.03k
  }
612
9.03k
  if (result) {
613
9.03k
    if ((result->kind == XS_ACCESSOR_KIND) && (result->value.accessor.getter == C_NULL))
614
0
      result = C_NULL;
615
9.03k
  }
616
9.03k
  return result;
617
9.03k
}
618
619
txSlot* fxSetPrivateProperty(txMachine* the, txSlot* instance, txSlot* check, txID id) 
620
11
{
621
11
    txSlot* result;
622
11
  mxCheck(the, instance->kind == XS_INSTANCE_KIND);
623
#if mxAliasInstance
624
  if (instance->ID) {
625
    txSlot* alias = the->aliasArray[instance->ID];
626
    if (alias)
627
      instance = alias;
628
    else
629
      instance = fxAliasInstance(the, instance);
630
  }
631
#endif
632
11
  if (mxIsModule(instance)) {
633
0
    instance = mxModuleInstanceExports(instance)->value.reference;
634
0
  }
635
11
  result = instance->next;
636
15
  while (result) {
637
13
    if (result->kind == XS_PRIVATE_KIND) {
638
9
      if (result->value.private.check == check)
639
9
        break;
640
9
    }
641
4
    result = result->next;
642
4
  }
643
11
  if (result) {
644
9
    result = result->value.private.first;
645
9
    while (result) {
646
9
      if (result->ID == id)
647
9
        break;
648
0
      result = result->next;
649
0
    }
650
9
  }
651
11
  if (result) {
652
9
    if ((result->kind == XS_ACCESSOR_KIND) && (result->value.accessor.setter == C_NULL))
653
0
      result = C_NULL;
654
9
  }
655
11
  return result;
656
11
}
657
658
void fxGroupBy(txMachine* the, txCallback aux) 
659
3.92k
{
660
3.92k
  txSlot *function, *iterable, *iterator, *next, *value, *slot;
661
3.92k
  txNumber k = 0;
662
3.92k
  if ((mxArgc < 1) || mxIsUndefined(mxArgv(0)) || mxIsUndefined(mxArgv(1)))
663
1.30k
    mxTypeError("items: not an object");
664
2.62k
  if ((mxArgc < 2) || (!fxIsCallable(the, mxArgv(1))))
665
2.59k
    mxTypeError("callback: not a function");
666
37
  function = mxArgv(1);
667
37
  iterable = mxArgv(0);
668
37
  mxTemporary(iterator);
669
37
  mxTemporary(next);
670
37
  fxGetIterator(the, iterable, iterator, next, 0);
671
37
  mxTemporary(value);
672
1.37k
  while (fxIteratorNext(the, iterator, next, value)) {
673
1.33k
    mxTry(the) {
674
1.33k
      if (k > C_MAX_SAFE_INTEGER)
675
0
        mxTypeError("unsafe integer");
676
1.33k
      mxPushUndefined();
677
1.33k
      mxPushSlot(function);
678
1.33k
      mxCall();
679
1.33k
      mxPushSlot(value);
680
1.33k
      mxPushNumber(k);
681
1.33k
      mxRunCount(2);
682
1.33k
      aux(the);
683
1.33k
      slot = the->stack->value.reference->next;
684
1.33k
      slot->value.array.length++;
685
24.8k
      while (slot->next)
686
23.4k
        slot = slot->next;
687
1.33k
      slot->next = fxDuplicateSlot(the, value);
688
1.33k
      mxPop();
689
1.33k
      mxPop();
690
1.33k
      k++;
691
1.33k
    }
692
1.33k
    mxCatch(the) {
693
1
      fxIteratorReturn(the, iterator, 1);
694
1
      fxJump(the);
695
1
    }
696
1.33k
  }
697
36
  mxPop();
698
36
  mxPop();
699
36
  mxPop();
700
36
}
701
702
703
704
705
706