Coverage Report

Created: 2025-12-11 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hermes/lib/VM/JSLib/Object.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
//===----------------------------------------------------------------------===//
9
/// \file
10
/// ES5.1 15.2 Initialize the Object constructor.
11
//===----------------------------------------------------------------------===//
12
#include "Object.h"
13
#include "JSLibInternal.h"
14
15
#include "hermes/VM/HermesValueTraits.h"
16
#include "hermes/VM/Operations.h"
17
#include "hermes/VM/PrimitiveBox.h"
18
#include "hermes/VM/PropertyAccessor.h"
19
#include "hermes/VM/StringBuilder.h"
20
21
namespace hermes {
22
namespace vm {
23
24
//===----------------------------------------------------------------------===//
25
/// Object.
26
27
94
Handle<JSObject> createObjectConstructor(Runtime &runtime) {
28
94
  auto objectPrototype = Handle<JSObject>::vmcast(&runtime.objectPrototype);
29
30
94
  auto cons = defineSystemConstructor<JSObject>(
31
94
      runtime,
32
94
      Predefined::getSymbolID(Predefined::Object),
33
94
      objectConstructor,
34
94
      Handle<JSObject>::vmcast(&runtime.objectPrototype),
35
94
      1,
36
94
      CellKind::JSObjectKind);
37
94
  void *ctx = nullptr;
38
39
  // Object.prototype.xxx methods.
40
94
  defineMethod(
41
94
      runtime,
42
94
      objectPrototype,
43
94
      Predefined::getSymbolID(Predefined::toString),
44
94
      ctx,
45
94
      objectPrototypeToString,
46
94
      0);
47
94
  defineMethod(
48
94
      runtime,
49
94
      objectPrototype,
50
94
      Predefined::getSymbolID(Predefined::toLocaleString),
51
94
      ctx,
52
94
      objectPrototypeToLocaleString,
53
94
      0);
54
94
  defineMethod(
55
94
      runtime,
56
94
      objectPrototype,
57
94
      Predefined::getSymbolID(Predefined::valueOf),
58
94
      ctx,
59
94
      objectPrototypeValueOf,
60
94
      0);
61
94
  defineMethod(
62
94
      runtime,
63
94
      objectPrototype,
64
94
      Predefined::getSymbolID(Predefined::hasOwnProperty),
65
94
      ctx,
66
94
      objectPrototypeHasOwnProperty,
67
94
      1);
68
94
  defineMethod(
69
94
      runtime,
70
94
      objectPrototype,
71
94
      Predefined::getSymbolID(Predefined::isPrototypeOf),
72
94
      ctx,
73
94
      objectPrototypeIsPrototypeOf,
74
94
      1);
75
94
  defineMethod(
76
94
      runtime,
77
94
      objectPrototype,
78
94
      Predefined::getSymbolID(Predefined::propertyIsEnumerable),
79
94
      ctx,
80
94
      objectPrototypePropertyIsEnumerable,
81
94
      1);
82
94
  defineAccessor(
83
94
      runtime,
84
94
      objectPrototype,
85
94
      Predefined::getSymbolID(Predefined::underscore_proto),
86
94
      ctx,
87
94
      objectPrototypeProto_getter,
88
94
      objectPrototypeProto_setter,
89
94
      false,
90
94
      true);
91
94
  defineMethod(
92
94
      runtime,
93
94
      objectPrototype,
94
94
      Predefined::getSymbolID(Predefined::__defineGetter__),
95
94
      ctx,
96
94
      objectPrototypeDefineGetter,
97
94
      2);
98
94
  defineMethod(
99
94
      runtime,
100
94
      objectPrototype,
101
94
      Predefined::getSymbolID(Predefined::__defineSetter__),
102
94
      ctx,
103
94
      objectPrototypeDefineSetter,
104
94
      2);
105
94
  defineMethod(
106
94
      runtime,
107
94
      objectPrototype,
108
94
      Predefined::getSymbolID(Predefined::__lookupGetter__),
109
94
      ctx,
110
94
      objectPrototypeLookupGetter,
111
94
      1);
112
94
  defineMethod(
113
94
      runtime,
114
94
      objectPrototype,
115
94
      Predefined::getSymbolID(Predefined::__lookupSetter__),
116
94
      ctx,
117
94
      objectPrototypeLookupSetter,
118
94
      1);
119
120
  // Object.xxx() methods.
121
94
  defineMethod(
122
94
      runtime,
123
94
      cons,
124
94
      Predefined::getSymbolID(Predefined::getPrototypeOf),
125
94
      ctx,
126
94
      objectGetPrototypeOf,
127
94
      1);
128
94
  defineMethod(
129
94
      runtime,
130
94
      cons,
131
94
      Predefined::getSymbolID(Predefined::getOwnPropertyDescriptor),
132
94
      ctx,
133
94
      objectGetOwnPropertyDescriptor,
134
94
      2);
135
94
  defineMethod(
136
94
      runtime,
137
94
      cons,
138
94
      Predefined::getSymbolID(Predefined::getOwnPropertyDescriptors),
139
94
      ctx,
140
94
      objectGetOwnPropertyDescriptors,
141
94
      1);
142
94
  defineMethod(
143
94
      runtime,
144
94
      cons,
145
94
      Predefined::getSymbolID(Predefined::getOwnPropertyNames),
146
94
      ctx,
147
94
      objectGetOwnPropertyNames,
148
94
      1);
149
94
  defineMethod(
150
94
      runtime,
151
94
      cons,
152
94
      Predefined::getSymbolID(Predefined::getOwnPropertySymbols),
153
94
      ctx,
154
94
      objectGetOwnPropertySymbols,
155
94
      1);
156
94
  defineMethod(
157
94
      runtime,
158
94
      cons,
159
94
      Predefined::getSymbolID(Predefined::hasOwn),
160
94
      ctx,
161
94
      objectHasOwn,
162
94
      2);
163
94
  defineMethod(
164
94
      runtime,
165
94
      cons,
166
94
      Predefined::getSymbolID(Predefined::seal),
167
94
      ctx,
168
94
      objectSeal,
169
94
      1);
170
94
  defineMethod(
171
94
      runtime,
172
94
      cons,
173
94
      Predefined::getSymbolID(Predefined::freeze),
174
94
      ctx,
175
94
      objectFreeze,
176
94
      1);
177
94
  defineMethod(
178
94
      runtime,
179
94
      cons,
180
94
      Predefined::getSymbolID(Predefined::fromEntries),
181
94
      ctx,
182
94
      objectFromEntries,
183
94
      1);
184
94
  defineMethod(
185
94
      runtime,
186
94
      cons,
187
94
      Predefined::getSymbolID(Predefined::preventExtensions),
188
94
      ctx,
189
94
      objectPreventExtensions,
190
94
      1);
191
192
94
  defineMethod(
193
94
      runtime, cons, Predefined::getSymbolID(Predefined::is), ctx, objectIs, 2);
194
94
  defineMethod(
195
94
      runtime,
196
94
      cons,
197
94
      Predefined::getSymbolID(Predefined::isSealed),
198
94
      ctx,
199
94
      objectIsSealed,
200
94
      1);
201
94
  defineMethod(
202
94
      runtime,
203
94
      cons,
204
94
      Predefined::getSymbolID(Predefined::isFrozen),
205
94
      ctx,
206
94
      objectIsFrozen,
207
94
      1);
208
94
  defineMethod(
209
94
      runtime,
210
94
      cons,
211
94
      Predefined::getSymbolID(Predefined::isExtensible),
212
94
      ctx,
213
94
      objectIsExtensible,
214
94
      1);
215
94
  defineMethod(
216
94
      runtime,
217
94
      cons,
218
94
      Predefined::getSymbolID(Predefined::keys),
219
94
      ctx,
220
94
      objectKeys,
221
94
      1);
222
94
  defineMethod(
223
94
      runtime,
224
94
      cons,
225
94
      Predefined::getSymbolID(Predefined::values),
226
94
      ctx,
227
94
      objectValues,
228
94
      1);
229
94
  defineMethod(
230
94
      runtime,
231
94
      cons,
232
94
      Predefined::getSymbolID(Predefined::entries),
233
94
      ctx,
234
94
      objectEntries,
235
94
      1);
236
94
  defineMethod(
237
94
      runtime,
238
94
      cons,
239
94
      Predefined::getSymbolID(Predefined::create),
240
94
      ctx,
241
94
      objectCreate,
242
94
      2);
243
94
  defineMethod(
244
94
      runtime,
245
94
      cons,
246
94
      Predefined::getSymbolID(Predefined::defineProperty),
247
94
      ctx,
248
94
      objectDefineProperty,
249
94
      3);
250
94
  defineMethod(
251
94
      runtime,
252
94
      cons,
253
94
      Predefined::getSymbolID(Predefined::defineProperties),
254
94
      ctx,
255
94
      objectDefineProperties,
256
94
      2);
257
94
  defineMethod(
258
94
      runtime,
259
94
      cons,
260
94
      Predefined::getSymbolID(Predefined::assign),
261
94
      ctx,
262
94
      objectAssign,
263
94
      2);
264
94
  defineMethod(
265
94
      runtime,
266
94
      cons,
267
94
      Predefined::getSymbolID(Predefined::setPrototypeOf),
268
94
      ctx,
269
94
      objectSetPrototypeOf,
270
94
      2);
271
272
94
  return cons;
273
94
}
274
275
/// ES2024 20.1.1.1 Object() invoked as a function and as a
276
/// constructor.
277
CallResult<HermesValue>
278
0
objectConstructor(void *, Runtime &runtime, NativeArgs args) {
279
0
  auto &newTarget = args.getNewTarget();
280
  // 1. If NewTarget is neither undefined nor the active function object, then
281
0
  if (!newTarget.isUndefined() &&
282
0
      newTarget.getRaw() != runtime.objectConstructor.getRaw()) {
283
    // a. Return ? OrdinaryCreateFromConstructor(NewTarget,
284
    // "%Object.prototype%").
285
    // This is a construct call, which means the object we want to create was
286
    // actually already created for us in the caller and passed as `this`, so we
287
    // can just use that.
288
0
    assert(
289
0
        args.getThisArg().isObject() &&
290
0
        "'this' must be an object in a constructor call");
291
0
    return args.getThisArg();
292
0
  }
293
294
0
  auto value = args.getArgHandle(0);
295
  // 2. If value is either undefined or null, return
296
  // OrdinaryObjectCreate(%Object.prototype%).
297
0
  if (value->isUndefined() || value->isNull()) {
298
    // If this is a construct call directly on Object, then
299
    // OrdinaryObjectCreate(%Object.prototype%) is the value of `this`.
300
0
    if (newTarget.getRaw() == runtime.objectConstructor.getRaw()) {
301
0
      return args.getThisArg();
302
0
    }
303
0
    return JSObject::create(runtime).getHermesValue();
304
0
  }
305
306
  // 3. Return ! ToObject(value).
307
0
  return toObject(runtime, value);
308
0
}
309
310
0
CallResult<HermesValue> getPrototypeOf(Runtime &runtime, Handle<JSObject> obj) {
311
0
  CallResult<PseudoHandle<JSObject>> protoRes =
312
0
      JSObject::getPrototypeOf(obj, runtime);
313
0
  if (LLVM_UNLIKELY(protoRes == ExecutionStatus::EXCEPTION)) {
314
0
    return ExecutionStatus::EXCEPTION;
315
0
  }
316
  // Note that we must return 'null' if there is no prototype.
317
0
  if (!*protoRes) {
318
0
    return HermesValue::encodeNullValue();
319
0
  }
320
0
  return protoRes->getHermesValue();
321
0
}
322
323
CallResult<HermesValue>
324
0
objectGetPrototypeOf(void *, Runtime &runtime, NativeArgs args) {
325
0
  CallResult<HermesValue> res = toObject(runtime, args.getArgHandle(0));
326
0
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
327
0
    return ExecutionStatus::EXCEPTION;
328
0
  }
329
330
0
  return getPrototypeOf(runtime, runtime.makeHandle(vmcast<JSObject>(*res)));
331
0
}
332
333
CallResult<HermesValue> getOwnPropertyDescriptor(
334
    Runtime &runtime,
335
    Handle<JSObject> object,
336
0
    Handle<> key) {
337
0
  ComputedPropertyDescriptor desc;
338
0
  MutableHandle<> valueOrAccessor{runtime};
339
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
340
0
  {
341
0
    auto result = JSObject::getOwnComputedDescriptor(
342
0
        object, runtime, key, tmpPropNameStorage, desc, valueOrAccessor);
343
0
    if (result == ExecutionStatus::EXCEPTION) {
344
0
      return ExecutionStatus::EXCEPTION;
345
0
    }
346
0
    if (!*result) {
347
0
      if (LLVM_LIKELY(!object->isHostObject()))
348
0
        return HermesValue::encodeUndefinedValue();
349
      // For compatibility with polyfills we want to pretend that all HostObject
350
      // properties are "own" properties in hasOwnProperty() and in
351
      // getOwnPropertyDescriptor(). Since there is no way to check for a
352
      // HostObject property, we must always assume the property exists.
353
0
      desc.flags.enumerable = true;
354
0
      desc.flags.writable = true;
355
0
      desc.flags.hostObject = true;
356
0
    }
357
0
  }
358
359
0
  if (LLVM_UNLIKELY(!desc.flags.accessor && desc.flags.hostObject)) {
360
0
    auto propRes = JSObject::getComputed_RJS(object, runtime, key);
361
0
    if (propRes == ExecutionStatus::EXCEPTION) {
362
0
      return ExecutionStatus::EXCEPTION;
363
0
    }
364
0
    valueOrAccessor = std::move(*propRes);
365
0
  }
366
367
0
  DefinePropertyFlags dpFlags;
368
0
  dpFlags.configurable = desc.flags.configurable;
369
0
  dpFlags.enumerable = desc.flags.enumerable;
370
0
  dpFlags.writable = desc.flags.writable;
371
0
  dpFlags.setEnumerable = true;
372
0
  dpFlags.setWritable = true;
373
0
  dpFlags.setConfigurable = true;
374
0
  dpFlags.setGetter = desc.flags.accessor;
375
0
  dpFlags.setSetter = desc.flags.accessor;
376
0
  dpFlags.setValue = !desc.flags.accessor;
377
378
0
  return objectFromPropertyDescriptor(runtime, dpFlags, valueOrAccessor);
379
0
}
380
381
CallResult<HermesValue>
382
0
objectGetOwnPropertyDescriptor(void *, Runtime &runtime, NativeArgs args) {
383
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
384
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
385
0
    return ExecutionStatus::EXCEPTION;
386
0
  }
387
0
  Handle<JSObject> O = runtime.makeHandle<JSObject>(objRes.getValue());
388
389
0
  return getOwnPropertyDescriptor(runtime, O, args.getArgHandle(1));
390
0
}
391
392
/// ES10.0 19.1.2.9
393
CallResult<HermesValue>
394
0
objectGetOwnPropertyDescriptors(void *, Runtime &runtime, NativeArgs args) {
395
0
  GCScope gcScope{runtime};
396
397
  // 1. Let obj be ? ToObject(O).
398
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
399
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
400
0
    return ExecutionStatus::EXCEPTION;
401
0
  }
402
0
  Handle<JSObject> obj = runtime.makeHandle<JSObject>(objRes.getValue());
403
404
  // 2. Let ownKeys be ? obj.[[OwnPropertyKeys]]().
405
0
  auto ownKeysRes = JSObject::getOwnPropertyKeys(
406
0
      obj,
407
0
      runtime,
408
0
      OwnKeysFlags()
409
0
          .plusIncludeNonSymbols()
410
0
          .plusIncludeSymbols()
411
0
          .plusIncludeNonEnumerable());
412
0
  if (LLVM_UNLIKELY(ownKeysRes == ExecutionStatus::EXCEPTION)) {
413
0
    return ExecutionStatus::EXCEPTION;
414
0
  }
415
0
  Handle<JSArray> ownKeys = *ownKeysRes;
416
0
  uint32_t len = JSArray::getLength(*ownKeys, runtime);
417
418
  // 3. Let descriptors be ! ObjectCreate(%ObjectPrototype%).
419
0
  auto descriptors = runtime.makeHandle<JSObject>(JSObject::create(runtime));
420
421
0
  MutableHandle<> key{runtime};
422
0
  MutableHandle<> descriptor{runtime};
423
424
0
  DefinePropertyFlags dpf = DefinePropertyFlags::getDefaultNewPropertyFlags();
425
426
0
  auto marker = gcScope.createMarker();
427
  // 4. For each element key of ownKeys in List order, do
428
0
  for (uint32_t i = 0; i < len; ++i) {
429
0
    gcScope.flushToMarker(marker);
430
0
    key = ownKeys->at(runtime, i).unboxToHV(runtime);
431
    // a. Let desc be ? obj.[[GetOwnProperty]](key).
432
    // b. Let descriptor be ! FromPropertyDescriptor(desc).
433
0
    auto descriptorRes = getOwnPropertyDescriptor(runtime, obj, key);
434
0
    if (LLVM_UNLIKELY(descriptorRes == ExecutionStatus::EXCEPTION)) {
435
0
      return ExecutionStatus::EXCEPTION;
436
0
    }
437
    // c. If descriptor is not undefined,
438
    //    perform !CreateDataProperty(descriptors, key, descriptor).
439
0
    if (!descriptorRes->isUndefined()) {
440
0
      descriptor = *descriptorRes;
441
0
      auto res = JSObject::defineOwnComputedPrimitive(
442
0
          descriptors, runtime, key, dpf, descriptor);
443
0
      (void)res;
444
0
      assert(
445
0
          res != ExecutionStatus::EXCEPTION &&
446
0
          "defining own property on a new object cannot fail");
447
0
    }
448
0
  }
449
  // 5. Return descriptors.
450
0
  return descriptors.getHermesValue();
451
0
}
452
453
/// Return a list of property names belonging to this object. All
454
/// properties are converted into strings. The order of
455
/// properties will remain the same as Object::getOwnPropertyNames.
456
/// \returns a JSArray containing the names, encoded in HermesValue.
457
CallResult<HermesValue> getOwnPropertyKeysAsStrings(
458
    Handle<JSObject> selfHandle,
459
    Runtime &runtime,
460
0
    OwnKeysFlags okFlags) {
461
0
  auto cr = JSObject::getOwnPropertyKeys(selfHandle, runtime, okFlags);
462
0
  if (cr == ExecutionStatus::EXCEPTION) {
463
0
    return ExecutionStatus::EXCEPTION;
464
0
  }
465
0
  auto array = *cr;
466
0
  MutableHandle<> prop(runtime);
467
0
  GCScope gcScope(runtime);
468
0
  auto marker = gcScope.createMarker();
469
0
  for (unsigned i = 0, e = array->getEndIndex(); i < e; ++i) {
470
0
    gcScope.flushToMarker(marker);
471
0
    prop = array->at(runtime, i).unboxToHV(runtime);
472
0
    if (prop->isString() || prop->isSymbol()) {
473
      // Nothing to do if it's already a string or symbol.
474
0
      continue;
475
0
    }
476
0
    assert(prop->isNumber() && "Property name is either string or number");
477
    // Otherwise convert it to a string and replace the element.
478
0
    auto status = toString_RJS(runtime, prop);
479
0
    assert(
480
0
        status != ExecutionStatus::EXCEPTION &&
481
0
        "toString() on property name cannot fail");
482
0
    JSArray::setElementAt(
483
0
        array, runtime, i, runtime.makeHandle(std::move(*status)));
484
0
  }
485
0
  return array.getHermesValue();
486
0
}
487
488
CallResult<HermesValue>
489
0
objectGetOwnPropertyNames(void *, Runtime &runtime, NativeArgs args) {
490
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
491
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
492
0
    return ExecutionStatus::EXCEPTION;
493
0
  }
494
0
  auto objHandle = runtime.makeHandle<JSObject>(objRes.getValue());
495
0
  auto cr = getOwnPropertyKeysAsStrings(
496
0
      objHandle,
497
0
      runtime,
498
0
      OwnKeysFlags().plusIncludeNonSymbols().plusIncludeNonEnumerable());
499
0
  if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) {
500
0
    return ExecutionStatus::EXCEPTION;
501
0
  }
502
0
  return *cr;
503
0
}
504
505
CallResult<HermesValue>
506
0
objectGetOwnPropertySymbols(void *, Runtime &runtime, NativeArgs args) {
507
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
508
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
509
0
    return ExecutionStatus::EXCEPTION;
510
0
  }
511
0
  auto objHandle = runtime.makeHandle<JSObject>(objRes.getValue());
512
0
  auto cr = JSObject::getOwnPropertySymbols(objHandle, runtime);
513
0
  if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) {
514
0
    return ExecutionStatus::EXCEPTION;
515
0
  }
516
0
  return cr->getHermesValue();
517
0
}
518
519
CallResult<bool>
520
0
defineProperty(Runtime &runtime, NativeArgs args, PropOpFlags opFlags) {
521
  // ES9 19.1.2.4 (throwOnError == true) or 26.1.3 (throwOnError == false)
522
0
  auto O = args.dyncastArg<JSObject>(0);
523
  // 1. If Type(O) is not Object, throw a TypeError exception.
524
0
  if (!O) {
525
0
    return runtime.raiseTypeError(
526
0
        "Object.defineProperty() called on non-object");
527
0
  }
528
529
  // 2. Let key be ? ToPropertyKey(P).
530
  // Convert the property name to string if it's an object.  This is
531
  // done explicitly instead of calling defineOwnComputed so that
532
  // converting the key argument to a primitive happens before
533
  // toPropertyDescriptor (which can fail, so the order is
534
  // observable).
535
0
  CallResult<Handle<>> keyRes =
536
0
      toPropertyKeyIfObject(runtime, args.getArgHandle(1));
537
0
  if (LLVM_UNLIKELY(keyRes == ExecutionStatus::EXCEPTION))
538
0
    return ExecutionStatus::EXCEPTION;
539
540
  // 3. Let desc be ? ToPropertyDescriptor(Attributes).
541
0
  DefinePropertyFlags descFlags;
542
0
  MutableHandle<> descValueOrAccessor{runtime};
543
0
  if (toPropertyDescriptor(
544
0
          args.getArgHandle(2), runtime, descFlags, descValueOrAccessor) ==
545
0
      ExecutionStatus::EXCEPTION) {
546
0
    return ExecutionStatus::EXCEPTION;
547
0
  }
548
549
  // 4[throwOnError]. Perform ? DefinePropertyOrThrow(O, key, desc).
550
  // 4[!throwOnError]. Return ? O.[[DefineOwnProperty]](key, desc).
551
0
  return JSObject::defineOwnComputedPrimitive(
552
0
      O, runtime, *keyRes, descFlags, descValueOrAccessor, opFlags);
553
0
}
554
555
CallResult<HermesValue>
556
0
objectDefineProperty(void *, Runtime &runtime, NativeArgs args) {
557
  // ES9 19.1.2.4
558
0
  CallResult<bool> res =
559
0
      defineProperty(runtime, args, PropOpFlags().plusThrowOnError());
560
0
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
561
0
    return ExecutionStatus::EXCEPTION;
562
0
  }
563
0
  assert(*res && "defineProperty with throwOnError == true returned false");
564
  // 5. Return O.
565
0
  return args.getArg(0);
566
0
}
567
568
static CallResult<HermesValue>
569
0
objectDefinePropertiesInternal(Runtime &runtime, Handle<> obj, Handle<> props) {
570
  // Verify this method is called on an object.
571
0
  auto *objPtr = dyn_vmcast<JSObject>(obj.get());
572
0
  if (!objPtr) {
573
0
    return runtime.raiseTypeError(
574
0
        "Object.defineProperties() called on non-object");
575
0
  }
576
0
  auto objHandle = runtime.makeHandle(objPtr);
577
578
  // Verify that the properties argument is also an object.
579
0
  auto objRes = toObject(runtime, props);
580
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
581
0
    return ExecutionStatus::EXCEPTION;
582
0
  }
583
0
  auto propsHandle = runtime.makeHandle<JSObject>(objRes.getValue());
584
585
  // Get the list of identifiers in props.
586
0
  auto cr = JSObject::getOwnPropertyKeys(
587
0
      propsHandle,
588
0
      runtime,
589
0
      OwnKeysFlags()
590
0
          .plusIncludeSymbols()
591
0
          .plusIncludeNonSymbols()
592
          // setIncludeNonEnumerable for proxies is necessary to get the right
593
          // traps in the right order.  The non-enumerable props will be
594
          // filtered out below.
595
0
          .setIncludeNonEnumerable(propsHandle->isProxyObject()));
596
0
  if (cr == ExecutionStatus::EXCEPTION) {
597
0
    return ExecutionStatus::EXCEPTION;
598
0
  }
599
0
  auto propNames = *cr;
600
601
  // This function may create an unbounded number of GC handles.
602
0
  GCScope scope{runtime, "objectDefinePropertiesInternal", UINT_MAX};
603
604
  // Iterate through every identifier, get the property descriptor
605
  // object, and store it in a list, according to Step 5.  What the
606
  // spec describes is a pair is represented in NewProps, which has
607
  // three arguments because the spec descriptor is represented here
608
  // by flags and a handle.
609
0
  struct NewProps {
610
0
    unsigned propNameIndex;
611
0
    DefinePropertyFlags flags;
612
0
    MutableHandle<> valueOrAccessor;
613
614
0
    NewProps(unsigned i, DefinePropertyFlags f, MutableHandle<> voa)
615
0
        : propNameIndex(i), flags(f), valueOrAccessor(std::move(voa)) {}
616
0
  };
617
0
  llvh::SmallVector<NewProps, 4> newProps;
618
619
  // We store each property name here. This is hoisted out of the loop
620
  // to avoid allocating a handle per property.
621
0
  MutableHandle<> propName{runtime};
622
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
623
624
0
  for (unsigned i = 0, e = propNames->getEndIndex(); i < e; ++i) {
625
0
    propName = propNames->at(runtime, i).unboxToHV(runtime);
626
0
    ComputedPropertyDescriptor desc;
627
0
    CallResult<bool> descRes = JSObject::getOwnComputedDescriptor(
628
0
        propsHandle, runtime, propName, tmpPropNameStorage, desc);
629
0
    if (LLVM_UNLIKELY(descRes == ExecutionStatus::EXCEPTION)) {
630
0
      return ExecutionStatus::EXCEPTION;
631
0
    }
632
0
    if (LLVM_UNLIKELY(!*descRes || !desc.flags.enumerable)) {
633
0
      continue;
634
0
    }
635
0
    CallResult<PseudoHandle<>> propRes = propsHandle->isProxyObject()
636
0
        ? JSObject::getComputed_RJS(propsHandle, runtime, propName)
637
0
        : JSObject::getComputedPropertyValueInternal_RJS(
638
0
              propsHandle, runtime, propsHandle, desc);
639
0
    if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) {
640
0
      return ExecutionStatus::EXCEPTION;
641
0
    }
642
0
    DefinePropertyFlags flags;
643
0
    MutableHandle<> valueOrAccessor{runtime};
644
0
    if (LLVM_UNLIKELY(
645
0
            toPropertyDescriptor(
646
0
                runtime.makeHandle(std::move(*propRes)),
647
0
                runtime,
648
0
                flags,
649
0
                valueOrAccessor) == ExecutionStatus::EXCEPTION)) {
650
0
      return ExecutionStatus::EXCEPTION;
651
0
    }
652
0
    newProps.emplace_back(i, flags, std::move(valueOrAccessor));
653
0
  }
654
655
  // For each descriptor in the list, add it to the object.
656
0
  for (const auto &newProp : newProps) {
657
0
    propName = propNames->at(runtime, newProp.propNameIndex).unboxToHV(runtime);
658
0
    auto result = JSObject::defineOwnComputedPrimitive(
659
0
        objHandle,
660
0
        runtime,
661
0
        propName,
662
0
        newProp.flags,
663
0
        newProp.valueOrAccessor,
664
0
        PropOpFlags().plusThrowOnError());
665
0
    if (result == ExecutionStatus::EXCEPTION) {
666
0
      return ExecutionStatus::EXCEPTION;
667
0
    }
668
0
  }
669
0
  return objHandle.getHermesValue();
670
0
}
671
672
CallResult<HermesValue>
673
0
objectCreate(void *, Runtime &runtime, NativeArgs args) {
674
  // Verify this method is called with an object or with 'null'.
675
0
  auto obj = args.dyncastArg<JSObject>(0);
676
0
  if (!obj && !args.getArg(0).isNull()) {
677
0
    return runtime.raiseTypeError(
678
0
        "Object prototype argument must be an Object or null");
679
0
  }
680
681
0
  auto newObj = JSObject::create(runtime, obj).getHermesValue();
682
0
  auto arg1 = args.getArgHandle(1);
683
0
  if (arg1->isUndefined()) {
684
0
    return newObj;
685
0
  }
686
  // Properties argument is present and not undefined.
687
0
  auto cr =
688
0
      objectDefinePropertiesInternal(runtime, runtime.makeHandle(newObj), arg1);
689
0
  if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) {
690
0
    return ExecutionStatus::EXCEPTION;
691
0
  }
692
0
  return *cr;
693
0
}
694
695
CallResult<HermesValue>
696
0
objectDefineProperties(void *, Runtime &runtime, NativeArgs args) {
697
0
  auto cr = objectDefinePropertiesInternal(
698
0
      runtime, args.getArgHandle(0), args.getArgHandle(1));
699
0
  if (cr == ExecutionStatus::EXCEPTION) {
700
0
    return ExecutionStatus::EXCEPTION;
701
0
  }
702
0
  return *cr;
703
0
}
704
705
0
CallResult<HermesValue> objectSeal(void *, Runtime &runtime, NativeArgs args) {
706
0
  auto objHandle = args.dyncastArg<JSObject>(0);
707
708
0
  if (!objHandle) {
709
0
    return args.getArg(0);
710
0
  }
711
712
0
  if (LLVM_UNLIKELY(
713
0
          JSObject::seal(objHandle, runtime) == ExecutionStatus::EXCEPTION)) {
714
0
    return ExecutionStatus::EXCEPTION;
715
0
  }
716
0
  return objHandle.getHermesValue();
717
0
}
718
719
CallResult<HermesValue>
720
0
objectFreeze(void *, Runtime &runtime, NativeArgs args) {
721
0
  auto objHandle = args.dyncastArg<JSObject>(0);
722
723
0
  if (!objHandle) {
724
0
    return args.getArg(0);
725
0
  }
726
727
0
  if (LLVM_UNLIKELY(
728
0
          JSObject::freeze(objHandle, runtime) == ExecutionStatus::EXCEPTION)) {
729
0
    return ExecutionStatus::EXCEPTION;
730
0
  }
731
0
  return objHandle.getHermesValue();
732
0
}
733
734
CallResult<HermesValue>
735
0
objectPreventExtensions(void *, Runtime &runtime, NativeArgs args) {
736
0
  Handle<JSObject> obj = args.dyncastArg<JSObject>(0);
737
738
0
  if (!obj) {
739
0
    return args.getArg(0);
740
0
  }
741
742
0
  CallResult<bool> statusRes = JSObject::preventExtensions(
743
0
      obj, runtime, PropOpFlags().plusThrowOnError());
744
0
  if (LLVM_UNLIKELY(statusRes == ExecutionStatus::EXCEPTION)) {
745
0
    return ExecutionStatus::EXCEPTION;
746
0
  }
747
0
  assert(
748
0
      *statusRes &&
749
0
      "Object.preventExtensions with ThrowOnError returned false");
750
0
  return args.getArg(0);
751
0
}
752
753
0
CallResult<HermesValue> objectIs(void *, Runtime &runtime, NativeArgs args) {
754
0
  return HermesValue::encodeBoolValue(
755
0
      isSameValue(args.getArg(0), args.getArg(1)));
756
0
}
757
758
CallResult<HermesValue>
759
0
objectIsSealed(void *, Runtime &runtime, NativeArgs args) {
760
0
  auto objHandle = args.dyncastArg<JSObject>(0);
761
762
0
  if (!objHandle) {
763
    // ES6.0 19.1.2.13: If Type(O) is not Object, return true.
764
0
    return HermesValue::encodeBoolValue(true);
765
0
  }
766
767
0
  return HermesValue::encodeBoolValue(JSObject::isSealed(objHandle, runtime));
768
0
}
769
770
CallResult<HermesValue>
771
0
objectIsFrozen(void *, Runtime &runtime, NativeArgs args) {
772
0
  auto objHandle = args.dyncastArg<JSObject>(0);
773
774
0
  if (!objHandle) {
775
    // ES6.0 19.1.2.12: If Type(O) is not Object, return true.
776
0
    return HermesValue::encodeBoolValue(true);
777
0
  }
778
779
0
  return HermesValue::encodeBoolValue(JSObject::isFrozen(objHandle, runtime));
780
0
}
781
782
CallResult<HermesValue>
783
0
objectIsExtensible(void *, Runtime &runtime, NativeArgs args) {
784
0
  PseudoHandle<JSObject> obj =
785
0
      createPseudoHandle(dyn_vmcast<JSObject>(args.getArg(0)));
786
787
0
  if (!obj) {
788
    // ES6.0 19.1.2.11: If Type(O) is not Object, return false.
789
0
    return HermesValue::encodeBoolValue(false);
790
0
  }
791
792
0
  CallResult<bool> extRes = JSObject::isExtensible(std::move(obj), runtime);
793
0
  if (LLVM_UNLIKELY(extRes == ExecutionStatus::EXCEPTION)) {
794
0
    return ExecutionStatus::EXCEPTION;
795
0
  }
796
0
  return HermesValue::encodeBoolValue(*extRes);
797
0
}
798
799
/// ES8.0 7.3.21.
800
/// EnumerableOwnProperties gets the requested properties based on \p kind.
801
CallResult<HermesValue> enumerableOwnProperties_RJS(
802
    Runtime &runtime,
803
    Handle<JSObject> objHandle,
804
0
    EnumerableOwnPropertiesKind kind) {
805
0
  GCScope gcScope{runtime};
806
807
0
  auto namesRes = getOwnPropertyKeysAsStrings(
808
0
      objHandle,
809
0
      runtime,
810
0
      OwnKeysFlags().plusIncludeNonSymbols().setIncludeNonEnumerable(
811
0
          objHandle->isProxyObject()));
812
0
  if (namesRes == ExecutionStatus::EXCEPTION) {
813
0
    return ExecutionStatus::EXCEPTION;
814
0
  }
815
0
  if (kind == EnumerableOwnPropertiesKind::Key && !objHandle->isProxyObject()) {
816
0
    return *namesRes;
817
0
  }
818
0
  auto names = runtime.makeHandle<JSArray>(*namesRes);
819
0
  uint32_t len = JSArray::getLength(*names, runtime);
820
821
0
  auto propertiesRes = JSArray::create(runtime, len, len);
822
0
  if (LLVM_UNLIKELY(propertiesRes == ExecutionStatus::EXCEPTION)) {
823
0
    return ExecutionStatus::EXCEPTION;
824
0
  }
825
0
  auto properties = *propertiesRes;
826
827
0
  MutableHandle<StringPrimitive> name{runtime};
828
0
  MutableHandle<> value{runtime};
829
0
  MutableHandle<> entry{runtime};
830
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
831
832
0
  uint32_t targetIdx = 0;
833
834
  // Add the requested elements to properties.
835
  // We must keep track of the targetIdx because elements' enumerability may be
836
  // modified by a getter at any point in the loop, so `i` will not necessarily
837
  // correspond to `targetIdx`.
838
0
  auto marker = gcScope.createMarker();
839
0
  for (uint32_t i = 0, len = JSArray::getLength(*names, runtime); i < len;
840
0
       ++i) {
841
0
    gcScope.flushToMarker(marker);
842
843
0
    name = names->at(runtime, i).getString(runtime);
844
    // By calling getString, name is guaranteed to be primitive.
845
0
    ComputedPropertyDescriptor desc;
846
0
    CallResult<bool> descRes = JSObject::getOwnComputedPrimitiveDescriptor(
847
0
        objHandle,
848
0
        runtime,
849
0
        name,
850
0
        JSObject::IgnoreProxy::Yes,
851
0
        tmpPropNameStorage,
852
0
        desc);
853
0
    if (LLVM_UNLIKELY(descRes == ExecutionStatus::EXCEPTION)) {
854
0
      return ExecutionStatus::EXCEPTION;
855
0
    }
856
0
    if (LLVM_LIKELY(*descRes && desc.flags.enumerable)) {
857
      // Ensure that the property is still there and that it is enumerable,
858
      // as descriptors can be modified by a getter at any point.
859
860
      // Safe to call the Internal version here because we ignored Proxy above.
861
0
      auto valueRes = JSObject::getComputedPropertyValueInternal_RJS(
862
0
          objHandle, runtime, objHandle, desc);
863
0
      if (LLVM_UNLIKELY(valueRes == ExecutionStatus::EXCEPTION)) {
864
0
        return ExecutionStatus::EXCEPTION;
865
0
      }
866
0
      value = std::move(*valueRes);
867
0
    } else if (!objHandle->isProxyObject()) {
868
0
      continue;
869
0
    } else {
870
      // This is a proxy, so we need to call getOwnProperty() to see
871
      // if the value exists and is enumerable on the proxy.
872
0
      descRes =
873
0
          JSProxy::getOwnProperty(objHandle, runtime, name, desc, nullptr);
874
0
      if (LLVM_UNLIKELY(descRes == ExecutionStatus::EXCEPTION)) {
875
0
        return ExecutionStatus::EXCEPTION;
876
0
      }
877
0
      if (!*descRes || !desc.flags.enumerable) {
878
        // And skip the property if not.
879
0
        continue;
880
0
      }
881
      // And if the caller needs the value, we need to fetch that,
882
      // too.
883
0
      if (kind != EnumerableOwnPropertiesKind::Key) {
884
0
        auto valueRes =
885
0
            JSProxy::getComputed(objHandle, runtime, name, objHandle);
886
0
        if (LLVM_UNLIKELY(valueRes == ExecutionStatus::EXCEPTION)) {
887
0
          return ExecutionStatus::EXCEPTION;
888
0
        }
889
0
        value = std::move(*valueRes);
890
0
      }
891
0
    }
892
893
0
    if (kind == EnumerableOwnPropertiesKind::KeyValue) {
894
0
      auto entryRes = JSArray::create(runtime, 2, 2);
895
0
      if (LLVM_UNLIKELY(entryRes == ExecutionStatus::EXCEPTION)) {
896
0
        return ExecutionStatus::EXCEPTION;
897
0
      }
898
0
      entry = entryRes->getHermesValue();
899
0
      JSArray::setElementAt(Handle<JSArray>::vmcast(entry), runtime, 0, name);
900
0
      JSArray::setElementAt(Handle<JSArray>::vmcast(entry), runtime, 1, value);
901
0
    } else if (kind == EnumerableOwnPropertiesKind::Value) {
902
0
      entry = value.getHermesValue();
903
0
    } else {
904
0
      assert(
905
0
          objHandle->isProxyObject() &&
906
0
          "Key kind did not return early but not proxy");
907
0
      entry = names->at(runtime, i).unboxToHV(runtime);
908
0
    }
909
910
    // The element must exist because we just read it.
911
0
    JSArray::setElementAt(properties, runtime, targetIdx++, entry);
912
0
  }
913
914
  // Set length at the end only, because properties may be shorter than
915
  // names.size() - some properties may have been made non-enumerable by getters
916
  // in the loop.
917
0
  if (LLVM_UNLIKELY(
918
0
          JSArray::setLengthProperty(properties, runtime, targetIdx) ==
919
0
          ExecutionStatus::EXCEPTION)) {
920
0
    return ExecutionStatus::EXCEPTION;
921
0
  }
922
923
0
  return properties.getHermesValue();
924
0
}
925
926
0
CallResult<HermesValue> objectKeys(void *, Runtime &runtime, NativeArgs args) {
927
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
928
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
929
0
    return ExecutionStatus::EXCEPTION;
930
0
  }
931
932
0
  return enumerableOwnProperties_RJS(
933
0
      runtime,
934
0
      runtime.makeHandle<JSObject>(*objRes),
935
0
      EnumerableOwnPropertiesKind::Key);
936
0
}
937
938
CallResult<HermesValue>
939
0
objectValues(void *, Runtime &runtime, NativeArgs args) {
940
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
941
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
942
0
    return ExecutionStatus::EXCEPTION;
943
0
  }
944
945
0
  return enumerableOwnProperties_RJS(
946
0
      runtime,
947
0
      runtime.makeHandle<JSObject>(*objRes),
948
0
      EnumerableOwnPropertiesKind::Value);
949
0
}
950
951
CallResult<HermesValue>
952
0
objectEntries(void *, Runtime &runtime, NativeArgs args) {
953
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
954
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
955
0
    return ExecutionStatus::EXCEPTION;
956
0
  }
957
958
0
  return enumerableOwnProperties_RJS(
959
0
      runtime,
960
0
      runtime.makeHandle<JSObject>(*objRes),
961
0
      EnumerableOwnPropertiesKind::KeyValue);
962
0
}
963
964
/// ES10 19.1.2.7 Object.fromEntries(iterable)
965
/// Creates an object from an iterable of [key, value] pairs.
966
CallResult<HermesValue>
967
0
objectFromEntries(void *, Runtime &runtime, NativeArgs args) {
968
  // 1. Perform ? RequireObjectCoercible(iterable).
969
0
  if (args.getArg(0).isNull() || args.getArg(0).isUndefined()) {
970
0
    return runtime.raiseTypeError(
971
0
        "fromEntries argument is not coercible to Object");
972
0
  }
973
974
0
  GCScopeMarkerRAII marker{runtime};
975
976
  // 2. Let obj be ObjectCreate(%ObjectPrototype%).
977
0
  Handle<JSObject> obj = runtime.makeHandle(JSObject::create(runtime));
978
  // 3. Assert: obj is an extensible ordinary object with no own properties.
979
980
  // 4. Let stepsDefine be the algorithm steps defined in
981
  //    CreateDataPropertyOnObject Functions.
982
  // 5. Let adder be CreateBuiltinFunction(stepsDefine, « »).
983
  // NOTE: We avoid actually creating the NativeFunction here by simply putting
984
  // the DefineProperty code in the callback.
985
  // 6. Return ? AddEntriesFromIterable(obj, iterable, adder).
986
0
  return addEntriesFromIterable(
987
0
      runtime,
988
0
      obj,
989
0
      args.getArgHandle(0),
990
0
      [obj, &runtime](Runtime &, Handle<> key, Handle<> value) {
991
0
        const DefinePropertyFlags dpf =
992
0
            DefinePropertyFlags::getDefaultNewPropertyFlags();
993
0
        return JSObject::defineOwnComputed(
994
0
            obj, runtime, key, dpf, value, PropOpFlags().plusThrowOnError());
995
0
      });
996
0
}
997
998
CallResult<HermesValue>
999
0
objectAssign(void *, Runtime &runtime, NativeArgs args) {
1000
0
  vm::GCScope gcScope(runtime);
1001
1002
  // 1. Let to be ToObject(target).
1003
0
  auto objRes = toObject(runtime, args.getArgHandle(0));
1004
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
1005
    // 2. ReturnIfAbrupt(to).
1006
0
    return ExecutionStatus::EXCEPTION;
1007
0
  }
1008
0
  auto toHandle = runtime.makeHandle<JSObject>(objRes.getValue());
1009
1010
  // 3. If only one argument was passed, return to.
1011
0
  if (LLVM_UNLIKELY(args.getArgCount() == 1)) {
1012
0
    return toHandle.getHermesValue();
1013
0
  }
1014
1015
  // 4. Let sources be the List of argument values starting with the second
1016
  // argument.
1017
  // 5. For each element nextSource of sources, in ascending index order,
1018
1019
  // Handle for the current object being copied from.
1020
0
  MutableHandle<JSObject> fromHandle{runtime};
1021
  // Handle for the next key to be processed when copying properties.
1022
0
  MutableHandle<> nextKeyHandle{runtime};
1023
  // Handle for the property value being copied.
1024
0
  MutableHandle<> propValueHandle{runtime};
1025
  // Handle for the property value being copied.
1026
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
1027
1028
0
  for (uint32_t argIdx = 1; argIdx < args.getArgCount(); argIdx++) {
1029
0
    GCScopeMarkerRAII markerOuter(gcScope);
1030
0
    auto nextSource = args.getArgHandle(argIdx);
1031
    // 5.a. If nextSource is undefined or null, let keys be an empty List.
1032
0
    if (nextSource->isNull() || nextSource->isUndefined()) {
1033
0
      continue;
1034
0
    }
1035
1036
    // 5.b.i. Let from be ToObject(nextSource).
1037
0
    if (LLVM_UNLIKELY(
1038
0
            (objRes = toObject(runtime, nextSource)) ==
1039
0
            ExecutionStatus::EXCEPTION)) {
1040
0
      return ExecutionStatus::EXCEPTION;
1041
0
    }
1042
0
    fromHandle = vmcast<JSObject>(objRes.getValue());
1043
1044
    // 5.b.ii. Let keys be from.[[OwnPropertyKeys]]().
1045
0
    auto cr = JSObject::getOwnPropertyKeys(
1046
0
        fromHandle,
1047
0
        runtime,
1048
0
        OwnKeysFlags()
1049
0
            .plusIncludeSymbols()
1050
0
            .plusIncludeNonSymbols()
1051
0
            .setIncludeNonEnumerable(fromHandle->isProxyObject()));
1052
0
    if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) {
1053
      // 5.c.ii. ReturnIfAbrupt(keys).
1054
0
      return ExecutionStatus::EXCEPTION;
1055
0
    }
1056
1057
0
    auto keys = *cr;
1058
0
    ComputedPropertyDescriptor desc;
1059
    // 5.c. Repeat for each element nextKey of keys in List order,
1060
0
    for (uint32_t nextKeyIdx = 0, endIdx = keys->getEndIndex();
1061
0
         nextKeyIdx < endIdx;
1062
0
         ++nextKeyIdx) {
1063
0
      GCScopeMarkerRAII markerInner(gcScope);
1064
1065
0
      nextKeyHandle = keys->at(runtime, nextKeyIdx).unboxToHV(runtime);
1066
1067
      // 5.c.i. Let desc be from.[[GetOwnProperty]](nextKey).
1068
0
      auto descCr = JSObject::getOwnComputedDescriptor(
1069
0
          fromHandle, runtime, nextKeyHandle, tmpPropNameStorage, desc);
1070
0
      if (LLVM_UNLIKELY(descCr == ExecutionStatus::EXCEPTION)) {
1071
        // 5.c.ii. ReturnIfAbrupt(desc).
1072
0
        return ExecutionStatus::EXCEPTION;
1073
0
      }
1074
      // 5.c.iii. if desc is not undefined and desc.[[Enumerable]] is true, then
1075
0
      if (LLVM_UNLIKELY(!*descCr) || LLVM_UNLIKELY(!desc.flags.enumerable)) {
1076
0
        continue;
1077
0
      }
1078
1079
      // 5.c.iii.1. Let propValue be Get(from, nextKey).
1080
1081
      // getComputed_RJS would work here in all cases.  But, just
1082
      // changing it to make proxy work is is a surprisingly large
1083
      // regression if used always, even with no Proxy objects.  So we
1084
      // check if we can use getComputedPropertyValue_RJS and do so.
1085
0
      CallResult<PseudoHandle<>> propRes = fromHandle->isProxyObject()
1086
0
          ? JSObject::getComputed_RJS(fromHandle, runtime, nextKeyHandle)
1087
0
          : JSObject::getComputedPropertyValue_RJS(
1088
0
                fromHandle,
1089
0
                runtime,
1090
0
                fromHandle,
1091
0
                tmpPropNameStorage,
1092
0
                desc,
1093
0
                nextKeyHandle);
1094
0
      if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) {
1095
        // 5.c.iii.2. ReturnIfAbrupt(propValue).
1096
0
        return ExecutionStatus::EXCEPTION;
1097
0
      }
1098
0
      propValueHandle = std::move(*propRes);
1099
1100
      // 5.c.iii.3. Let status be Set(to, nextKey, propValue, true).
1101
0
      auto statusCr = JSObject::putComputed_RJS(
1102
0
          toHandle,
1103
0
          runtime,
1104
0
          nextKeyHandle,
1105
0
          propValueHandle,
1106
0
          PropOpFlags().plusThrowOnError());
1107
0
      if (LLVM_UNLIKELY(statusCr == ExecutionStatus::EXCEPTION)) {
1108
        // 5.c.ii.4. ReturnIfAbrupt(status).
1109
0
        return ExecutionStatus::EXCEPTION;
1110
0
      }
1111
0
    }
1112
0
  }
1113
1114
  // 6 Return to.
1115
0
  return toHandle.getHermesValue();
1116
0
}
1117
1118
CallResult<HermesValue>
1119
0
objectSetPrototypeOf(void *, Runtime &runtime, NativeArgs args) {
1120
0
  Handle<> O = args.getArgHandle(0);
1121
0
  Handle<> proto = args.getArgHandle(1);
1122
  // 1. Let O be RequireObjectCoercible(O).
1123
0
  if (O->isNull() || O->isUndefined()) {
1124
0
    return runtime.raiseTypeError(
1125
0
        "setPrototypeOf argument is not coercible to Object");
1126
0
  }
1127
1128
  // 3. If Type(proto) is neither Object nor Null, throw a TypeError exception.
1129
0
  if (!(proto->isObject() || proto->isNull())) {
1130
0
    return runtime.raiseTypeError(
1131
0
        "setPrototypeOf new prototype must be object or null");
1132
0
  }
1133
  // 4. If Type(O) is not Object, return O.
1134
0
  if (!vmisa<JSObject>(*O)) {
1135
0
    return *O;
1136
0
  }
1137
  // 5. Let status be O.[[SetPrototypeOf]](proto).
1138
0
  auto status = JSObject::setParent(
1139
0
      vmcast<JSObject>(*O),
1140
0
      runtime,
1141
0
      dyn_vmcast<JSObject>(*proto),
1142
0
      PropOpFlags().plusThrowOnError());
1143
  // 7. If status is false, throw a TypeError exception.
1144
  // Note that JSObject::setParent throws instead of returning false.
1145
0
  if (LLVM_UNLIKELY(status == ExecutionStatus::EXCEPTION)) {
1146
0
    return ExecutionStatus::EXCEPTION;
1147
0
  }
1148
1149
  // 8. Return O.
1150
0
  return *O;
1151
0
}
1152
1153
//===----------------------------------------------------------------------===//
1154
/// Object.prototype.
1155
1156
CallResult<HermesValue> directObjectPrototypeToString(
1157
    Runtime &runtime,
1158
0
    Handle<> arg) {
1159
0
  StringPrimitive *str;
1160
1161
0
  if (arg->isUndefined()) {
1162
0
    str = runtime.getPredefinedString(Predefined::squareObjectUndefined);
1163
0
  } else if (arg->isNull()) {
1164
0
    str = runtime.getPredefinedString(Predefined::squareObjectNull);
1165
0
  } else if (arg->getRaw() == runtime.getGlobal().getHermesValue().getRaw()) {
1166
0
    str = runtime.getPredefinedString(Predefined::squareObjectGlobal);
1167
0
  } else {
1168
0
    auto res = toObject(runtime, arg);
1169
0
    if (res == ExecutionStatus::EXCEPTION) {
1170
0
      return ExecutionStatus::EXCEPTION;
1171
0
    }
1172
1173
0
    auto O = runtime.makeHandle<JSObject>(res.getValue());
1174
    // 16. Let tag be Get (O, @@toStringTag).
1175
0
    auto tagRes = JSObject::getNamed_RJS(
1176
0
        O, runtime, Predefined::getSymbolID(Predefined::SymbolToStringTag));
1177
0
    if (LLVM_UNLIKELY(tagRes == ExecutionStatus::EXCEPTION)) {
1178
0
      return ExecutionStatus::EXCEPTION;
1179
0
    }
1180
1181
0
    if ((*tagRes)->isString()) {
1182
0
      auto tag = runtime.makeHandle(
1183
0
          PseudoHandle<StringPrimitive>::vmcast(std::move(*tagRes)));
1184
0
      SafeUInt32 tagLen(tag->getStringLength());
1185
0
      tagLen.add(9);
1186
0
      CallResult<StringBuilder> builder =
1187
0
          StringBuilder::createStringBuilder(runtime, tagLen);
1188
0
      if (LLVM_UNLIKELY(builder == ExecutionStatus::EXCEPTION)) {
1189
0
        return ExecutionStatus::EXCEPTION;
1190
0
      }
1191
      // 19. Return the String that is the result of concatenating
1192
      // "[object ", tag, and "]".
1193
0
      builder->appendASCIIRef(ASCIIRef{"[object ", 8});
1194
0
      builder->appendStringPrim(tag);
1195
0
      builder->appendCharacter(']');
1196
0
      return builder->getStringPrimitive().getHermesValue();
1197
0
    }
1198
1199
    // 18. If Type(tag) is not String, let tag be builtinTag.
1200
0
    CallResult<bool> isArrayRes = isArray(runtime, *O);
1201
0
    if (LLVM_UNLIKELY(isArrayRes == ExecutionStatus::EXCEPTION)) {
1202
0
      return ExecutionStatus::EXCEPTION;
1203
0
    }
1204
0
    if (*isArrayRes) {
1205
      // 6. If isArray is true, let builtinTag be "Array".
1206
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSArray);
1207
0
    } else if (vmisa<JSString>(O.getHermesValue())) {
1208
      // 7. Else, if O is an exotic String object, let builtinTag be "String".
1209
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSString);
1210
0
    } else if (vmisa<Arguments>(O.getHermesValue())) {
1211
      // 8. Else, if O has an [[ParameterMap]] internal slot, let builtinTag be
1212
      // "Arguments".
1213
0
      str = runtime.getPredefinedString(Predefined::squareObject_Arguments);
1214
0
    } else if (vmisa<Callable>(O.getHermesValue())) {
1215
      // 9. Else, if O has a [[Call]] internal method, let builtinTag be
1216
      // "Function".
1217
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSFunction);
1218
0
    } else if (vmisa<JSError>(O.getHermesValue())) {
1219
      // 10. Else, if O has an [[ErrorData]] internal slot, let builtinTag be
1220
      // "Error".
1221
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSError);
1222
0
    } else if (vmisa<JSBoolean>(O.getHermesValue())) {
1223
      // 11. Else, if O has a [[BooleanData]] internal slot, let builtinTag be
1224
      // "Boolean".
1225
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSBoolean);
1226
0
    } else if (vmisa<JSNumber>(O.getHermesValue())) {
1227
      // 12. Else, if O has a [[NumberData]] internal slot, let builtinTag be
1228
      // "Number".
1229
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSNumber);
1230
0
    } else if (vmisa<JSDate>(O.getHermesValue())) {
1231
      // 13. Else, if O has a [[DateValue]] internal slot, let builtinTag be
1232
      // "Date".
1233
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSDate);
1234
0
    } else if (vmisa<JSRegExp>(O.getHermesValue())) {
1235
      // 14. Else, if O has a [[RegExpMatcher]] internal slot, let builtinTag be
1236
      // "RegExp".
1237
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSRegExp);
1238
0
    } else {
1239
0
      str = runtime.getPredefinedString(Predefined::squareObject_JSObject);
1240
0
    }
1241
0
  }
1242
1243
0
  return HermesValue::encodeStringValue(str);
1244
0
}
1245
1246
CallResult<HermesValue>
1247
0
objectPrototypeToString(void *, Runtime &runtime, NativeArgs args) {
1248
0
  return directObjectPrototypeToString(runtime, args.getThisHandle());
1249
0
}
1250
1251
CallResult<HermesValue>
1252
0
objectPrototypeToLocaleString(void *, Runtime &runtime, NativeArgs args) {
1253
0
  GCScope gcScope(runtime);
1254
0
  auto objRes = toObject(runtime, args.getThisHandle());
1255
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
1256
0
    return ExecutionStatus::EXCEPTION;
1257
0
  }
1258
0
  auto selfHandle = runtime.makeHandle<JSObject>(objRes.getValue());
1259
0
  auto propRes = JSObject::getNamed_RJS(
1260
0
      selfHandle, runtime, Predefined::getSymbolID(Predefined::toString));
1261
0
  if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) {
1262
0
    return ExecutionStatus::EXCEPTION;
1263
0
  }
1264
0
  if (auto func = Handle<Callable>::dyn_vmcast(
1265
0
          runtime.makeHandle(std::move(*propRes)))) {
1266
0
    return Callable::executeCall0(func, runtime, selfHandle)
1267
0
        .toCallResultHermesValue();
1268
0
  }
1269
0
  return runtime.raiseTypeError("toString must be callable");
1270
0
}
1271
1272
CallResult<HermesValue>
1273
1.10k
objectPrototypeValueOf(void *, Runtime &runtime, NativeArgs args) {
1274
1.10k
  auto res = toObject(runtime, args.getThisHandle());
1275
1.10k
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
1276
0
    return ExecutionStatus::EXCEPTION;
1277
0
  }
1278
1.10k
  return res;
1279
1.10k
}
1280
1281
static CallResult<HermesValue>
1282
0
objectHasOwnHelper(Runtime &runtime, Handle<JSObject> O, Handle<> P) {
1283
0
  ComputedPropertyDescriptor desc;
1284
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
1285
0
  CallResult<bool> hasProp = JSObject::getOwnComputedDescriptor(
1286
0
      O, runtime, P, tmpPropNameStorage, desc);
1287
0
  if (LLVM_UNLIKELY(hasProp == ExecutionStatus::EXCEPTION)) {
1288
0
    return ExecutionStatus::EXCEPTION;
1289
0
  }
1290
0
  if (*hasProp) {
1291
0
    return HermesValue::encodeBoolValue(true);
1292
0
  }
1293
  // For compatibility with polyfills we want to pretend that all HostObject
1294
  // properties are "own" properties in hasOwnProperty() and in
1295
  // getOwnPropertyDescriptor(). Since there is no way to check for a
1296
  // HostObject property, we must always assume success. In practice the
1297
  // property name would have been obtained from enumerating the properties in
1298
  // JS code that looks something like this:
1299
  //    for(key in hostObj) {
1300
  //      if (Object.hasOwnProperty(hostObj, key))
1301
  //        ...
1302
  //    }
1303
0
  if (LLVM_UNLIKELY(O->isHostObject())) {
1304
0
    return HermesValue::encodeBoolValue(true);
1305
0
  }
1306
0
  return HermesValue::encodeBoolValue(false);
1307
0
}
1308
1309
/// ES11.0 19.1.3.2
1310
CallResult<HermesValue>
1311
0
objectPrototypeHasOwnProperty(void *, Runtime &runtime, NativeArgs args) {
1312
  /// 1. Let P be ? ToPropertyKey(V).
1313
0
  auto PRes = toPropertyKey(runtime, args.getArgHandle(0));
1314
0
  if (LLVM_UNLIKELY(PRes == ExecutionStatus::EXCEPTION)) {
1315
0
    return ExecutionStatus::EXCEPTION;
1316
0
  }
1317
1318
  /// 2. Let O be ? ToObject(this value).
1319
0
  auto ORes = toObject(runtime, args.getThisHandle());
1320
0
  if (LLVM_UNLIKELY(ORes == ExecutionStatus::EXCEPTION)) {
1321
0
    return ExecutionStatus::EXCEPTION;
1322
0
  }
1323
  /// 3. Return ? HasOwnProperty(O, P).
1324
0
  Handle<JSObject> O = runtime.makeHandle<JSObject>(ORes.getValue());
1325
0
  return objectHasOwnHelper(runtime, O, *PRes);
1326
0
}
1327
1328
CallResult<HermesValue>
1329
0
objectHasOwn(void *, Runtime &runtime, NativeArgs args) {
1330
  /// 1. Let O be ? ToObject(O).
1331
0
  auto ORes = toObject(runtime, args.getArgHandle(0));
1332
0
  if (LLVM_UNLIKELY(ORes == ExecutionStatus::EXCEPTION)) {
1333
0
    return ExecutionStatus::EXCEPTION;
1334
0
  }
1335
0
  Handle<JSObject> O = runtime.makeHandle<JSObject>(ORes.getValue());
1336
1337
  /// 2. Let P be ? ToPropertyKey(P).
1338
0
  auto PRes = toPropertyKey(runtime, args.getArgHandle(1));
1339
0
  if (LLVM_UNLIKELY(PRes == ExecutionStatus::EXCEPTION)) {
1340
0
    return ExecutionStatus::EXCEPTION;
1341
0
  }
1342
  /// 3. Return ? HasOwnProperty(O, P).
1343
0
  return objectHasOwnHelper(runtime, O, *PRes);
1344
0
}
1345
1346
CallResult<HermesValue>
1347
0
objectPrototypeIsPrototypeOf(void *, Runtime &runtime, NativeArgs args) {
1348
0
  if (LLVM_UNLIKELY(!args.getArg(0).isObject())) {
1349
    // If arg[0] is not an object, return false.
1350
0
    return HermesValue::encodeBoolValue(false);
1351
0
  }
1352
0
  auto res = toObject(runtime, args.getThisHandle());
1353
0
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
1354
0
    return ExecutionStatus::EXCEPTION;
1355
0
  }
1356
0
  Handle<JSObject> objHandle = runtime.makeHandle<JSObject>(*res);
1357
0
  PseudoHandle<JSObject> parent =
1358
0
      createPseudoHandle(vmcast<JSObject>(args.getArg(0)));
1359
0
  while (true) {
1360
0
    CallResult<PseudoHandle<JSObject>> protoRes =
1361
0
        JSObject::getPrototypeOf(std::move(parent), runtime);
1362
0
    if (LLVM_UNLIKELY(protoRes == ExecutionStatus::EXCEPTION)) {
1363
0
      return ExecutionStatus::EXCEPTION;
1364
0
    }
1365
0
    if (!*protoRes) {
1366
0
      break;
1367
0
    }
1368
0
    parent = std::move(*protoRes);
1369
0
    if (parent.get() == objHandle.get()) {
1370
0
      return HermesValue::encodeBoolValue(true);
1371
0
    }
1372
0
  }
1373
0
  return HermesValue::encodeBoolValue(false);
1374
0
}
1375
1376
CallResult<HermesValue>
1377
0
objectPrototypePropertyIsEnumerable(void *, Runtime &runtime, NativeArgs args) {
1378
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
1379
0
  auto res = toObject(runtime, args.getThisHandle());
1380
0
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
1381
0
    return ExecutionStatus::EXCEPTION;
1382
0
  }
1383
0
  ComputedPropertyDescriptor desc;
1384
0
  auto status = JSObject::getOwnComputedDescriptor(
1385
0
      runtime.makeHandle<JSObject>(res.getValue()),
1386
0
      runtime,
1387
0
      args.getArgHandle(0),
1388
0
      tmpPropNameStorage,
1389
0
      desc);
1390
0
  if (LLVM_UNLIKELY(status == ExecutionStatus::EXCEPTION)) {
1391
0
    return ExecutionStatus::EXCEPTION;
1392
0
  }
1393
0
  return HermesValue::encodeBoolValue(
1394
0
      status.getValue() && desc.flags.enumerable);
1395
0
}
1396
1397
CallResult<HermesValue>
1398
0
objectPrototypeProto_getter(void *, Runtime &runtime, NativeArgs args) {
1399
0
  CallResult<HermesValue> res = toObject(runtime, args.getThisHandle());
1400
0
  if (res == ExecutionStatus::EXCEPTION) {
1401
0
    return ExecutionStatus::EXCEPTION;
1402
0
  }
1403
0
  return getPrototypeOf(runtime, runtime.makeHandle(vmcast<JSObject>(*res)));
1404
0
}
1405
1406
CallResult<HermesValue>
1407
0
objectPrototypeProto_setter(void *, Runtime &runtime, NativeArgs args) {
1408
  // thisArg must be coercible to Object.
1409
0
  if (args.getThisArg().isNull() || args.getThisArg().isUndefined()) {
1410
0
    return runtime.raiseTypeError("'this' is not coercible to JSObject");
1411
0
  }
1412
  // But if it isn't an actual object, do nothing.
1413
0
  if (!args.getThisArg().isObject()) {
1414
0
    return HermesValue::encodeUndefinedValue();
1415
0
  }
1416
1417
0
  HermesValue proto = args.getArg(0);
1418
0
  JSObject *protoPtr;
1419
0
  if (proto.isObject())
1420
0
    protoPtr = vmcast<JSObject>(proto);
1421
0
  else if (proto.isNull())
1422
0
    protoPtr = nullptr;
1423
0
  else
1424
0
    return HermesValue::encodeUndefinedValue();
1425
1426
0
  if (LLVM_UNLIKELY(
1427
0
          JSObject::setParent(
1428
0
              vmcast<JSObject>(args.getThisArg()),
1429
0
              runtime,
1430
0
              protoPtr,
1431
0
              PropOpFlags().plusThrowOnError()) == ExecutionStatus::EXCEPTION))
1432
0
    return ExecutionStatus::EXCEPTION;
1433
0
  return HermesValue::encodeUndefinedValue();
1434
0
}
1435
1436
CallResult<HermesValue>
1437
0
objectPrototypeDefineGetter(void *, Runtime &runtime, NativeArgs args) {
1438
0
  auto objRes = toObject(runtime, args.getThisHandle());
1439
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
1440
0
    return ExecutionStatus::EXCEPTION;
1441
0
  }
1442
0
  auto O = runtime.makeHandle<JSObject>(objRes.getValue());
1443
1444
0
  auto getter = args.dyncastArg<Callable>(1);
1445
0
  if (!getter) {
1446
0
    return runtime.raiseTypeError("__defineGetter__ getter not callable");
1447
0
  }
1448
1449
0
  HermesValue crtRes = PropertyAccessor::create(
1450
0
      runtime, getter, Runtime::makeNullHandle<Callable>());
1451
0
  auto accessor = runtime.makeHandle<PropertyAccessor>(crtRes);
1452
1453
0
  DefinePropertyFlags dpf;
1454
0
  dpf.setEnumerable = 1;
1455
0
  dpf.enumerable = 1;
1456
0
  dpf.setConfigurable = 1;
1457
0
  dpf.configurable = 1;
1458
0
  dpf.setGetter = 1;
1459
1460
0
  auto res = JSObject::defineOwnComputed(
1461
0
      O,
1462
0
      runtime,
1463
0
      args.getArgHandle(0),
1464
0
      dpf,
1465
0
      accessor,
1466
0
      PropOpFlags().plusThrowOnError());
1467
0
  if (res == ExecutionStatus::EXCEPTION) {
1468
0
    return ExecutionStatus::EXCEPTION;
1469
0
  }
1470
1471
0
  return HermesValue::encodeUndefinedValue();
1472
0
}
1473
1474
CallResult<HermesValue>
1475
0
objectPrototypeDefineSetter(void *, Runtime &runtime, NativeArgs args) {
1476
0
  auto objRes = toObject(runtime, args.getThisHandle());
1477
0
  if (LLVM_UNLIKELY(objRes == ExecutionStatus::EXCEPTION)) {
1478
0
    return ExecutionStatus::EXCEPTION;
1479
0
  }
1480
0
  auto O = runtime.makeHandle<JSObject>(objRes.getValue());
1481
1482
0
  auto setter = args.dyncastArg<Callable>(1);
1483
0
  if (!setter) {
1484
0
    return runtime.raiseTypeError("__defineSetter__ setter not callable");
1485
0
  }
1486
1487
0
  HermesValue crtRes = PropertyAccessor::create(
1488
0
      runtime, Runtime::makeNullHandle<Callable>(), setter);
1489
0
  auto accessor = runtime.makeHandle<PropertyAccessor>(crtRes);
1490
1491
0
  DefinePropertyFlags dpf;
1492
0
  dpf.setEnumerable = 1;
1493
0
  dpf.enumerable = 1;
1494
0
  dpf.setConfigurable = 1;
1495
0
  dpf.configurable = 1;
1496
0
  dpf.setSetter = 1;
1497
1498
0
  auto res = JSObject::defineOwnComputed(
1499
0
      O,
1500
0
      runtime,
1501
0
      args.getArgHandle(0),
1502
0
      dpf,
1503
0
      accessor,
1504
0
      PropOpFlags().plusThrowOnError());
1505
0
  if (res == ExecutionStatus::EXCEPTION) {
1506
0
    return ExecutionStatus::EXCEPTION;
1507
0
  }
1508
1509
0
  return HermesValue::encodeUndefinedValue();
1510
0
}
1511
1512
namespace {
1513
1514
/// Helper function for objectPrototypeLookup{Get,Set}ter.  Returns a
1515
/// pointer to the cell which contains the actual accessors, or
1516
/// nullptr if there aren't any.  This iterates internally because the
1517
/// functions in JSObject are structured in such a way that for
1518
/// complex proxy/target/prototype chains, the accessor is called in a
1519
/// deeply nested place.  To expose it, we need to do the chaining
1520
/// explicitly.
1521
CallResult<PropertyAccessor *> lookupAccessor(
1522
    Runtime &runtime,
1523
0
    NativeArgs args) {
1524
0
  CallResult<HermesValue> res = toObject(runtime, args.getThisHandle());
1525
0
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) {
1526
0
    return ExecutionStatus::EXCEPTION;
1527
0
  }
1528
0
  MutableHandle<JSObject> O = runtime.makeMutableHandle(vmcast<JSObject>(*res));
1529
0
  Handle<> key = args.getArgHandle(0);
1530
0
  MutableHandle<> valueOrAccessor{runtime};
1531
0
  MutableHandle<SymbolID> tmpPropNameStorage{runtime};
1532
0
  do {
1533
0
    ComputedPropertyDescriptor desc;
1534
0
    CallResult<bool> definedRes = JSObject::getOwnComputedDescriptor(
1535
0
        O, runtime, key, tmpPropNameStorage, desc, valueOrAccessor);
1536
0
    if (LLVM_UNLIKELY(definedRes == ExecutionStatus::EXCEPTION)) {
1537
0
      return ExecutionStatus::EXCEPTION;
1538
0
    }
1539
0
    if (*definedRes) {
1540
0
      if (!desc.flags.accessor) {
1541
0
        break;
1542
0
      }
1543
0
      return vmcast<PropertyAccessor>(valueOrAccessor.get());
1544
0
    }
1545
0
    CallResult<PseudoHandle<JSObject>> protoRes =
1546
0
        JSObject::getPrototypeOf(O, runtime);
1547
0
    if (LLVM_UNLIKELY(protoRes == ExecutionStatus::EXCEPTION)) {
1548
0
      return ExecutionStatus::EXCEPTION;
1549
0
    }
1550
0
    O = protoRes->get();
1551
0
  } while (O);
1552
0
  return nullptr;
1553
0
}
1554
1555
} // namespace
1556
1557
CallResult<HermesValue>
1558
0
objectPrototypeLookupGetter(void *, Runtime &runtime, NativeArgs args) {
1559
0
  CallResult<PropertyAccessor *> accessorRes = lookupAccessor(runtime, args);
1560
0
  if (LLVM_UNLIKELY(accessorRes == ExecutionStatus::EXCEPTION)) {
1561
0
    return ExecutionStatus::EXCEPTION;
1562
0
  }
1563
0
  return (*accessorRes && (*accessorRes)->getter)
1564
0
      ? HermesValue::encodeObjectValue(
1565
0
            (*accessorRes)->getter.getNonNull(runtime))
1566
0
      : HermesValue::encodeUndefinedValue();
1567
0
}
1568
1569
CallResult<HermesValue>
1570
0
objectPrototypeLookupSetter(void *, Runtime &runtime, NativeArgs args) {
1571
0
  CallResult<PropertyAccessor *> accessorRes = lookupAccessor(runtime, args);
1572
0
  if (LLVM_UNLIKELY(accessorRes == ExecutionStatus::EXCEPTION)) {
1573
0
    return ExecutionStatus::EXCEPTION;
1574
0
  }
1575
0
  return (*accessorRes && (*accessorRes)->setter)
1576
0
      ? HermesValue::encodeObjectValue(
1577
0
            (*accessorRes)->setter.getNonNull(runtime))
1578
0
      : HermesValue::encodeUndefinedValue();
1579
0
}
1580
1581
} // namespace vm
1582
} // namespace hermes