Coverage Report

Created: 2026-07-14 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsProxy.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
static txSlot* fxNewProxyInstance(txMachine* the);
41
static txSlot* fxCheckProxyFunction(txMachine* the, txSlot* proxy, txID index);
42
43
static void fxProxyCall(txMachine* the, txSlot* instance, txSlot* _this, txSlot* arguments);
44
static void fxProxyConstruct(txMachine* the, txSlot* instance, txSlot* arguments, txSlot* target);
45
static txBoolean fxProxyDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask);
46
static txBoolean fxProxyDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
47
static txBoolean fxProxyGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot);
48
static txSlot* fxProxyGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
49
static txBoolean fxProxyGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* receiver, txSlot* value);
50
static txBoolean fxProxyGetPrototype(txMachine* the, txSlot* instance, txSlot* result);
51
static txBoolean fxProxyHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
52
static txBoolean fxProxyIsExtensible(txMachine* the, txSlot* instance);
53
static void fxProxyOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* list);
54
static txBoolean fxProxyPreventExtensions(txMachine* the, txSlot* instance);
55
static txSlot* fxProxySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
56
static txBoolean fxProxySetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver);
57
static txBoolean fxProxySetPrototype(txMachine* the, txSlot* instance, txSlot* prototype);
58
59
const txBehavior ICACHE_FLASH_ATTR gxProxyBehavior = {
60
  fxProxyGetProperty,
61
  fxProxySetProperty,
62
  fxProxyCall,
63
  fxProxyConstruct,
64
  fxProxyDefineOwnProperty,
65
  fxProxyDeleteProperty,
66
  fxProxyGetOwnProperty,
67
  fxProxyGetPropertyValue,
68
  fxProxyGetPrototype,
69
  fxProxyHasProperty,
70
  fxProxyIsExtensible,
71
  fxProxyOwnKeys,
72
  fxProxyPreventExtensions,
73
  fxProxySetPropertyValue,
74
  fxProxySetPrototype,
75
};
76
77
void fxBuildProxy(txMachine* the)
78
32.3k
{
79
32.3k
  txSlot* slot;
80
81
32.3k
  fxNewHostFunction(the, mxCallback(fxProxyGetter), 0, XS_NO_ID, XS_NO_ID);
82
32.3k
  fxNewHostFunction(the, mxCallback(fxProxySetter), 1, XS_NO_ID, XS_NO_ID);
83
32.3k
  mxPushUndefined();
84
32.3k
  the->stack->flag = XS_DONT_DELETE_FLAG;
85
32.3k
  the->stack->kind = XS_ACCESSOR_KIND;
86
32.3k
  the->stack->value.accessor.getter = (the->stack + 2)->value.reference;
87
32.3k
  the->stack->value.accessor.setter = (the->stack + 1)->value.reference;
88
32.3k
  mxPull(mxProxyAccessor);
89
32.3k
  the->stack += 2;
90
  
91
32.3k
  slot = fxBuildHostFunction(the, mxCallback(fx_Proxy), 2, mxID(_Proxy));
92
32.3k
  slot->flag |= XS_CAN_CONSTRUCT_FLAG;
93
32.3k
  mxProxyConstructor = *the->stack;
94
32.3k
  slot = fxLastProperty(the, slot);
95
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Proxy_revocable), 2, mxID(_revocable), XS_DONT_ENUM_FLAG);
96
32.3k
  mxPop();
97
98
32.3k
  mxPush(mxObjectPrototype);
99
32.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
100
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_apply), 3, mxID(_apply), XS_DONT_ENUM_FLAG);
101
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_construct), 2, mxID(_construct), XS_DONT_ENUM_FLAG);
102
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_defineProperty), 3, mxID(_defineProperty), XS_DONT_ENUM_FLAG);
103
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_deleteProperty), 2, mxID(_deleteProperty), XS_DONT_ENUM_FLAG);
104
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_get), 2, mxID(_get), XS_DONT_ENUM_FLAG);
105
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_getOwnPropertyDescriptor), 2, mxID(_getOwnPropertyDescriptor), XS_DONT_ENUM_FLAG);
106
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_getPrototypeOf), 1, mxID(_getPrototypeOf), XS_DONT_ENUM_FLAG);
107
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_has), 2, mxID(_has), XS_DONT_ENUM_FLAG);
108
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_isExtensible), 1, mxID(_isExtensible), XS_DONT_ENUM_FLAG);
109
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_ownKeys), 1, mxID(_ownKeys), XS_DONT_ENUM_FLAG);
110
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_preventExtensions), 1, mxID(_preventExtensions), XS_DONT_ENUM_FLAG);
111
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_set), 3, mxID(_set), XS_DONT_ENUM_FLAG);
112
32.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Reflect_setPrototypeOf), 2, mxID(_setPrototypeOf), XS_DONT_ENUM_FLAG);
113
32.3k
  slot = fxNextStringXProperty(the, slot, "Reflect", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
114
32.3k
  mxPull(mxReflectObject);
115
32.3k
}
116
117
txSlot* fxNewProxyInstance(txMachine* the)
118
1.43M
{
119
1.43M
  txSlot* prototype;
120
1.43M
  txSlot* instance;
121
1.43M
  txSlot* property;
122
1.43M
  txSlot* slot;
123
  
124
1.43M
  prototype = mxIsReference(the->stack) ? the->stack->value.reference : C_NULL;
125
  
126
1.43M
  instance = fxNewSlot(the);
127
1.43M
  instance->flag = XS_EXOTIC_FLAG;
128
1.43M
  instance->kind = XS_INSTANCE_KIND;
129
1.43M
  instance->value.instance.garbage = C_NULL;
130
1.43M
  instance->value.instance.prototype = C_NULL;
131
1.43M
  the->stack->kind = XS_REFERENCE_KIND;
132
1.43M
  the->stack->value.reference = instance;
133
134
1.43M
  property = instance->next = fxNewSlot(the);
135
1.43M
  property->flag = XS_INTERNAL_FLAG;
136
1.43M
  property->kind = XS_PROXY_KIND;
137
1.43M
  property->ID = XS_PROXY_BEHAVIOR;
138
1.43M
  if (prototype && ((slot = prototype->next)) && (slot->kind = XS_PROXY_KIND)) {
139
0
    property->value.proxy.handler = slot->value.proxy.handler;
140
0
    property->value.proxy.target = slot->value.proxy.target;
141
0
  }
142
1.43M
  else {
143
1.43M
    property->value.proxy.handler = C_NULL;
144
1.43M
    property->value.proxy.target = C_NULL;
145
1.43M
    }
146
  
147
1.43M
  return instance;
148
1.43M
}
149
150
#define mxProxyDeclarations(ID) \
151
1.02M
  txSlot* proxy = instance->next; \
152
1.02M
  txSlot* function = fxCheckProxyFunction(the, proxy, ID); \
153
1.02M
  txSlot* handler = the->stack + 1; \
154
1.02M
  txSlot* target = the->stack + 2
155
  
156
#define mxProxyPop() \
157
1.02M
  mxPop(); \
158
1.02M
  mxPop(); \
159
1.02M
  mxPop()
160
161
txSlot* fxCheckProxyFunction(txMachine* the, txSlot* proxy, txID index)
162
1.02M
{
163
1.02M
  txSlot* function;
164
1.02M
  mxCheckCStack();
165
1.02M
  if (!proxy->value.proxy.handler)
166
11
    mxTypeError("(proxy).%s: no handler", fxName(the, mxID(index)));
167
1.02M
  if (!proxy->value.proxy.target)
168
0
    mxTypeError("(proxy).%s: no target", fxName(the, mxID(index)));
169
1.02M
  mxPushReference(proxy->value.proxy.target);
170
1.02M
  mxPushReference(proxy->value.proxy.handler);
171
1.02M
  mxDub();
172
1.02M
  mxGetID(mxID(index));
173
1.02M
  function = the->stack;
174
1.02M
  if (mxIsUndefined(function) || (mxIsNull(function)))
175
902k
    function = C_NULL;
176
125k
  else if (!fxIsCallable(the, function))
177
7
    mxTypeError("(proxy).%s: not a function", fxName(the, mxID(index)));
178
1.02M
  return function;
179
1.02M
}
180
181
void fxProxyGetter(txMachine* the)
182
116k
{
183
116k
  txSlot* instance = fxToInstance(the, mxThis);
184
189k
  while (instance) {
185
189k
    if (mxIsProxy(instance))
186
116k
      break;
187
72.2k
    instance = fxGetPrototype(the, instance);
188
72.2k
  }
189
116k
  if (instance) {
190
116k
    txID id = the->scratch.value.at.id;
191
116k
    txIndex index = the->scratch.value.at.index;
192
116k
    fxProxyGetPropertyValue(the, instance, id, index, mxThis, mxResult);
193
116k
  }
194
116k
}
195
196
void fxProxySetter(txMachine* the)
197
223k
{
198
223k
  txSlot* instance = fxToInstance(the, mxThis);
199
445k
  while (instance) {
200
445k
    if (mxIsProxy(instance))
201
223k
      break;
202
221k
    instance = fxGetPrototype(the, instance);
203
221k
  }
204
223k
  if (instance) {
205
223k
    txID id = the->scratch.value.at.id;
206
223k
    txIndex index = the->scratch.value.at.index;
207
223k
    txBoolean result = fxProxySetPropertyValue(the, instance, id, index, mxArgv(0), mxThis);
208
223k
        if (!result) {
209
20
            if (the->frame->next->flag & XS_STRICT_FLAG)
210
4
        mxTypeError("(proxy).set: not extensible or not writable");
211
20
        }
212
223k
  }
213
223k
}
214
215
void fxProxyCall(txMachine* the, txSlot* instance, txSlot* _this, txSlot* arguments)
216
134k
{
217
134k
  mxProxyDeclarations(_apply);
218
134k
  if (function) {
219
    /* THIS */
220
50.3k
    mxPushSlot(handler);
221
    /* FUNCTION */
222
50.3k
    mxPushSlot(function);
223
50.3k
    mxCall();
224
    /* ARGUMENTS */
225
50.3k
    mxPushSlot(target);
226
50.3k
    mxPushSlot(_this);
227
50.3k
    mxPushSlot(arguments);
228
50.3k
    mxRunCount(3);
229
50.3k
    mxPullSlot(mxResult);
230
50.3k
  }
231
83.7k
  else 
232
83.7k
    mxBehaviorCall(the, target->value.reference, _this, arguments);
233
134k
  mxProxyPop();
234
134k
}
235
236
void fxProxyConstruct(txMachine* the, txSlot* instance, txSlot* arguments, txSlot* newTarget)
237
21.8k
{
238
21.8k
  mxProxyDeclarations(_construct);
239
21.8k
  if (function) {
240
    /* THIS */
241
2
    mxPushSlot(handler);
242
    /* FUNCTION */
243
2
    mxPushSlot(function);
244
2
    mxCall();
245
    /* ARGUMENTS */
246
2
    mxPushSlot(target);
247
2
    mxPushSlot(arguments);
248
2
    mxPushSlot(newTarget);
249
2
    mxRunCount(3);
250
2
    mxPullSlot(mxResult);
251
2
    if (!mxIsReference(mxResult))
252
1
      mxTypeError("(proxy).construct: not an object");
253
2
  }
254
21.7k
  else 
255
21.7k
    mxBehaviorConstruct(the, target->value.reference, arguments, newTarget);
256
21.8k
  mxProxyPop();
257
21.7k
}
258
259
txBoolean fxProxyDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask)
260
2.71k
{
261
2.71k
  txBoolean result;
262
2.71k
  mxProxyDeclarations(_defineProperty);
263
2.71k
  if (function) {
264
    /* THIS */
265
2.57k
    mxPushSlot(handler);
266
    /* FUNCTION */
267
2.57k
    mxPushSlot(function);
268
2.57k
    mxCall();
269
    /* ARGUMENTS */
270
2.57k
    mxPushSlot(target);
271
2.57k
    mxPushUndefined();
272
2.57k
    fxKeyAt(the, id, index, the->stack);
273
2.57k
    fxDescribeProperty(the, slot, mask);
274
2.57k
    mxRunCount(3);
275
2.57k
    result = fxToBoolean(the, the->stack);
276
2.57k
    mxPop();
277
2.57k
    if (result) {
278
41
      mxPushUndefined();
279
41
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
280
27
        if (fxIsPropertyCompatible(the, the->stack, slot, mask)) {
281
26
          if ((mask & XS_DONT_DELETE_FLAG) && (slot->flag & XS_DONT_DELETE_FLAG)) {
282
9
            if (!(the->stack->flag & XS_DONT_DELETE_FLAG))
283
1
              mxTypeError("(proxy).defineProperty: true with non-configurable descriptor for configurable property");
284
9
          }
285
25
          if (the->stack->flag & XS_DONT_DELETE_FLAG) {
286
11
            if ((mask & XS_DONT_SET_FLAG) && (slot->flag & XS_DONT_SET_FLAG) && !(the->stack->flag & XS_DONT_SET_FLAG))
287
1
              mxTypeError("(proxy).defineProperty: true with non-writable descriptor for non-configurable writable property");
288
11
          }
289
25
        }
290
1
        else
291
1
          mxTypeError("(proxy).defineProperty: true with incompatible descriptor for existent property");
292
27
      }
293
14
      else if (mxBehaviorIsExtensible(the, target->value.reference)) {
294
13
        if ((mask & XS_DONT_DELETE_FLAG) && (slot->flag & XS_DONT_DELETE_FLAG))
295
1
          mxTypeError("(proxy).defineProperty: true with non-configurable descriptor for non-existent property");
296
13
      }
297
1
      else
298
1
        mxTypeError("(proxy).defineProperty: true with descriptor for non-existent property of non-extensible object");
299
36
      mxPop();
300
36
    }
301
2.57k
  }
302
135
  else
303
135
    result = mxBehaviorDefineOwnProperty(the, target->value.reference, id, index, slot, mask);
304
2.71k
  mxProxyPop();
305
2.70k
  return result;
306
2.71k
}
307
308
txBoolean fxProxyDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
309
96
{
310
96
  txBoolean result;
311
96
  mxProxyDeclarations(_deleteProperty);
312
96
  if (function) {
313
    /* THIS */
314
27
    mxPushSlot(handler);
315
    /* FUNCTION */
316
27
    mxPushSlot(function);
317
27
    mxCall();
318
    /* ARGUMENTS */
319
27
    mxPushSlot(target);
320
27
    mxPushUndefined();
321
27
    fxKeyAt(the, id, index, the->stack);
322
27
    mxRunCount(2);
323
27
    result = fxToBoolean(the, the->stack);
324
27
    mxPop();
325
27
    if (result) {
326
15
      mxPushUndefined();
327
15
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
328
5
        if (the->stack->flag & XS_DONT_DELETE_FLAG)
329
1
          mxTypeError("(proxy).deleteProperty: true for non-configurable property");
330
4
        if (!mxBehaviorIsExtensible(the, target->value.reference))
331
2
          mxTypeError("(proxy).deleteProperty: true for non-extensible object");
332
4
      }
333
12
      mxPop();
334
12
    }
335
27
  }
336
69
  else
337
69
    result = mxBehaviorDeleteProperty(the, target->value.reference, id, index);
338
96
  mxProxyPop();
339
93
  return result;
340
96
}
341
342
txBoolean fxProxyGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot)
343
5.39k
{
344
5.39k
  txBoolean result;
345
5.39k
  mxProxyDeclarations(_getOwnPropertyDescriptor);
346
5.39k
  if (function) {
347
5.25k
    txFlag mask;
348
    /* THIS */
349
5.25k
    mxPushSlot(handler);
350
    /* FUNCTION */
351
5.25k
    mxPushSlot(function);
352
5.25k
    mxCall();
353
    /* ARGUMENTS */
354
5.25k
    mxPushSlot(target);
355
5.25k
    mxPushUndefined();
356
5.25k
    fxKeyAt(the, id, index, the->stack);
357
5.25k
    mxRunCount(2);
358
5.25k
    mxPullSlot(slot);
359
5.25k
    mxPushUndefined();
360
5.25k
    if (slot->kind == XS_UNDEFINED_KIND) {
361
2.55k
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
362
19
        if (the->stack->flag & XS_DONT_DELETE_FLAG)
363
1
          mxTypeError("(proxy).getOwnPropertyDescriptor: no descriptor for non-configurable property");
364
18
        if (!mxBehaviorIsExtensible(the, target->value.reference)) 
365
1
          mxTypeError("(proxy).getOwnPropertyDescriptor: no descriptor for existent property of non-extensible object");
366
18
      }
367
2.55k
      result = 0;
368
2.55k
    }
369
2.69k
    else {
370
2.69k
      mask = fxDescriptorToSlot(the, slot);
371
2.69k
      if (!(mask & XS_DONT_DELETE_FLAG)) {
372
2
        mask |= XS_DONT_DELETE_FLAG;
373
2
        slot->flag |= XS_DONT_DELETE_FLAG;
374
2
      }
375
2.69k
      if (!(mask & XS_DONT_ENUM_FLAG)) {
376
15
        mask |= XS_DONT_ENUM_FLAG;
377
15
        slot->flag |= XS_DONT_ENUM_FLAG;
378
15
      }
379
2.69k
      if (!(mask & (XS_GETTER_FLAG | XS_SETTER_FLAG))) {
380
69
        if (!(mask & XS_DONT_SET_FLAG)) {
381
6
          mask |= XS_DONT_SET_FLAG;
382
6
          slot->flag |= XS_DONT_SET_FLAG;
383
6
        }
384
69
        if (slot->kind == XS_UNINITIALIZED_KIND)
385
9
          slot->kind = XS_UNDEFINED_KIND;
386
69
      }
387
2.69k
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
388
47
        if (fxIsPropertyCompatible(the, the->stack, slot, mask)) {
389
46
          if ((mask & XS_DONT_DELETE_FLAG) && (slot->flag & XS_DONT_DELETE_FLAG)) {
390
28
            if (!(the->stack->flag & XS_DONT_DELETE_FLAG))
391
1
              mxTypeError("(proxy).getOwnPropertyDescriptor: non-configurable descriptor for configurable property");
392
28
          }
393
45
          if (the->stack->flag & XS_DONT_DELETE_FLAG) {
394
27
            if ((mask & XS_DONT_SET_FLAG) && (slot->flag & XS_DONT_SET_FLAG) && !(the->stack->flag & XS_DONT_SET_FLAG))
395
1
              mxTypeError("(proxy).getOwnPropertyDescriptor: true with non-writable descriptor for non-configurable writable property");
396
27
          }
397
45
        }
398
1
        else
399
1
          mxTypeError("(proxy).getOwnPropertyDescriptor: incompatible descriptor for existent property");
400
47
      }
401
2.64k
      else if (mxBehaviorIsExtensible(the, target->value.reference)) {
402
22
        if ((mask & XS_DONT_DELETE_FLAG) && (slot->flag & XS_DONT_DELETE_FLAG))
403
1
          mxTypeError("(proxy).getOwnPropertyDescriptor: non-configurable descriptor for non-existent property");
404
22
      }
405
2.62k
      else
406
2.62k
        mxTypeError("(proxy).getOwnPropertyDescriptor: descriptor for non-existent property of non-extensible object");
407
65
      result = 1;
408
65
    }
409
2.62k
    mxPop();
410
2.62k
  }
411
146
  else
412
146
    result = mxBehaviorGetOwnProperty(the, target->value.reference, id, index, slot);
413
5.39k
  mxProxyPop();
414
2.76k
  return result;
415
5.39k
}
416
417
txSlot* fxProxyGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
418
335k
{
419
335k
  the->scratch.value.at.id = id;
420
335k
  the->scratch.value.at.index = index;
421
335k
  return &mxProxyAccessor;
422
335k
}
423
424
txBoolean fxProxyGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* receiver, txSlot* slot)
425
172k
{
426
172k
  txBoolean result;
427
172k
  mxProxyDeclarations(_get);
428
172k
  if (function) {
429
    /* THIS */
430
31.5k
    mxPushSlot(handler);
431
    /* FUNCTION */
432
31.5k
    mxPushSlot(function);
433
31.5k
    mxCall();
434
    /* ARGUMENTS */
435
31.5k
    mxPushSlot(target);
436
31.5k
    mxPushUndefined();
437
31.5k
    fxKeyAt(the, id, index, the->stack);
438
31.5k
    mxPushSlot(receiver);
439
31.5k
    mxRunCount(3);
440
31.5k
    mxPullSlot(slot);
441
31.5k
    mxPushUndefined();
442
31.5k
    if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
443
147
      txSlot* property = the->stack;
444
147
      if (property->flag & XS_DONT_DELETE_FLAG) {
445
112
        if (property->kind == XS_ACCESSOR_KIND) {
446
7
          if ((property->value.accessor.getter == C_NULL) && (slot->kind != XS_UNDEFINED_KIND))
447
3
            mxTypeError("(proxy).get: different getter for non-configurable property");
448
7
        }
449
105
        else {
450
105
          if ((property->flag & XS_DONT_SET_FLAG) && (!fxIsSameValue(the, property, slot, 0)))
451
3
            mxTypeError("(proxy).get: different value for non-configurable, non-writable property");
452
105
        }
453
112
      }
454
147
    }
455
31.5k
    result = 1;
456
31.5k
    mxPop();
457
31.5k
  }
458
141k
  else
459
141k
    result = mxBehaviorGetPropertyValue(the, target->value.reference, id, index, receiver, slot);
460
172k
  mxProxyPop();
461
172k
  return result;
462
172k
}
463
464
txBoolean fxProxyGetPrototype(txMachine* the, txSlot* instance, txSlot* slot)
465
1.00k
{
466
1.00k
  txBoolean result;
467
1.00k
  mxProxyDeclarations(_getPrototypeOf);
468
1.00k
  if (function) {
469
    /* THIS */
470
7
    mxPushSlot(handler);
471
    /* FUNCTION */
472
7
    mxPushSlot(function);
473
7
    mxCall();
474
    /* ARGUMENTS */
475
7
    mxPushSlot(target);
476
7
    mxRunCount(1);
477
7
    mxPullSlot(slot);
478
7
    if ((slot->kind == XS_NULL_KIND) ||  (slot->kind == XS_REFERENCE_KIND)) {
479
5
      if (!mxBehaviorIsExtensible(the, target->value.reference)) {
480
2
        mxPushUndefined();
481
2
        mxBehaviorGetPrototype(the, target->value.reference, the->stack);
482
2
        if (!fxIsSameValue(the, slot, the->stack, 0))
483
1
          mxTypeError("(proxy).getPrototypeOf: different prototype for non-extensible object");
484
1
        mxPop();
485
1
      }
486
5
    }
487
2
    else
488
2
      mxTypeError("(proxy).getPrototypeOf: neither object nor null");
489
4
    result = (slot->kind == XS_NULL_KIND) ? 0 : 1;
490
4
  }
491
995
  else
492
995
    result = mxBehaviorGetPrototype(the, target->value.reference, slot);
493
1.00k
  mxProxyPop();
494
999
  return result;
495
1.00k
}
496
497
txBoolean fxProxyHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
498
223k
{
499
223k
  txBoolean result;
500
223k
  mxProxyDeclarations(_has);
501
223k
  if (function) {
502
    /* THIS */
503
32.0k
    mxPushSlot(handler);
504
    /* FUNCTION */
505
32.0k
    mxPushSlot(function);
506
32.0k
    mxCall();
507
    /* ARGUMENTS */
508
32.0k
    mxPushSlot(target);
509
32.0k
    mxPushUndefined();
510
32.0k
    fxKeyAt(the, id, index, the->stack);
511
32.0k
    mxRunCount(2);
512
32.0k
    result = fxToBoolean(the, the->stack);
513
32.0k
    mxPop();
514
32.0k
    if (!result) {
515
19.2k
      mxPushUndefined();
516
19.2k
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
517
13
        if (the->stack->flag & XS_DONT_DELETE_FLAG)
518
3
          mxTypeError("(proxy).has: false for non-configurable property");
519
10
         if (!mxBehaviorIsExtensible(the, target->value.reference)) 
520
1
          mxTypeError("(proxy).has: false for property of not extensible object");
521
10
      }
522
19.2k
      mxPop();
523
19.2k
    }
524
32.0k
  }
525
191k
  else
526
191k
    result = mxBehaviorHasProperty(the, target->value.reference, id, index);
527
223k
  mxProxyPop();
528
223k
  return result;
529
223k
}
530
531
txBoolean fxProxyIsExtensible(txMachine* the, txSlot* instance)
532
104k
{
533
104k
  txBoolean result;
534
104k
  mxProxyDeclarations(_isExtensible);
535
104k
  if (function) {
536
    /* THIS */
537
20
    mxPushSlot(handler);
538
    /* FUNCTION */
539
20
    mxPushSlot(function);
540
20
    mxCall();
541
    /* ARGUMENTS */
542
20
    mxPushSlot(target);
543
20
    mxRunCount(1);
544
20
    result = fxToBoolean(the, the->stack);
545
20
    mxPop();
546
20
    if (mxBehaviorIsExtensible(the, target->value.reference)) {
547
16
      if (!result)
548
1
        mxTypeError("(proxy).isExtensible: false for extensible object");
549
16
    }
550
4
    else {
551
4
      if (result)
552
2
        mxTypeError("(proxy).isExtensible: true for non-extensible object");
553
4
    }
554
20
  }
555
104k
  else
556
104k
    result = mxBehaviorIsExtensible(the, target->value.reference);
557
104k
  mxProxyPop();
558
104k
  return result;
559
104k
}
560
561
void fxProxyOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* list) 
562
137k
{
563
137k
  mxProxyDeclarations(_ownKeys);
564
137k
  if (function) {
565
51
    txIndex length;
566
51
    txSlot* reference;
567
51
    txSlot* item;
568
51
    txIndex index;
569
51
    txSlot* at;
570
51
    txBoolean test;
571
51
    txSlot* property;
572
    /* THIS */
573
51
    mxPushSlot(handler);
574
    /* FUNCTION */
575
51
    mxPushSlot(function);
576
51
    mxCall();
577
    /* ARGUMENTS */
578
51
    mxPushSlot(target);
579
51
    mxRunCount(1);
580
51
    reference = the->stack;
581
51
    mxPushSlot(reference);
582
51
    mxGetID(mxID(_length));
583
51
    length = fxToInteger(the, the->stack++);
584
51
    item = list;
585
51
    index = 0;
586
156
    while (index < length) {
587
110
      mxPushSlot(reference);
588
110
      mxGetIndex(index);
589
110
      at = the->stack;
590
110
      test = (at->kind == XS_SYMBOL_KIND) ? 1 : 0;
591
110
      if (test || (at->kind == XS_STRING_KIND) || (at->kind == XS_STRING_X_KIND)) {
592
109
        fxAt(the, at);
593
109
        property = list;
594
215
        while ((property = property->next)) {
595
110
          if ((at->value.at.id == property->value.at.id) && (at->value.at.index == property->value.at.index))
596
4
            break;
597
110
        }
598
109
        if (property)
599
4
          mxTypeError("(proxy).ownKeys: duplicate key");
600
105
        item = item->next = fxNewSlot(the);
601
105
        mxPullSlot(item);
602
105
        if (test)
603
12
          item->flag |= XS_INTERNAL_FLAG;
604
105
      }
605
1
      else
606
1
        mxTypeError("(proxy).ownKeys: key is neither string nor symbol");
607
105
      index++;
608
105
    }
609
46
    mxPop();
610
    
611
46
    test = mxBehaviorIsExtensible(the, target->value.reference) ? 1 : 0;
612
46
    at = fxNewInstance(the);
613
46
    mxBehaviorOwnKeys(the, target->value.reference, XS_EACH_NAME_FLAG | XS_EACH_SYMBOL_FLAG, at);
614
46
    mxPushUndefined();
615
46
    property = the->stack;
616
70
    while ((at = at->next)) {
617
32
      mxBehaviorGetOwnProperty(the, target->value.reference, at->value.at.id, at->value.at.index, property);
618
32
      item = list;
619
72
      while ((item = item->next)) {
620
59
        if ((at->value.at.id == item->value.at.id) && (at->value.at.index == item->value.at.index)) {
621
19
          length--;
622
19
          break;
623
19
        }
624
59
      }
625
32
      if (!item) {
626
13
        if (property->flag & XS_DONT_DELETE_FLAG)
627
3
          mxTypeError("(proxy).ownKeys: no key for non-configurable property");
628
10
        if (!test)
629
5
          mxTypeError("(proxy).ownKeys: no key for property of non-extensible object");
630
10
      }
631
32
    }
632
38
    if (!test && length)
633
2
      mxTypeError("(proxy).ownKeys: key for non-existent property of non-extensible object");
634
36
    mxPop();
635
36
    mxPop();
636
    
637
36
    item = list;
638
111
    while ((property = item->next)) {
639
75
      if (property->flag & XS_INTERNAL_FLAG) {
640
8
        property->flag &= ~XS_INTERNAL_FLAG;
641
8
        if (flag & XS_EACH_SYMBOL_FLAG)
642
7
          item = property;
643
1
        else
644
1
          item->next = property->next;
645
8
      }
646
67
      else {
647
67
        if (flag & XS_EACH_NAME_FLAG)
648
59
          item = property;
649
8
        else
650
8
          item->next = property->next;
651
67
      }
652
75
    }
653
36
  }
654
137k
  else
655
137k
    mxBehaviorOwnKeys(the, target->value.reference, flag, list);
656
137k
  mxProxyPop();
657
137k
}
658
659
txBoolean fxProxyPreventExtensions(txMachine* the, txSlot* instance)
660
30
{
661
30
  txBoolean result;
662
30
  mxProxyDeclarations(_preventExtensions);
663
30
  if (function) {
664
    /* THIS */
665
8
    mxPushSlot(handler);
666
    /* FUNCTION */
667
8
    mxPushSlot(function);
668
8
    mxCall();
669
    /* ARGUMENTS */
670
8
    mxPushSlot(target);
671
8
    mxRunCount(1);
672
8
    result = fxToBoolean(the, the->stack);
673
8
    mxPop();
674
8
    if (result) {
675
2
      if (mxBehaviorIsExtensible(the, target->value.reference))
676
1
        mxTypeError("(proxy).preventExtensions: true for extensible object");
677
2
    }
678
8
  }
679
22
  else
680
22
    result = mxBehaviorPreventExtensions(the, target->value.reference);
681
30
  mxProxyPop();
682
29
  return result;
683
30
}
684
685
txSlot* fxProxySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
686
5.24k
{
687
5.24k
  the->scratch.value.at.id = id;
688
5.24k
  the->scratch.value.at.index = index;
689
5.24k
  return &mxProxyAccessor;
690
5.24k
}
691
692
txBoolean fxProxySetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txSlot* receiver)
693
223k
{
694
223k
  txBoolean result;
695
223k
  mxProxyDeclarations(_set);
696
223k
  if (function) {
697
    /* THIS */
698
3.47k
    mxPushSlot(handler);
699
    /* FUNCTION */
700
3.47k
    mxPushSlot(function);
701
3.47k
    mxCall();
702
    /* ARGUMENTS */
703
3.47k
    mxPushSlot(target);
704
3.47k
    mxPushUndefined();
705
3.47k
    fxKeyAt(the, id, index, the->stack);
706
3.47k
    mxPushSlot(slot);
707
3.47k
    mxPushSlot(receiver);
708
3.47k
    mxRunCount(4);
709
3.47k
    result = fxToBoolean(the, the->stack);
710
3.47k
    mxPop();
711
3.47k
    if (result) {
712
31
      mxPushUndefined();
713
31
      if (mxBehaviorGetOwnProperty(the, target->value.reference, id, index, the->stack)) {
714
10
        txSlot* property = the->stack;
715
10
        if (property->flag & XS_DONT_DELETE_FLAG) {
716
9
          if (property->kind == XS_ACCESSOR_KIND) {
717
4
            if (property->value.accessor.setter == C_NULL)
718
3
              mxTypeError("(proxy).set: true for non-configurable property with different setter");
719
4
          }
720
5
          else {
721
5
            if ((property->flag & XS_DONT_SET_FLAG) && (!fxIsSameValue(the, property, slot, 0)))
722
4
              mxTypeError("(proxy).set: true for non-configurable, non-writable property with different value");
723
5
          }
724
9
        }
725
10
      }
726
24
      mxPop();
727
24
    }
728
3.47k
  }
729
220k
  else
730
220k
    result = mxBehaviorSetPropertyValue(the, target->value.reference, id, index, slot, receiver);
731
223k
  mxProxyPop();
732
223k
  return result;
733
223k
}
734
735
txBoolean fxProxySetPrototype(txMachine* the, txSlot* instance, txSlot* prototype)
736
72
{
737
72
  txBoolean result;
738
72
  mxProxyDeclarations(_setPrototypeOf);
739
72
  if (function) {
740
    /* THIS */
741
37
    mxPushSlot(handler);
742
    /* FUNCTION */
743
37
    mxPushSlot(function);
744
37
    mxCall();
745
    /* ARGUMENTS */
746
37
    mxPushSlot(target);
747
37
    mxPushSlot(prototype);
748
37
    mxRunCount(2);
749
37
    result = fxToBoolean(the, the->stack);
750
37
    mxPop();
751
37
    if (result) {
752
24
      if (!mxBehaviorIsExtensible(the, target->value.reference)) {
753
6
        mxPushUndefined();
754
6
        mxBehaviorGetPrototype(the, target->value.reference, the->stack);
755
6
        if (!fxIsSameValue(the, prototype, the->stack, 0))
756
3
          mxTypeError("(proxy).setPrototypeOf: true for non-extensible object with different prototype");
757
3
        mxPop();
758
3
      }
759
24
    }
760
37
  }
761
35
  else
762
35
    result = mxBehaviorSetPrototype(the, target->value.reference, prototype);
763
72
  mxProxyPop();
764
69
  return result;
765
72
}
766
767
void fx_Proxy(txMachine* the)
768
1.42M
{
769
1.42M
  txSlot* instance;
770
1.42M
  txSlot* proxy;
771
1.42M
  txSlot* target;
772
1.42M
  txSlot* handler;
773
1.42M
  if (!mxHasTarget)
774
1
    mxTypeError("call: Proxy");
775
1.42M
  mxPushUndefined();
776
1.42M
  instance = fxNewProxyInstance(the);
777
1.42M
  mxPullSlot(mxResult);
778
1.42M
  proxy = instance->next;
779
1.42M
  if (!proxy || (proxy->kind != XS_PROXY_KIND))
780
0
    mxTypeError("this: not a Proxy instance");
781
#if mxHostFunctionPrimitive
782
  if ((mxArgc > 0) && (mxArgv(0)->kind == XS_HOST_FUNCTION_KIND))
783
    fxToInstance(the, mxArgv(0));
784
  if ((mxArgc > 1) && (mxArgv(1)->kind == XS_HOST_FUNCTION_KIND))
785
    fxToInstance(the, mxArgv(1));
786
#endif
787
1.42M
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
788
5
    mxTypeError("target: not an object");
789
1.42M
  target = mxArgv(0)->value.reference;
790
1.42M
  if ((mxArgc < 2) || (mxArgv(1)->kind != XS_REFERENCE_KIND))
791
21
    mxTypeError("handler: not an object");
792
1.42M
  handler = mxArgv(1)->value.reference;
793
1.42M
  instance->flag |= target->flag & (XS_CAN_CALL_FLAG | XS_CAN_CONSTRUCT_FLAG);
794
1.42M
  proxy->value.proxy.target = target;
795
1.42M
  proxy->value.proxy.handler = handler;
796
1.42M
}
797
798
void fx_Proxy_revocable(txMachine* the)
799
10.2k
{
800
10.2k
  txSlot* target;
801
10.2k
  txSlot* handler;
802
10.2k
  txSlot* property;
803
10.2k
  txSlot* instance;
804
10.2k
  txSlot* slot;
805
  
806
#if mxHostFunctionPrimitive
807
  if ((mxArgc > 0) && (mxArgv(0)->kind == XS_HOST_FUNCTION_KIND))
808
    fxToInstance(the, mxArgv(0));
809
  if ((mxArgc > 1) && (mxArgv(1)->kind == XS_HOST_FUNCTION_KIND))
810
    fxToInstance(the, mxArgv(1));
811
#endif
812
10.2k
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
813
1
    mxTypeError("target: not an object");
814
10.2k
  target = mxArgv(0)->value.reference;
815
10.2k
  if ((mxArgc < 2) || (mxArgv(1)->kind != XS_REFERENCE_KIND))
816
15
    mxTypeError("handler: not an object");
817
10.2k
  handler = mxArgv(1)->value.reference;
818
    
819
10.2k
  mxPush(mxObjectPrototype);
820
10.2k
  property = fxLastProperty(the, fxNewObjectInstance(the));
821
10.2k
  mxPullSlot(mxResult);
822
  
823
10.2k
  mxPushUndefined();
824
10.2k
  instance = fxNewProxyInstance(the);
825
10.2k
  instance->flag |= target->flag & (XS_CAN_CALL_FLAG | XS_CAN_CONSTRUCT_FLAG);
826
10.2k
  slot = instance->next;
827
10.2k
  slot->value.proxy.target = target;
828
10.2k
  slot->value.proxy.handler = handler;
829
10.2k
  property = fxNextSlotProperty(the, property, the->stack, mxID(_proxy), XS_GET_ONLY);
830
  
831
10.2k
  slot = fxLastProperty(the, fxNewHostFunction(the, mxCallback(fx_Proxy_revoke), 0, XS_NO_ID, XS_NO_ID));
832
10.2k
  slot = fxNextSlotProperty(the, slot, the->stack + 1, mxID(_proxy), XS_GET_ONLY);
833
10.2k
  property = fxNextSlotProperty(the, property, the->stack, mxID(_revoke), XS_GET_ONLY);
834
  
835
10.2k
  the->stack += 2;
836
10.2k
}
837
838
void fx_Proxy_revoke(txMachine* the)
839
31
{
840
31
  txSlot* property = mxBehaviorGetProperty(the, mxFunction->value.reference, mxID(_proxy), 0, XS_ANY);
841
31
  if (property && (property->kind == XS_REFERENCE_KIND)) {
842
28
    txSlot* instance = property->value.reference;
843
28
    txSlot* proxy = instance->next;
844
28
    if (!proxy || (proxy->kind != XS_PROXY_KIND))
845
0
      mxTypeError("(proxy).revoke: not a Proxy instance");
846
28
    if (proxy->flag & XS_MARK_FLAG)
847
0
      mxTypeError("(proxy).revoke: read-only Proxy instance");
848
28
    proxy->value.proxy.target = C_NULL;
849
28
    proxy->value.proxy.handler = C_NULL;
850
28
    property->kind = XS_NULL_KIND;
851
28
  }
852
31
}
853
854
void fx_Reflect_apply(txMachine* the)
855
68.0k
{
856
68.0k
  if ((mxArgc < 1) || !(fxIsCallable(the, mxArgv(0))))
857
10
    mxTypeError("target: not a function");
858
68.0k
  if ((mxArgc < 3) || (mxArgv(2)->kind != XS_REFERENCE_KIND))
859
2
    mxTypeError("argumentsList: not an object");
860
68.0k
  mxBehaviorCall(the, fxToInstance(the, mxArgv(0)), mxArgv(1), mxArgv(2));
861
68.0k
}
862
863
void fx_Reflect_construct(txMachine* the)
864
166
{
865
166
    txSlot* target;
866
166
  if ((mxArgc < 1) || !mxIsReference(mxArgv(0)) || !mxIsConstructor(mxArgv(0)->value.reference))
867
7
    mxTypeError("target: not a constructor");
868
159
  if ((mxArgc < 2) || (mxArgv(1)->kind != XS_REFERENCE_KIND))
869
2
    mxTypeError("argumentsList: not an object");
870
157
  if (mxArgc < 3)
871
21
    target = mxArgv(0);
872
136
  else if (!mxIsReference(mxArgv(2)) || !mxIsConstructor(mxArgv(2)->value.reference))
873
9
    mxTypeError("newTarget: not a constructor");
874
127
  else
875
127
    target = mxArgv(2);
876
148
  mxBehaviorConstruct(the, fxToInstance(the, mxArgv(0)), mxArgv(1), target);
877
148
}
878
879
void fx_Reflect_defineProperty(txMachine* the)
880
65
{
881
65
  txSlot* at;
882
65
  txFlag mask;
883
65
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
884
10
    mxTypeError("target: not an object");
885
55
  if (mxArgc < 2)
886
0
    mxTypeError("no key");
887
55
  at = fxAt(the, mxArgv(1));
888
55
  if ((mxArgc < 3) || (mxArgv(2)->kind != XS_REFERENCE_KIND))
889
5
    mxTypeError("invalid descriptor");
890
50
  mask = fxDescriptorToSlot(the, mxArgv(2));
891
50
  mxResult->value.boolean = mxBehaviorDefineOwnProperty(the, mxArgv(0)->value.reference, at->value.at.id, at->value.at.index, mxArgv(2), mask);
892
50
  mxResult->kind = XS_BOOLEAN_KIND;
893
50
}
894
895
void fx_Reflect_deleteProperty(txMachine* the)
896
53
{
897
53
  txSlot* at;
898
53
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
899
10
    mxTypeError("target: not an object");
900
43
  if (mxArgc < 2)
901
1
    mxTypeError("no key");
902
42
  at = fxAt(the, mxArgv(1));
903
42
  mxResult->value.boolean = mxBehaviorDeleteProperty(the, mxArgv(0)->value.reference, at->value.at.id, at->value.at.index);
904
42
  mxResult->kind = XS_BOOLEAN_KIND;
905
42
}
906
907
void fx_Reflect_get(txMachine* the)
908
10.4k
{
909
10.4k
  txSlot* at;
910
10.4k
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
911
10
    mxTypeError("target: not an object");
912
10.3k
  if (mxArgc < 2)
913
1
    mxTypeError("no key");
914
10.3k
  at = fxAt(the, mxArgv(1));
915
10.3k
  mxBehaviorGetPropertyValue(the,   mxArgv(0)->value.reference, at->value.at.id, at->value.at.index, mxArgc < 3 ? mxArgv(0) : mxArgv(2), mxResult);
916
10.3k
}
917
918
void fx_Reflect_getOwnPropertyDescriptor(txMachine* the)
919
2.59k
{
920
2.59k
  txSlot* at;
921
2.59k
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
922
10
    mxTypeError("target: not an object");
923
2.58k
  if (mxArgc < 2)
924
0
    mxTypeError("no key");
925
2.58k
  at = fxAt(the, mxArgv(1));
926
2.58k
  mxPushUndefined();
927
2.58k
  if (mxBehaviorGetOwnProperty(the, mxArgv(0)->value.reference, at->value.at.id, at->value.at.index, the->stack)) {
928
50
    fxDescribeProperty(the, the->stack, XS_GET_ONLY);
929
50
    mxPullSlot(mxResult);
930
50
  }
931
2.58k
  mxPop();
932
2.58k
}
933
934
void fx_Reflect_getPrototypeOf(txMachine* the)
935
20
{
936
20
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
937
10
    mxTypeError("target: not an object");
938
10
  mxBehaviorGetPrototype(the, mxArgv(0)->value.reference, mxResult);
939
10
}
940
941
void fx_Reflect_has(txMachine* the)
942
21.2k
{
943
21.2k
  txSlot* at;
944
21.2k
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
945
7
    mxTypeError("target: not an object");
946
21.2k
  if (mxArgc < 2)
947
0
    mxTypeError("no key");
948
21.2k
  at = fxAt(the, mxArgv(1));
949
21.2k
  mxResult->value.boolean = mxBehaviorHasProperty(the, mxArgv(0)->value.reference, at->value.at.id, at->value.at.index);
950
21.2k
  mxResult->kind = XS_BOOLEAN_KIND;
951
21.2k
}
952
953
void fx_Reflect_isExtensible(txMachine* the)
954
22
{
955
22
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
956
9
    mxTypeError("target: not an object");
957
13
  mxResult->value.boolean = mxBehaviorIsExtensible(the, mxArgv(0)->value.reference);
958
13
  mxResult->kind = XS_BOOLEAN_KIND;
959
13
}
960
961
void fx_Reflect_ownKeys(txMachine* the)
962
35
{
963
35
  txSlot* result;
964
35
  txSlot* array;
965
35
  txSlot* item;
966
35
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
967
10
    mxTypeError("target: not an object");
968
25
  mxPush(mxArrayPrototype);
969
25
  result = fxNewArrayInstance(the);
970
25
  mxPullSlot(mxResult);
971
25
  array = result->next;
972
25
  mxBehaviorOwnKeys(the, mxArgv(0)->value.reference, XS_EACH_NAME_FLAG | XS_EACH_SYMBOL_FLAG, array);
973
25
  item = array;
974
109
  while ((item = item->next)) {
975
84
    array->value.array.length++;
976
84
    fxKeyAt(the, item->value.at.id, item->value.at.index, item);
977
84
  }
978
25
  fxCacheArray(the, result);
979
25
}
980
981
void fx_Reflect_preventExtensions(txMachine* the)
982
26
{
983
26
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
984
10
    mxTypeError("target: not an object");
985
16
  mxResult->value.boolean = mxBehaviorPreventExtensions(the, mxArgv(0)->value.reference);
986
16
  mxResult->kind = XS_BOOLEAN_KIND;
987
16
}
988
989
void fx_Reflect_set(txMachine* the)
990
57
{
991
57
  txSlot* at;
992
57
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
993
9
    mxTypeError("target: not an object");
994
48
  if (mxArgc < 2)
995
0
    mxTypeError("no key");
996
48
  at = fxAt(the, mxArgv(1));
997
48
  if (mxArgc < 3)
998
1
    mxPushUndefined();
999
47
  else
1000
47
    mxPushSlot(mxArgv(2));
1001
48
  mxResult->value.boolean = mxBehaviorSetPropertyValue(the, mxArgv(0)->value.reference, at->value.at.id, at->value.at.index, the->stack, mxArgc < 4 ? mxArgv(0) : mxArgv(3));
1002
48
  mxResult->kind = XS_BOOLEAN_KIND;
1003
48
  mxPop();
1004
48
}
1005
1006
void fx_Reflect_setPrototypeOf(txMachine* the)
1007
96
{
1008
96
  if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND))
1009
10
    mxTypeError("target: not an object");
1010
86
  if ((mxArgc < 2) || ((mxArgv(1)->kind != XS_NULL_KIND) && (mxArgv(1)->kind != XS_REFERENCE_KIND)))
1011
10
    mxTypeError("invalid prototype");
1012
76
  mxResult->value.boolean = mxBehaviorSetPrototype(the, mxArgv(0)->value.reference, mxArgv(1));
1013
76
  mxResult->kind = XS_BOOLEAN_KIND;
1014
76
}