Coverage Report

Created: 2025-12-30 08:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/deps/v8/include/v8-object.h
Line
Count
Source
1
// Copyright 2021 the V8 project authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef INCLUDE_V8_OBJECT_H_
6
#define INCLUDE_V8_OBJECT_H_
7
8
#include "cppgc/garbage-collected.h"
9
#include "cppgc/name-provider.h"
10
#include "v8-internal.h"           // NOLINT(build/include_directory)
11
#include "v8-local-handle.h"       // NOLINT(build/include_directory)
12
#include "v8-maybe.h"              // NOLINT(build/include_directory)
13
#include "v8-persistent-handle.h"  // NOLINT(build/include_directory)
14
#include "v8-primitive.h"          // NOLINT(build/include_directory)
15
#include "v8-sandbox.h"            // NOLINT(build/include_directory)
16
#include "v8-traced-handle.h"      // NOLINT(build/include_directory)
17
#include "v8-value.h"              // NOLINT(build/include_directory)
18
#include "v8config.h"              // NOLINT(build/include_directory)
19
20
namespace v8 {
21
22
class Array;
23
class Function;
24
class FunctionTemplate;
25
template <typename T>
26
class PropertyCallbackInfo;
27
28
/**
29
 * A tag for embedder data. Objects with different C++ types should use
30
 * different values of EmbedderDataTypeTag when written to embedder data. The
31
 * allowed range is 0..V8_EMBEDDER_DATA_TAG_COUNT - 1. If this is not
32
 * sufficient, V8_EMBEDDER_DATA_TAG_COUNT can be increased.
33
 */
34
using EmbedderDataTypeTag = uint16_t;
35
36
constexpr EmbedderDataTypeTag kEmbedderDataTypeTagDefault = 0;
37
38
V8_EXPORT internal::ExternalPointerTag ToExternalPointerTag(
39
    v8::EmbedderDataTypeTag api_tag);
40
41
/**
42
 * A private symbol
43
 *
44
 * This is an experimental feature. Use at your own risk.
45
 */
46
class V8_EXPORT Private : public Data {
47
 public:
48
  /**
49
   * Returns the print name string of the private symbol, or undefined if none.
50
   */
51
  Local<Value> Name() const;
52
53
  /**
54
   * Create a private symbol. If name is not empty, it will be the description.
55
   */
56
  static Local<Private> New(Isolate* isolate,
57
                            Local<String> name = Local<String>());
58
59
  /**
60
   * Retrieve a global private symbol. If a symbol with this name has not
61
   * been retrieved in the same isolate before, it is created.
62
   * Note that private symbols created this way are never collected, so
63
   * they should only be used for statically fixed properties.
64
   * Also, there is only one global name space for the names used as keys.
65
   * To minimize the potential for clashes, use qualified names as keys,
66
   * e.g., "Class#property".
67
   */
68
  static Local<Private> ForApi(Isolate* isolate, Local<String> name);
69
70
  V8_INLINE static Private* Cast(Data* data);
71
72
 private:
73
  Private();
74
75
  static void CheckCast(Data* that);
76
};
77
78
/**
79
 * An instance of a Property Descriptor, see Ecma-262 6.2.4.
80
 *
81
 * Properties in a descriptor are present or absent. If you do not set
82
 * `enumerable`, `configurable`, and `writable`, they are absent. If `value`,
83
 * `get`, or `set` are absent, but you must specify them in the constructor, use
84
 * empty handles.
85
 *
86
 * Accessors `get` and `set` must be callable or undefined if they are present.
87
 *
88
 * \note Only query properties if they are present, i.e., call `x()` only if
89
 * `has_x()` returns true.
90
 *
91
 * \code
92
 * // var desc = {writable: false}
93
 * v8::PropertyDescriptor d(Local<Value>()), false);
94
 * d.value(); // error, value not set
95
 * if (d.has_writable()) {
96
 *   d.writable(); // false
97
 * }
98
 *
99
 * // var desc = {value: undefined}
100
 * v8::PropertyDescriptor d(v8::Undefined(isolate));
101
 *
102
 * // var desc = {get: undefined}
103
 * v8::PropertyDescriptor d(v8::Undefined(isolate), Local<Value>()));
104
 * \endcode
105
 */
106
class V8_EXPORT PropertyDescriptor {
107
 public:
108
  // GenericDescriptor
109
  PropertyDescriptor();
110
111
  // DataDescriptor
112
  explicit PropertyDescriptor(Local<Value> value);
113
114
  // DataDescriptor with writable property
115
  PropertyDescriptor(Local<Value> value, bool writable);
116
117
  // AccessorDescriptor
118
  PropertyDescriptor(Local<Value> get, Local<Value> set);
119
120
  ~PropertyDescriptor();
121
122
  Local<Value> value() const;
123
  bool has_value() const;
124
125
  Local<Value> get() const;
126
  bool has_get() const;
127
  Local<Value> set() const;
128
  bool has_set() const;
129
130
  void set_enumerable(bool enumerable);
131
  bool enumerable() const;
132
  bool has_enumerable() const;
133
134
  void set_configurable(bool configurable);
135
  bool configurable() const;
136
  bool has_configurable() const;
137
138
  bool writable() const;
139
  bool has_writable() const;
140
141
  struct PrivateData;
142
0
  PrivateData* get_private() const { return private_; }
143
144
  PropertyDescriptor(const PropertyDescriptor&) = delete;
145
  void operator=(const PropertyDescriptor&) = delete;
146
147
 private:
148
  PrivateData* private_;
149
};
150
151
/**
152
 * PropertyAttribute.
153
 */
154
enum PropertyAttribute {
155
  /** None. **/
156
  None = 0,
157
  /** ReadOnly, i.e., not writable. **/
158
  ReadOnly = 1 << 0,
159
  /** DontEnum, i.e., not enumerable. **/
160
  DontEnum = 1 << 1,
161
  /** DontDelete, i.e., not configurable. **/
162
  DontDelete = 1 << 2
163
};
164
165
/**
166
 * Accessor[Getter|Setter] are used as callback functions when setting|getting
167
 * a particular data property. See Object::SetNativeDataProperty and
168
 * ObjectTemplate::SetNativeDataProperty methods.
169
 */
170
using AccessorNameGetterCallback =
171
    void (*)(Local<Name> property, const PropertyCallbackInfo<Value>& info);
172
173
using AccessorNameSetterCallback =
174
    void (*)(Local<Name> property, Local<Value> value,
175
             const PropertyCallbackInfo<void>& info);
176
177
/**
178
 * Access control specifications.
179
 *
180
 * Some accessors should be accessible across contexts. These
181
 * accessors have an explicit access control parameter which specifies
182
 * the kind of cross-context access that should be allowed.
183
 *
184
 */
185
enum V8_DEPRECATED(
186
    "This enum is no longer used and will be removed in V8 14.3.")
187
    AccessControl {
188
      DEFAULT V8_ENUM_DEPRECATED("not used") = 0,
189
    };
190
191
/**
192
 * Property filter bits. They can be or'ed to build a composite filter.
193
 */
194
enum PropertyFilter {
195
  ALL_PROPERTIES = 0,
196
  ONLY_WRITABLE = 1,
197
  ONLY_ENUMERABLE = 2,
198
  ONLY_CONFIGURABLE = 4,
199
  SKIP_STRINGS = 8,
200
  SKIP_SYMBOLS = 16
201
};
202
203
/**
204
 * Options for marking whether callbacks may trigger JS-observable side effects.
205
 * Side-effect-free callbacks are allowlisted during debug evaluation with
206
 * throwOnSideEffect. It applies when calling a Function, FunctionTemplate,
207
 * or an Accessor callback. For Interceptors, please see
208
 * PropertyHandlerFlags's kHasNoSideEffect.
209
 * Callbacks that only cause side effects to the receiver are allowlisted if
210
 * invoked on receiver objects that are created within the same debug-evaluate
211
 * call, as these objects are temporary and the side effect does not escape.
212
 */
213
enum class SideEffectType {
214
  kHasSideEffect,
215
  kHasNoSideEffect,
216
  kHasSideEffectToReceiver
217
};
218
219
/**
220
 * Keys/Properties filter enums:
221
 *
222
 * KeyCollectionMode limits the range of collected properties. kOwnOnly limits
223
 * the collected properties to the given Object only. kIncludesPrototypes will
224
 * include all keys of the objects's prototype chain as well.
225
 */
226
enum class KeyCollectionMode { kOwnOnly, kIncludePrototypes };
227
228
/**
229
 * kIncludesIndices allows for integer indices to be collected, while
230
 * kSkipIndices will exclude integer indices from being collected.
231
 */
232
enum class IndexFilter { kIncludeIndices, kSkipIndices };
233
234
/**
235
 * kConvertToString will convert integer indices to strings.
236
 * kKeepNumbers will return numbers for integer indices.
237
 */
238
enum class KeyConversionMode { kConvertToString, kKeepNumbers, kNoNumbers };
239
240
/**
241
 * Integrity level for objects.
242
 */
243
enum class IntegrityLevel { kFrozen, kSealed };
244
245
/**
246
 * A JavaScript object (ECMA-262, 4.3.3)
247
 */
248
class V8_EXPORT Object : public Value {
249
 public:
250
  /**
251
   * Set only return Just(true) or Empty(), so if it should never fail, use
252
   * result.Check().
253
   */
254
  V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
255
                                        Local<Value> key, Local<Value> value);
256
  V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
257
                                        Local<Value> key, Local<Value> value,
258
                                        MaybeLocal<Object> receiver);
259
260
  V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
261
                                        Local<Value> value);
262
263
  /**
264
   * Implements CreateDataProperty(O, P, V), see
265
   * https://tc39.es/ecma262/#sec-createdataproperty.
266
   *
267
   * Defines a configurable, writable, enumerable property with the given value
268
   * on the object unless the property already exists and is not configurable
269
   * or the object is not extensible.
270
   *
271
   * Returns true on success.
272
   */
273
  V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
274
                                                       Local<Name> key,
275
                                                       Local<Value> value);
276
  V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
277
                                                       uint32_t index,
278
                                                       Local<Value> value);
279
280
  /**
281
   * Implements [[DefineOwnProperty]] for data property case, see
282
   * https://tc39.es/ecma262/#table-essential-internal-methods.
283
   *
284
   * In general, CreateDataProperty will be faster, however, does not allow
285
   * for specifying attributes.
286
   *
287
   * Returns true on success.
288
   */
289
  V8_WARN_UNUSED_RESULT Maybe<bool> DefineOwnProperty(
290
      Local<Context> context, Local<Name> key, Local<Value> value,
291
      PropertyAttribute attributes = None);
292
293
  /**
294
   * Implements Object.defineProperty(O, P, Attributes), see
295
   * https://tc39.es/ecma262/#sec-object.defineproperty.
296
   *
297
   * The defineProperty function is used to add an own property or
298
   * update the attributes of an existing own property of an object.
299
   *
300
   * Both data and accessor descriptors can be used.
301
   *
302
   * In general, CreateDataProperty is faster, however, does not allow
303
   * for specifying attributes or an accessor descriptor.
304
   *
305
   * The PropertyDescriptor can change when redefining a property.
306
   *
307
   * Returns true on success.
308
   */
309
  V8_WARN_UNUSED_RESULT Maybe<bool> DefineProperty(
310
      Local<Context> context, Local<Name> key, PropertyDescriptor& descriptor);
311
312
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
313
                                              Local<Value> key);
314
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
315
                                              Local<Value> key,
316
                                              MaybeLocal<Object> receiver);
317
318
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
319
                                              uint32_t index);
320
321
  /**
322
   * Gets the property attributes of a property which can be None or
323
   * any combination of ReadOnly, DontEnum and DontDelete. Returns
324
   * None when the property doesn't exist.
325
   */
326
  V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetPropertyAttributes(
327
      Local<Context> context, Local<Value> key);
328
329
  /**
330
   * Implements Object.getOwnPropertyDescriptor(O, P), see
331
   * https://tc39.es/ecma262/#sec-object.getownpropertydescriptor.
332
   */
333
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetOwnPropertyDescriptor(
334
      Local<Context> context, Local<Name> key);
335
336
  /**
337
   * Object::Has() calls the abstract operation HasProperty(O, P), see
338
   * https://tc39.es/ecma262/#sec-hasproperty. Has() returns
339
   * true, if the object has the property, either own or on the prototype chain.
340
   * Interceptors, i.e., PropertyQueryCallbacks, are called if present.
341
   *
342
   * Has() has the same side effects as JavaScript's `variable in object`.
343
   * For example, calling Has() on a revoked proxy will throw an exception.
344
   *
345
   * \note Has() converts the key to a name, which possibly calls back into
346
   * JavaScript.
347
   *
348
   * See also v8::Object::HasOwnProperty() and
349
   * v8::Object::HasRealNamedProperty().
350
   */
351
  V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context,
352
                                        Local<Value> key);
353
354
  V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
355
                                           Local<Value> key);
356
357
  V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context, uint32_t index);
358
359
  V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
360
                                           uint32_t index);
361
362
  /**
363
   * Sets an accessor property like Template::SetAccessorProperty, but
364
   * this method sets on this object directly.
365
   */
366
  void SetAccessorProperty(Local<Name> name, Local<Function> getter,
367
                           Local<Function> setter = Local<Function>(),
368
                           PropertyAttribute attributes = None);
369
370
  /**
371
   * Sets a native data property like Template::SetNativeDataProperty, but
372
   * this method sets on this object directly.
373
   */
374
  V8_WARN_UNUSED_RESULT Maybe<bool> SetNativeDataProperty(
375
      Local<Context> context, Local<Name> name,
376
      AccessorNameGetterCallback getter,
377
      AccessorNameSetterCallback setter = nullptr,
378
      Local<Value> data = Local<Value>(), PropertyAttribute attributes = None,
379
      SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
380
      SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
381
382
  /**
383
   * Attempts to create a property with the given name which behaves like a data
384
   * property, except that the provided getter is invoked (and provided with the
385
   * data value) to supply its value the first time it is read. After the
386
   * property is accessed once, it is replaced with an ordinary data property.
387
   *
388
   * Analogous to Template::SetLazyDataProperty.
389
   */
390
  V8_WARN_UNUSED_RESULT Maybe<bool> SetLazyDataProperty(
391
      Local<Context> context, Local<Name> name,
392
      AccessorNameGetterCallback getter, Local<Value> data = Local<Value>(),
393
      PropertyAttribute attributes = None,
394
      SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
395
      SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
396
397
  /**
398
   * Functionality for private properties.
399
   * This is an experimental feature, use at your own risk.
400
   * Note: Private properties are not inherited. Do not rely on this, since it
401
   * may change.
402
   */
403
  Maybe<bool> HasPrivate(Local<Context> context, Local<Private> key);
404
  Maybe<bool> SetPrivate(Local<Context> context, Local<Private> key,
405
                         Local<Value> value);
406
  Maybe<bool> DeletePrivate(Local<Context> context, Local<Private> key);
407
  MaybeLocal<Value> GetPrivate(Local<Context> context, Local<Private> key);
408
409
  /**
410
   * Returns an array containing the names of the enumerable properties
411
   * of this object, including properties from prototype objects.  The
412
   * array returned by this method contains the same values as would
413
   * be enumerated by a for-in statement over this object.
414
   */
415
  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
416
      Local<Context> context);
417
  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
418
      Local<Context> context, KeyCollectionMode mode,
419
      PropertyFilter property_filter, IndexFilter index_filter,
420
      KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
421
422
  /**
423
   * This function has the same functionality as GetPropertyNames but
424
   * the returned array doesn't contain the names of properties from
425
   * prototype objects.
426
   */
427
  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
428
      Local<Context> context);
429
430
  /**
431
   * Returns an array containing the names of the filtered properties
432
   * of this object, including properties from prototype objects.  The
433
   * array returned by this method contains the same values as would
434
   * be enumerated by a for-in statement over this object.
435
   */
436
  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
437
      Local<Context> context, PropertyFilter filter,
438
      KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
439
440
  /**
441
   * Get the prototype object (same as calling Object.getPrototypeOf(..)).
442
   * This does not consult the security handler.
443
   * TODO(http://crbug.com/333672197): rename back to GetPrototype().
444
   */
445
  Local<Value> GetPrototypeV2();
446
447
  /**
448
   * Set the prototype object (same as calling Object.setPrototypeOf(..)).
449
   * This does not consult the security handler.
450
   * TODO(http://crbug.com/333672197): rename back to SetPrototype().
451
   */
452
  V8_WARN_UNUSED_RESULT Maybe<bool> SetPrototypeV2(Local<Context> context,
453
                                                   Local<Value> prototype);
454
455
  /**
456
   * Finds an instance of the given function template in the prototype
457
   * chain.
458
   */
459
  Local<Object> FindInstanceInPrototypeChain(Local<FunctionTemplate> tmpl);
460
461
  /**
462
   * Call builtin Object.prototype.toString on this object.
463
   * This is different from Value::ToString() that may call
464
   * user-defined toString function. This one does not.
465
   */
466
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
467
      Local<Context> context);
468
469
  /**
470
   * Returns the name of the function invoked as a constructor for this object.
471
   */
472
  Local<String> GetConstructorName();
473
474
  /**
475
   * Sets the integrity level of the object.
476
   */
477
  Maybe<bool> SetIntegrityLevel(Local<Context> context, IntegrityLevel level);
478
479
  /** Gets the number of internal fields for this Object. */
480
  int InternalFieldCount() const;
481
482
  /** Same as above, but works for PersistentBase. */
483
  V8_INLINE static int InternalFieldCount(
484
0
      const PersistentBase<Object>& object) {
485
0
    return object.template value<Object>()->InternalFieldCount();
486
0
  }
487
488
  /** Same as above, but works for BasicTracedReference. */
489
  V8_INLINE static int InternalFieldCount(
490
0
      const BasicTracedReference<Object>& object) {
491
0
    return object.template value<Object>()->InternalFieldCount();
492
0
  }
493
494
  /**
495
   * Gets the data from an internal field.
496
   * To cast the return value into v8::Value subtypes, it needs to be
497
   * casted to a v8::Value first. For example, to cast it into v8::External:
498
   *
499
   * object->GetInternalField(index).As<v8::Value>().As<v8::External>();
500
   *
501
   * The embedder should make sure that the internal field being retrieved
502
   * using this method has already been set with SetInternalField() before.
503
   **/
504
  V8_INLINE Local<Data> GetInternalField(int index);
505
506
  /** Sets the data in an internal field. */
507
  void SetInternalField(int index, Local<Data> data);
508
509
  /**
510
   * Gets a 2-byte-aligned native pointer from an internal field. This field
511
   * must have been set by SetAlignedPointerInInternalField, everything else
512
   * leads to undefined behavior.
513
   */
514
  V8_INLINE void* GetAlignedPointerFromInternalField(int index,
515
                                                     EmbedderDataTypeTag tag);
516
  V8_INLINE void* GetAlignedPointerFromInternalField(v8::Isolate* isolate,
517
                                                     int index,
518
                                                     EmbedderDataTypeTag tag);
519
520
  V8_DEPRECATE_SOON(
521
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
522
      "parameter instead.")
523
0
  V8_INLINE void* GetAlignedPointerFromInternalField(int index) {
524
0
    return GetAlignedPointerFromInternalField(index,
525
0
                                              kEmbedderDataTypeTagDefault);
526
0
  }
527
528
  V8_DEPRECATE_SOON(
529
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
530
      "parameter instead.")
531
  V8_INLINE void* GetAlignedPointerFromInternalField(v8::Isolate* isolate,
532
0
                                                     int index) {
533
0
    return GetAlignedPointerFromInternalField(isolate, index,
534
0
                                              kEmbedderDataTypeTagDefault);
535
0
  }
536
537
  /** Same as above, but works for PersistentBase. */
538
  V8_INLINE static void* GetAlignedPointerFromInternalField(
539
      const PersistentBase<Object>& object, int index,
540
0
      EmbedderDataTypeTag tag) {
541
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
542
0
        index, tag);
543
0
  }
544
545
  V8_DEPRECATE_SOON(
546
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
547
      "parameter instead.")
548
  V8_INLINE static void* GetAlignedPointerFromInternalField(
549
0
      const PersistentBase<Object>& object, int index) {
550
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
551
0
        index);
552
0
  }
553
554
  /** Same as above, but works for TracedReference. */
555
  V8_INLINE static void* GetAlignedPointerFromInternalField(
556
      const BasicTracedReference<Object>& object, int index,
557
0
      EmbedderDataTypeTag tag) {
558
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
559
0
        index, tag);
560
0
  }
561
562
  V8_DEPRECATE_SOON(
563
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
564
      "parameter instead.")
565
  V8_INLINE static void* GetAlignedPointerFromInternalField(
566
0
      const BasicTracedReference<Object>& object, int index) {
567
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
568
0
        index);
569
0
  }
570
571
  /**
572
   * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
573
   * a field, GetAlignedPointerFromInternalField must be used, everything else
574
   * leads to undefined behavior.
575
   */
576
  void SetAlignedPointerInInternalField(int index, void* value,
577
                                        EmbedderDataTypeTag tag);
578
579
  V8_DEPRECATE_SOON(
580
      "Use SetAlignedPointerInInternalField with EmbedderDataTypeTag parameter "
581
      "instead.")
582
0
  void SetAlignedPointerInInternalField(int index, void* value) {
583
0
    SetAlignedPointerInInternalField(index, value, kEmbedderDataTypeTagDefault);
584
0
  }
585
586
  V8_DEPRECATE_SOON(
587
      "Use SetAlignedPointerInInternalField with EmbedderDataTypeTag "
588
      "parameter instead.")
589
  void SetAlignedPointerInInternalFields(int argc, int indices[],
590
                                         void* values[]);
591
592
  // Type information for a Wrappable object that got wrapped with
593
  // `v8::Object::Wrap()`.
594
  struct WrapperTypeInfo {
595
    const int16_t type_id;
596
  };
597
598
  // v8::Object::Wrappable serves as the base class for all C++ objects that can
599
  // be wrapped by a JavaScript object using `v8::Object::Wrap()`.
600
  //
601
  // Note that v8::Object::Wrappable` inherits from `NameProvider` and provides
602
  // `GetWrapperTypeInfo` to allow subclasses to have smaller object sizes.
603
  class Wrappable : public cppgc::GarbageCollected<Wrappable>,
604
                    public cppgc::NameProvider {
605
   public:
606
0
    virtual const WrapperTypeInfo* GetWrapperTypeInfo() const {
607
0
      return nullptr;
608
0
    }
609
610
0
    const char* GetHumanReadableName() const override { return "internal"; }
611
612
0
    virtual void Trace(cppgc::Visitor* visitor) const {}
613
  };
614
615
  /**
616
   * Unwraps a JS wrapper object.
617
   *
618
   * \param tag The tag for retrieving the wrappable instance. Must match the
619
   * tag that has been used for a previous `Wrap()` operation.
620
   * \param isolate The Isolate for the `wrapper` object.
621
   * \param wrapper The JS wrapper object that should be unwrapped.
622
   * \returns the C++ wrappable instance, or nullptr if the JS object has never
623
   * been wrapped.
624
   */
625
  template <CppHeapPointerTag tag, typename T = void>
626
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
627
                             const v8::Local<v8::Object>& wrapper);
628
  template <CppHeapPointerTag tag, typename T = void>
629
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
630
                             const PersistentBase<Object>& wrapper);
631
  template <CppHeapPointerTag tag, typename T = void>
632
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
633
                             const BasicTracedReference<Object>& wrapper);
634
635
  template <typename T = void>
636
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
637
                             const v8::Local<v8::Object>& wrapper,
638
                             CppHeapPointerTagRange tag_range);
639
  template <typename T = void>
640
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
641
                             const PersistentBase<Object>& wrapper,
642
                             CppHeapPointerTagRange tag_range);
643
  template <typename T = void>
644
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
645
                             const BasicTracedReference<Object>& wrapper,
646
                             CppHeapPointerTagRange tag_range);
647
648
  /**
649
   * Wraps a JS wrapper with a C++ instance.
650
   *
651
   * \param tag The pointer tag that should be used for storing this object.
652
   * Future `Unwrap()` operations must provide a matching tag.
653
   * \param isolate The Isolate for the `wrapper` object.
654
   * \param wrapper The JS wrapper object.
655
   * \param wrappable The C++ object instance that is wrapped by the JS object.
656
   */
657
  template <CppHeapPointerTag tag>
658
  static V8_INLINE void Wrap(v8::Isolate* isolate,
659
                             const v8::Local<v8::Object>& wrapper,
660
                             Wrappable* wrappable);
661
  template <CppHeapPointerTag tag>
662
  static V8_INLINE void Wrap(v8::Isolate* isolate,
663
                             const PersistentBase<Object>& wrapper,
664
                             Wrappable* wrappable);
665
  template <CppHeapPointerTag tag>
666
  static V8_INLINE void Wrap(v8::Isolate* isolate,
667
                             const BasicTracedReference<Object>& wrapper,
668
                             Wrappable* wrappable);
669
  static V8_INLINE void Wrap(v8::Isolate* isolate,
670
                             const v8::Local<v8::Object>& wrapper,
671
                             Wrappable* wrappable, CppHeapPointerTag tag);
672
  static V8_INLINE void Wrap(v8::Isolate* isolate,
673
                             const PersistentBase<Object>& wrapper,
674
                             Wrappable* wrappable, CppHeapPointerTag tag);
675
  static V8_INLINE void Wrap(v8::Isolate* isolate,
676
                             const BasicTracedReference<Object>& wrapper,
677
                             Wrappable* wrappable, CppHeapPointerTag tag);
678
679
  // Version of Wrap() function for v8::Context::Global() objects.
680
  // Unlike the functions above it wraps both JSGlobalProxy and its hidden
681
  // prototype (JSGlobalObject or remote object).
682
  static void WrapGlobal(v8::Isolate* isolate,
683
                         const v8::Local<v8::Object>& wrapper,
684
                         Wrappable* wrappable, CppHeapPointerTag tag);
685
686
  // Checks that wrappables set on JSGlobalProxy and its hidden prototype are
687
  // the same.
688
  static bool CheckGlobalWrappable(v8::Isolate* isolate,
689
                                   const v8::Local<v8::Object>& wrapper,
690
                                   CppHeapPointerTagRange tag_range);
691
692
  /**
693
   * HasOwnProperty() is like JavaScript's
694
   * Object.prototype.hasOwnProperty().
695
   *
696
   * See also v8::Object::Has() and v8::Object::HasRealNamedProperty().
697
   */
698
  V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
699
                                                   Local<Name> key);
700
  V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
701
                                                   uint32_t index);
702
  /**
703
   * Use HasRealNamedProperty() if you want to check if an object has an own
704
   * property without causing side effects, i.e., without calling interceptors.
705
   *
706
   * This function is similar to v8::Object::HasOwnProperty(), but it does not
707
   * call interceptors.
708
   *
709
   * \note Consider using non-masking interceptors, i.e., the interceptors are
710
   * not called if the receiver has the real named property. See
711
   * `v8::PropertyHandlerFlags::kNonMasking`.
712
   *
713
   * See also v8::Object::Has().
714
   */
715
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
716
                                                         Local<Name> key);
717
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealIndexedProperty(
718
      Local<Context> context, uint32_t index);
719
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedCallbackProperty(
720
      Local<Context> context, Local<Name> key);
721
722
  /**
723
   * If result.IsEmpty() no real property was located in the prototype chain.
724
   * This means interceptors in the prototype chain are not called.
725
   */
726
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedPropertyInPrototypeChain(
727
      Local<Context> context, Local<Name> key);
728
729
  /**
730
   * Gets the property attributes of a real property in the prototype chain,
731
   * which can be None or any combination of ReadOnly, DontEnum and DontDelete.
732
   * Interceptors in the prototype chain are not called.
733
   */
734
  V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute>
735
  GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,
736
                                                 Local<Name> key);
737
738
  /**
739
   * If result.IsEmpty() no real property was located on the object or
740
   * in the prototype chain.
741
   * This means interceptors in the prototype chain are not called.
742
   */
743
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedProperty(
744
      Local<Context> context, Local<Name> key);
745
746
  /**
747
   * Gets the property attributes of a real property which can be
748
   * None or any combination of ReadOnly, DontEnum and DontDelete.
749
   * Interceptors in the prototype chain are not called.
750
   */
751
  V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetRealNamedPropertyAttributes(
752
      Local<Context> context, Local<Name> key);
753
754
  /** Tests for a named lookup interceptor.*/
755
  bool HasNamedLookupInterceptor() const;
756
757
  /** Tests for an index lookup interceptor.*/
758
  bool HasIndexedLookupInterceptor() const;
759
760
  /**
761
   * Returns the identity hash for this object. The current implementation
762
   * uses a hidden property on the object to store the identity hash.
763
   *
764
   * The return value will never be 0. Also, it is not guaranteed to be
765
   * unique.
766
   */
767
  int GetIdentityHash();
768
769
  /**
770
   * Clone this object with a fast but shallow copy. Values will point to the
771
   * same values as the original object.
772
   *
773
   * Prefer using version with Isolate parameter.
774
   */
775
  Local<Object> Clone(v8::Isolate* isolate);
776
  Local<Object> Clone();
777
778
  /**
779
   * Returns the context in which the object was created.
780
   *
781
   * Prefer using version with Isolate parameter.
782
   */
783
  MaybeLocal<Context> GetCreationContext(v8::Isolate* isolate);
784
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
785
  MaybeLocal<Context> GetCreationContext();
786
787
  /**
788
   * Shortcut for GetCreationContext(...).ToLocalChecked().
789
   *
790
   * Prefer using version with Isolate parameter.
791
   **/
792
  Local<Context> GetCreationContextChecked(v8::Isolate* isolate);
793
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
794
  Local<Context> GetCreationContextChecked();
795
796
  /** Same as above, but works for Persistents */
797
  V8_INLINE static MaybeLocal<Context> GetCreationContext(
798
0
      v8::Isolate* isolate, const PersistentBase<Object>& object) {
799
0
    return object.template value<Object>()->GetCreationContext(isolate);
800
0
  }
801
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
802
  V8_INLINE static MaybeLocal<Context> GetCreationContext(
803
      const PersistentBase<Object>& object);
804
805
  /**
806
   * Gets the context in which the object was created (see GetCreationContext())
807
   * and if it's available reads respective embedder field value.
808
   * If the context can't be obtained nullptr is returned.
809
   * Basically it's a shortcut for
810
   *   obj->GetCreationContext().GetAlignedPointerFromEmbedderData(index)
811
   * which doesn't create a handle for Context object on the way and doesn't
812
   * try to expand the embedder data attached to the context.
813
   * In case the Local<Context> is already available because of other reasons,
814
   * it's fine to keep using Context::GetAlignedPointerFromEmbedderData().
815
   *
816
   * Prefer using version with Isolate parameter if you have an Isolate,
817
   * otherwise use the other one.
818
   */
819
  void* GetAlignedPointerFromEmbedderDataInCreationContext(
820
      v8::Isolate* isolate, int index, EmbedderDataTypeTag tag);
821
  void* GetAlignedPointerFromEmbedderDataInCreationContext(
822
      int index, EmbedderDataTypeTag tag);
823
824
  V8_DEPRECATE_SOON(
825
      "Use GetAlignedPointerFromEmbedderDataInCreationContext with "
826
      "EmbedderDataTypeTag parameter instead.")
827
  void* GetAlignedPointerFromEmbedderDataInCreationContext(v8::Isolate* isolate,
828
0
                                                           int index) {
829
0
    return GetAlignedPointerFromEmbedderDataInCreationContext(
830
0
        isolate, index, kEmbedderDataTypeTagDefault);
831
0
  }
832
833
  V8_DEPRECATE_SOON(
834
      "Use GetAlignedPointerFromEmbedderDataInCreationContext with "
835
      "EmbedderDataTypeTag parameter instead.")
836
0
  void* GetAlignedPointerFromEmbedderDataInCreationContext(int index) {
837
0
    return GetAlignedPointerFromEmbedderDataInCreationContext(
838
0
        index, kEmbedderDataTypeTagDefault);
839
0
  }
840
841
  /**
842
   * Checks whether a callback is set by the
843
   * ObjectTemplate::SetCallAsFunctionHandler method.
844
   * When an Object is callable this method returns true.
845
   */
846
  bool IsCallable() const;
847
848
  /**
849
   * True if this object is a constructor.
850
   */
851
  bool IsConstructor() const;
852
853
  /**
854
   * Returns true if this object can be generally used to wrap object objects.
855
   * This means that the object either follows the convention of using embedder
856
   * fields to denote type/instance pointers or is using the Wrap()/Unwrap()
857
   * APIs for the same purpose. Returns false otherwise.
858
   *
859
   * Note that there may be other objects that use embedder fields but are not
860
   * used as API wrapper objects. E.g., v8::Promise may in certain configuration
861
   * use embedder fields but promises are not generally supported as API
862
   * wrappers. The method will return false in those cases.
863
   */
864
  bool IsApiWrapper() const;
865
866
  /**
867
   * True if this object was created from an object template which was marked
868
   * as undetectable. See v8::ObjectTemplate::MarkAsUndetectable for more
869
   * information.
870
   */
871
  bool IsUndetectable() const;
872
873
  /**
874
   * Call an Object as a function if a callback is set by the
875
   * ObjectTemplate::SetCallAsFunctionHandler method.
876
   */
877
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsFunction(Local<Context> context,
878
                                                         Local<Value> recv,
879
                                                         int argc,
880
                                                         Local<Value> argv[]);
881
882
  /**
883
   * Call an Object as a constructor if a callback is set by the
884
   * ObjectTemplate::SetCallAsFunctionHandler method.
885
   * Note: This method behaves like the Function::NewInstance method.
886
   */
887
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsConstructor(
888
      Local<Context> context, int argc, Local<Value> argv[]);
889
890
  /**
891
   * If this object is a Set, Map, WeakSet or WeakMap, this returns a
892
   * representation of the elements of this object as an array.
893
   * If this object is a SetIterator or MapIterator, this returns all
894
   * elements of the underlying collection, starting at the iterator's current
895
   * position.
896
   * For other types, this will return an empty MaybeLocal<Array> (without
897
   * scheduling an exception).
898
   */
899
  MaybeLocal<Array> PreviewEntries(bool* is_key_value);
900
901
  static Local<Object> New(Isolate* isolate);
902
903
  /**
904
   * Creates a JavaScript object with the given properties, and
905
   * a the given prototype_or_null (which can be any JavaScript
906
   * value, and if it's null, the newly created object won't have
907
   * a prototype at all). This is similar to Object.create().
908
   * All properties will be created as enumerable, configurable
909
   * and writable properties.
910
   */
911
  static Local<Object> New(Isolate* isolate, Local<Value> prototype_or_null,
912
                           Local<Name>* names, Local<Value>* values,
913
                           size_t length);
914
915
  V8_INLINE static Object* Cast(Value* obj);
916
917
  /**
918
   * Support for TC39 "dynamic code brand checks" proposal.
919
   *
920
   * This API allows to query whether an object was constructed from a
921
   * "code like" ObjectTemplate.
922
   *
923
   * See also: v8::ObjectTemplate::SetCodeLike
924
   */
925
  bool IsCodeLike(Isolate* isolate) const;
926
927
 private:
928
  static void* Unwrap(v8::Isolate* isolate, internal::Address wrapper_obj,
929
                      CppHeapPointerTagRange tag_range);
930
  static void Wrap(v8::Isolate* isolate, internal::Address wrapper_obj,
931
                   CppHeapPointerTag tag, void* wrappable);
932
933
  Object();
934
  static void CheckCast(Value* obj);
935
  Local<Data> SlowGetInternalField(int index);
936
  void* SlowGetAlignedPointerFromInternalField(int index,
937
                                               EmbedderDataTypeTag tag);
938
  void* SlowGetAlignedPointerFromInternalField(v8::Isolate* isolate, int index,
939
                                               EmbedderDataTypeTag tag);
940
};
941
942
// --- Implementation ---
943
944
0
Local<Data> Object::GetInternalField(int index) {
945
0
#ifndef V8_ENABLE_CHECKS
946
0
  using A = internal::Address;
947
0
  using I = internal::Internals;
948
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
949
  // Fast path: If the object is a plain JSObject, which is the common case, we
950
  // know where to find the internal fields and can return the value directly.
951
0
  int instance_type = I::GetInstanceType(obj);
952
0
  if (I::CanHaveInternalField(instance_type)) {
953
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
954
0
                 (I::kEmbedderDataSlotSize * index);
955
0
    A value = I::ReadRawField<A>(obj, offset);
956
#ifdef V8_COMPRESS_POINTERS
957
    // We read the full pointer value and then decompress it in order to avoid
958
    // dealing with potential endianness issues.
959
    value = I::DecompressTaggedField(obj, static_cast<uint32_t>(value));
960
#endif
961
962
0
    auto* isolate = I::GetCurrentIsolate();
963
0
    return Local<Data>::New(isolate, value);
964
0
  }
965
0
#endif
966
0
  return SlowGetInternalField(index);
967
0
}
968
969
void* Object::GetAlignedPointerFromInternalField(v8::Isolate* isolate,
970
                                                 int index,
971
0
                                                 EmbedderDataTypeTag tag) {
972
0
#if !defined(V8_ENABLE_CHECKS)
973
0
  using A = internal::Address;
974
0
  using I = internal::Internals;
975
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
976
0
  // Fast path: If the object is a plain JSObject, which is the common case, we
977
0
  // know where to find the internal fields and can return the value directly.
978
0
  auto instance_type = I::GetInstanceType(obj);
979
0
  if (V8_LIKELY(I::CanHaveInternalField(instance_type))) {
980
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
981
0
                 (I::kEmbedderDataSlotSize * index) +
982
0
                 I::kEmbedderDataSlotExternalPointerOffset;
983
0
    A value = I::ReadExternalPointerField(isolate, obj, offset,
984
0
                                          ToExternalPointerTag(tag));
985
0
    return reinterpret_cast<void*>(value);
986
0
  }
987
0
#endif
988
0
  return SlowGetAlignedPointerFromInternalField(isolate, index, tag);
989
0
}
990
991
void* Object::GetAlignedPointerFromInternalField(int index,
992
0
                                                 EmbedderDataTypeTag tag) {
993
0
#if !defined(V8_ENABLE_CHECKS)
994
0
  using A = internal::Address;
995
0
  using I = internal::Internals;
996
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
997
  // Fast path: If the object is a plain JSObject, which is the common case, we
998
  // know where to find the internal fields and can return the value directly.
999
0
  auto instance_type = I::GetInstanceType(obj);
1000
0
  if (V8_LIKELY(I::CanHaveInternalField(instance_type))) {
1001
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
1002
0
                 (I::kEmbedderDataSlotSize * index) +
1003
0
                 I::kEmbedderDataSlotExternalPointerOffset;
1004
0
    Isolate* isolate = I::GetCurrentIsolateForSandbox();
1005
0
    A value = I::ReadExternalPointerField(isolate, obj, offset,
1006
0
                                          ToExternalPointerTag(tag));
1007
0
    return reinterpret_cast<void*>(value);
1008
0
  }
1009
0
#endif
1010
0
  return SlowGetAlignedPointerFromInternalField(index, tag);
1011
0
}
1012
1013
// static
1014
template <CppHeapPointerTag tag, typename T>
1015
T* Object::Unwrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper) {
1016
  CppHeapPointerTagRange tag_range(tag, tag);
1017
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1018
#if !defined(V8_ENABLE_CHECKS)
1019
  return internal::ReadCppHeapPointerField<T>(
1020
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1021
#else   // defined(V8_ENABLE_CHECKS)
1022
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1023
#endif  // defined(V8_ENABLE_CHECKS)
1024
}
1025
1026
// static
1027
template <CppHeapPointerTag tag, typename T>
1028
T* Object::Unwrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper) {
1029
  CppHeapPointerTagRange tag_range(tag, tag);
1030
  auto obj =
1031
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1032
#if !defined(V8_ENABLE_CHECKS)
1033
  return internal::ReadCppHeapPointerField<T>(
1034
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1035
#else   // defined(V8_ENABLE_CHECKS)
1036
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1037
#endif  // defined(V8_ENABLE_CHECKS)
1038
}
1039
1040
// static
1041
template <CppHeapPointerTag tag, typename T>
1042
T* Object::Unwrap(v8::Isolate* isolate,
1043
                  const BasicTracedReference<Object>& wrapper) {
1044
  CppHeapPointerTagRange tag_range(tag, tag);
1045
  auto obj =
1046
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1047
#if !defined(V8_ENABLE_CHECKS)
1048
  return internal::ReadCppHeapPointerField<T>(
1049
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1050
#else   // defined(V8_ENABLE_CHECKS)
1051
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1052
#endif  // defined(V8_ENABLE_CHECKS)
1053
}
1054
1055
// static
1056
template <typename T>
1057
T* Object::Unwrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1058
                  CppHeapPointerTagRange tag_range) {
1059
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1060
#if !defined(V8_ENABLE_CHECKS)
1061
  return internal::ReadCppHeapPointerField<T>(
1062
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1063
#else   // defined(V8_ENABLE_CHECKS)
1064
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1065
#endif  // defined(V8_ENABLE_CHECKS)
1066
}
1067
1068
// static
1069
template <typename T>
1070
T* Object::Unwrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1071
                  CppHeapPointerTagRange tag_range) {
1072
  auto obj =
1073
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1074
#if !defined(V8_ENABLE_CHECKS)
1075
  return internal::ReadCppHeapPointerField<T>(
1076
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1077
#else   // defined(V8_ENABLE_CHECKS)
1078
1079
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1080
#endif  // defined(V8_ENABLE_CHECKS)
1081
}
1082
1083
// static
1084
template <typename T>
1085
T* Object::Unwrap(v8::Isolate* isolate,
1086
                  const BasicTracedReference<Object>& wrapper,
1087
                  CppHeapPointerTagRange tag_range) {
1088
  auto obj =
1089
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1090
#if !defined(V8_ENABLE_CHECKS)
1091
  return internal::ReadCppHeapPointerField<T>(
1092
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1093
#else   // defined(V8_ENABLE_CHECKS)
1094
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1095
#endif  // defined(V8_ENABLE_CHECKS)
1096
}
1097
1098
// static
1099
template <CppHeapPointerTag tag>
1100
void Object::Wrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1101
0
                  v8::Object::Wrappable* wrappable) {
1102
0
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1103
0
  Wrap(isolate, obj, tag, wrappable);
1104
0
}
1105
1106
// static
1107
template <CppHeapPointerTag tag>
1108
void Object::Wrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1109
                  v8::Object::Wrappable* wrappable) {
1110
  auto obj =
1111
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1112
  Wrap(isolate, obj, tag, wrappable);
1113
}
1114
1115
// static
1116
template <CppHeapPointerTag tag>
1117
void Object::Wrap(v8::Isolate* isolate,
1118
                  const BasicTracedReference<Object>& wrapper,
1119
                  v8::Object::Wrappable* wrappable) {
1120
  auto obj =
1121
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1122
  Wrap(isolate, obj, tag, wrappable);
1123
}
1124
1125
// static
1126
void Object::Wrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1127
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1128
0
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1129
0
  Wrap(isolate, obj, tag, wrappable);
1130
0
}
1131
1132
// static
1133
void Object::Wrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1134
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1135
0
  auto obj =
1136
0
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1137
0
  Wrap(isolate, obj, tag, wrappable);
1138
0
}
1139
1140
// static
1141
void Object::Wrap(v8::Isolate* isolate,
1142
                  const BasicTracedReference<Object>& wrapper,
1143
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1144
0
  auto obj =
1145
0
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1146
0
  Wrap(isolate, obj, tag, wrappable);
1147
0
}
1148
1149
0
Private* Private::Cast(Data* data) {
1150
#ifdef V8_ENABLE_CHECKS
1151
  CheckCast(data);
1152
#endif
1153
0
  return reinterpret_cast<Private*>(data);
1154
0
}
1155
1156
0
Object* Object::Cast(v8::Value* value) {
1157
#ifdef V8_ENABLE_CHECKS
1158
  CheckCast(value);
1159
#endif
1160
0
  return static_cast<Object*>(value);
1161
0
}
1162
1163
}  // namespace v8
1164
1165
#endif  // INCLUDE_V8_OBJECT_H_