Coverage Report

Created: 2025-06-13 06:10

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