Coverage Report

Created: 2025-10-31 09:06

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.  This does not skip objects marked to
442
   * be skipped by __proto__ and it does not consult the security
443
   * handler.
444
   */
445
  V8_DEPRECATED(
446
      "V8 will stop providing access to hidden prototype (i.e. "
447
      "JSGlobalObject). Use GetPrototypeV2() instead. "
448
      "See http://crbug.com/333672197.")
449
  Local<Value> GetPrototype();
450
451
  /**
452
   * Get the prototype object (same as calling Object.getPrototypeOf(..)).
453
   * This does not consult the security handler.
454
   * TODO(333672197): rename back to GetPrototype() once the old version goes
455
   * through the deprecation process and is removed.
456
   */
457
  Local<Value> GetPrototypeV2();
458
459
  /**
460
   * Set the prototype object (same as calling Object.setPrototypeOf(..)).
461
   * This does not consult the security handler.
462
   * TODO(http://crbug.com/333672197): rename back to SetPrototype().
463
   */
464
  V8_WARN_UNUSED_RESULT Maybe<bool> SetPrototypeV2(Local<Context> context,
465
                                                   Local<Value> prototype);
466
467
  /**
468
   * Finds an instance of the given function template in the prototype
469
   * chain.
470
   */
471
  Local<Object> FindInstanceInPrototypeChain(Local<FunctionTemplate> tmpl);
472
473
  /**
474
   * Call builtin Object.prototype.toString on this object.
475
   * This is different from Value::ToString() that may call
476
   * user-defined toString function. This one does not.
477
   */
478
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
479
      Local<Context> context);
480
481
  /**
482
   * Returns the name of the function invoked as a constructor for this object.
483
   */
484
  Local<String> GetConstructorName();
485
486
  /**
487
   * Sets the integrity level of the object.
488
   */
489
  Maybe<bool> SetIntegrityLevel(Local<Context> context, IntegrityLevel level);
490
491
  /** Gets the number of internal fields for this Object. */
492
  int InternalFieldCount() const;
493
494
  /** Same as above, but works for PersistentBase. */
495
  V8_INLINE static int InternalFieldCount(
496
0
      const PersistentBase<Object>& object) {
497
0
    return object.template value<Object>()->InternalFieldCount();
498
0
  }
499
500
  /** Same as above, but works for BasicTracedReference. */
501
  V8_INLINE static int InternalFieldCount(
502
0
      const BasicTracedReference<Object>& object) {
503
0
    return object.template value<Object>()->InternalFieldCount();
504
0
  }
505
506
  /**
507
   * Gets the data from an internal field.
508
   * To cast the return value into v8::Value subtypes, it needs to be
509
   * casted to a v8::Value first. For example, to cast it into v8::External:
510
   *
511
   * object->GetInternalField(index).As<v8::Value>().As<v8::External>();
512
   *
513
   * The embedder should make sure that the internal field being retrieved
514
   * using this method has already been set with SetInternalField() before.
515
   **/
516
  V8_INLINE Local<Data> GetInternalField(int index);
517
518
  /** Sets the data in an internal field. */
519
  void SetInternalField(int index, Local<Data> data);
520
521
  /**
522
   * Gets a 2-byte-aligned native pointer from an internal field. This field
523
   * must have been set by SetAlignedPointerInInternalField, everything else
524
   * leads to undefined behavior.
525
   */
526
  V8_INLINE void* GetAlignedPointerFromInternalField(int index,
527
                                                     EmbedderDataTypeTag tag);
528
  V8_INLINE void* GetAlignedPointerFromInternalField(v8::Isolate* isolate,
529
                                                     int index,
530
                                                     EmbedderDataTypeTag tag);
531
532
  V8_DEPRECATE_SOON(
533
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
534
      "parameter instead.")
535
0
  V8_INLINE void* GetAlignedPointerFromInternalField(int index) {
536
0
    return GetAlignedPointerFromInternalField(index,
537
0
                                              kEmbedderDataTypeTagDefault);
538
0
  }
539
540
  V8_DEPRECATE_SOON(
541
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
542
      "parameter instead.")
543
  V8_INLINE void* GetAlignedPointerFromInternalField(v8::Isolate* isolate,
544
0
                                                     int index) {
545
0
    return GetAlignedPointerFromInternalField(isolate, index,
546
0
                                              kEmbedderDataTypeTagDefault);
547
0
  }
548
549
  /** Same as above, but works for PersistentBase. */
550
  V8_INLINE static void* GetAlignedPointerFromInternalField(
551
      const PersistentBase<Object>& object, int index,
552
0
      EmbedderDataTypeTag tag) {
553
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
554
0
        index, tag);
555
0
  }
556
557
  V8_DEPRECATE_SOON(
558
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
559
      "parameter instead.")
560
  V8_INLINE static void* GetAlignedPointerFromInternalField(
561
0
      const PersistentBase<Object>& object, int index) {
562
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
563
0
        index);
564
0
  }
565
566
  /** Same as above, but works for TracedReference. */
567
  V8_INLINE static void* GetAlignedPointerFromInternalField(
568
      const BasicTracedReference<Object>& object, int index,
569
0
      EmbedderDataTypeTag tag) {
570
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
571
0
        index, tag);
572
0
  }
573
574
  V8_DEPRECATE_SOON(
575
      "Use GetAlignedPointerFromInternalField with EmbedderDataTypeTag "
576
      "parameter instead.")
577
  V8_INLINE static void* GetAlignedPointerFromInternalField(
578
0
      const BasicTracedReference<Object>& object, int index) {
579
0
    return object.template value<Object>()->GetAlignedPointerFromInternalField(
580
0
        index);
581
0
  }
582
583
  /**
584
   * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
585
   * a field, GetAlignedPointerFromInternalField must be used, everything else
586
   * leads to undefined behavior.
587
   */
588
  void SetAlignedPointerInInternalField(int index, void* value,
589
                                        EmbedderDataTypeTag tag);
590
591
  V8_DEPRECATE_SOON(
592
      "Use SetAlignedPointerInInternalField with EmbedderDataTypeTag parameter "
593
      "instead.")
594
840
  void SetAlignedPointerInInternalField(int index, void* value) {
595
840
    SetAlignedPointerInInternalField(index, value, kEmbedderDataTypeTagDefault);
596
840
  }
597
598
  V8_DEPRECATE_SOON(
599
      "Use SetAlignedPointerInInternalField with EmbedderDataTypeTag "
600
      "parameter instead.")
601
  void SetAlignedPointerInInternalFields(int argc, int indices[],
602
                                         void* values[]);
603
604
  // Type information for a Wrappable object that got wrapped with
605
  // `v8::Object::Wrap()`.
606
  struct WrapperTypeInfo {
607
    const int16_t type_id;
608
  };
609
610
  // v8::Object::Wrappable serves as the base class for all C++ objects that can
611
  // be wrapped by a JavaScript object using `v8::Object::Wrap()`.
612
  //
613
  // Note that v8::Object::Wrappable` inherits from `NameProvider` and provides
614
  // `GetWrapperTypeInfo` to allow subclasses to have smaller object sizes.
615
  class Wrappable : public cppgc::GarbageCollected<Wrappable>,
616
                    public cppgc::NameProvider {
617
   public:
618
0
    virtual const WrapperTypeInfo* GetWrapperTypeInfo() const {
619
0
      return nullptr;
620
0
    }
621
622
0
    const char* GetHumanReadableName() const override { return "internal"; }
623
624
0
    virtual void Trace(cppgc::Visitor* visitor) const {}
625
  };
626
627
  /**
628
   * Unwraps a JS wrapper object.
629
   *
630
   * \param tag The tag for retrieving the wrappable instance. Must match the
631
   * tag that has been used for a previous `Wrap()` operation.
632
   * \param isolate The Isolate for the `wrapper` object.
633
   * \param wrapper The JS wrapper object that should be unwrapped.
634
   * \returns the C++ wrappable instance, or nullptr if the JS object has never
635
   * been wrapped.
636
   */
637
  template <CppHeapPointerTag tag, typename T = void>
638
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
639
                             const v8::Local<v8::Object>& wrapper);
640
  template <CppHeapPointerTag tag, typename T = void>
641
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
642
                             const PersistentBase<Object>& wrapper);
643
  template <CppHeapPointerTag tag, typename T = void>
644
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
645
                             const BasicTracedReference<Object>& wrapper);
646
647
  template <typename T = void>
648
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
649
                             const v8::Local<v8::Object>& wrapper,
650
                             CppHeapPointerTagRange tag_range);
651
  template <typename T = void>
652
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
653
                             const PersistentBase<Object>& wrapper,
654
                             CppHeapPointerTagRange tag_range);
655
  template <typename T = void>
656
  static V8_INLINE T* Unwrap(v8::Isolate* isolate,
657
                             const BasicTracedReference<Object>& wrapper,
658
                             CppHeapPointerTagRange tag_range);
659
660
  /**
661
   * Wraps a JS wrapper with a C++ instance.
662
   *
663
   * \param tag The pointer tag that should be used for storing this object.
664
   * Future `Unwrap()` operations must provide a matching tag.
665
   * \param isolate The Isolate for the `wrapper` object.
666
   * \param wrapper The JS wrapper object.
667
   * \param wrappable The C++ object instance that is wrapped by the JS object.
668
   */
669
  template <CppHeapPointerTag tag>
670
  static V8_INLINE void Wrap(v8::Isolate* isolate,
671
                             const v8::Local<v8::Object>& wrapper,
672
                             Wrappable* wrappable);
673
  template <CppHeapPointerTag tag>
674
  static V8_INLINE void Wrap(v8::Isolate* isolate,
675
                             const PersistentBase<Object>& wrapper,
676
                             Wrappable* wrappable);
677
  template <CppHeapPointerTag tag>
678
  static V8_INLINE void Wrap(v8::Isolate* isolate,
679
                             const BasicTracedReference<Object>& wrapper,
680
                             Wrappable* wrappable);
681
  static V8_INLINE void Wrap(v8::Isolate* isolate,
682
                             const v8::Local<v8::Object>& wrapper,
683
                             Wrappable* wrappable, CppHeapPointerTag tag);
684
  static V8_INLINE void Wrap(v8::Isolate* isolate,
685
                             const PersistentBase<Object>& wrapper,
686
                             Wrappable* wrappable, CppHeapPointerTag tag);
687
  static V8_INLINE void Wrap(v8::Isolate* isolate,
688
                             const BasicTracedReference<Object>& wrapper,
689
                             Wrappable* wrappable, CppHeapPointerTag tag);
690
691
  // Version of Wrap() function for v8::Context::Global() objects.
692
  // Unlike the functions above it wraps both JSGlobalProxy and its hidden
693
  // prototype (JSGlobalObject or remote object).
694
  static void WrapGlobal(v8::Isolate* isolate,
695
                         const v8::Local<v8::Object>& wrapper,
696
                         Wrappable* wrappable, CppHeapPointerTag tag);
697
698
  // Checks that wrappables set on JSGlobalProxy and its hidden prototype are
699
  // the same.
700
  static bool CheckGlobalWrappable(v8::Isolate* isolate,
701
                                   const v8::Local<v8::Object>& wrapper,
702
                                   CppHeapPointerTagRange tag_range);
703
704
  /**
705
   * HasOwnProperty() is like JavaScript's
706
   * Object.prototype.hasOwnProperty().
707
   *
708
   * See also v8::Object::Has() and v8::Object::HasRealNamedProperty().
709
   */
710
  V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
711
                                                   Local<Name> key);
712
  V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
713
                                                   uint32_t index);
714
  /**
715
   * Use HasRealNamedProperty() if you want to check if an object has an own
716
   * property without causing side effects, i.e., without calling interceptors.
717
   *
718
   * This function is similar to v8::Object::HasOwnProperty(), but it does not
719
   * call interceptors.
720
   *
721
   * \note Consider using non-masking interceptors, i.e., the interceptors are
722
   * not called if the receiver has the real named property. See
723
   * `v8::PropertyHandlerFlags::kNonMasking`.
724
   *
725
   * See also v8::Object::Has().
726
   */
727
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
728
                                                         Local<Name> key);
729
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealIndexedProperty(
730
      Local<Context> context, uint32_t index);
731
  V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedCallbackProperty(
732
      Local<Context> context, Local<Name> key);
733
734
  /**
735
   * If result.IsEmpty() no real property was located in the prototype chain.
736
   * This means interceptors in the prototype chain are not called.
737
   */
738
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedPropertyInPrototypeChain(
739
      Local<Context> context, Local<Name> key);
740
741
  /**
742
   * Gets the property attributes of a real property in the prototype chain,
743
   * which can be None or any combination of ReadOnly, DontEnum and DontDelete.
744
   * Interceptors in the prototype chain are not called.
745
   */
746
  V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute>
747
  GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,
748
                                                 Local<Name> key);
749
750
  /**
751
   * If result.IsEmpty() no real property was located on the object or
752
   * in the prototype chain.
753
   * This means interceptors in the prototype chain are not called.
754
   */
755
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedProperty(
756
      Local<Context> context, Local<Name> key);
757
758
  /**
759
   * Gets the property attributes of a real property which can be
760
   * None or any combination of ReadOnly, DontEnum and DontDelete.
761
   * Interceptors in the prototype chain are not called.
762
   */
763
  V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetRealNamedPropertyAttributes(
764
      Local<Context> context, Local<Name> key);
765
766
  /** Tests for a named lookup interceptor.*/
767
  bool HasNamedLookupInterceptor() const;
768
769
  /** Tests for an index lookup interceptor.*/
770
  bool HasIndexedLookupInterceptor() const;
771
772
  /**
773
   * Returns the identity hash for this object. The current implementation
774
   * uses a hidden property on the object to store the identity hash.
775
   *
776
   * The return value will never be 0. Also, it is not guaranteed to be
777
   * unique.
778
   */
779
  int GetIdentityHash();
780
781
  /**
782
   * Clone this object with a fast but shallow copy. Values will point to the
783
   * same values as the original object.
784
   *
785
   * Prefer using version with Isolate parameter.
786
   */
787
  Local<Object> Clone(v8::Isolate* isolate);
788
  Local<Object> Clone();
789
790
  /**
791
   * Returns the context in which the object was created.
792
   *
793
   * Prefer using version with Isolate parameter.
794
   */
795
  MaybeLocal<Context> GetCreationContext(v8::Isolate* isolate);
796
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
797
  MaybeLocal<Context> GetCreationContext();
798
799
  /**
800
   * Shortcut for GetCreationContext(...).ToLocalChecked().
801
   *
802
   * Prefer using version with Isolate parameter.
803
   **/
804
  Local<Context> GetCreationContextChecked(v8::Isolate* isolate);
805
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
806
  Local<Context> GetCreationContextChecked();
807
808
  /** Same as above, but works for Persistents */
809
  V8_INLINE static MaybeLocal<Context> GetCreationContext(
810
0
      v8::Isolate* isolate, const PersistentBase<Object>& object) {
811
0
    return object.template value<Object>()->GetCreationContext(isolate);
812
0
  }
813
  V8_DEPRECATE_SOON("Use the version with the isolate argument.")
814
  V8_INLINE static MaybeLocal<Context> GetCreationContext(
815
      const PersistentBase<Object>& object);
816
817
  /**
818
   * Gets the context in which the object was created (see GetCreationContext())
819
   * and if it's available reads respective embedder field value.
820
   * If the context can't be obtained nullptr is returned.
821
   * Basically it's a shortcut for
822
   *   obj->GetCreationContext().GetAlignedPointerFromEmbedderData(index)
823
   * which doesn't create a handle for Context object on the way and doesn't
824
   * try to expand the embedder data attached to the context.
825
   * In case the Local<Context> is already available because of other reasons,
826
   * it's fine to keep using Context::GetAlignedPointerFromEmbedderData().
827
   *
828
   * Prefer using version with Isolate parameter if you have an Isolate,
829
   * otherwise use the other one.
830
   */
831
  void* GetAlignedPointerFromEmbedderDataInCreationContext(
832
      v8::Isolate* isolate, int index, EmbedderDataTypeTag tag);
833
  void* GetAlignedPointerFromEmbedderDataInCreationContext(
834
      int index, EmbedderDataTypeTag tag);
835
836
  V8_DEPRECATE_SOON(
837
      "Use GetAlignedPointerFromEmbedderDataInCreationContext with "
838
      "EmbedderDataTypeTag parameter instead.")
839
  void* GetAlignedPointerFromEmbedderDataInCreationContext(v8::Isolate* isolate,
840
0
                                                           int index) {
841
0
    return GetAlignedPointerFromEmbedderDataInCreationContext(
842
0
        isolate, index, kEmbedderDataTypeTagDefault);
843
0
  }
844
845
  V8_DEPRECATE_SOON(
846
      "Use GetAlignedPointerFromEmbedderDataInCreationContext with "
847
      "EmbedderDataTypeTag parameter instead.")
848
0
  void* GetAlignedPointerFromEmbedderDataInCreationContext(int index) {
849
0
    return GetAlignedPointerFromEmbedderDataInCreationContext(
850
0
        index, kEmbedderDataTypeTagDefault);
851
0
  }
852
853
  /**
854
   * Checks whether a callback is set by the
855
   * ObjectTemplate::SetCallAsFunctionHandler method.
856
   * When an Object is callable this method returns true.
857
   */
858
  bool IsCallable() const;
859
860
  /**
861
   * True if this object is a constructor.
862
   */
863
  bool IsConstructor() const;
864
865
  /**
866
   * Returns true if this object can be generally used to wrap object objects.
867
   * This means that the object either follows the convention of using embedder
868
   * fields to denote type/instance pointers or is using the Wrap()/Unwrap()
869
   * APIs for the same purpose. Returns false otherwise.
870
   *
871
   * Note that there may be other objects that use embedder fields but are not
872
   * used as API wrapper objects. E.g., v8::Promise may in certain configuration
873
   * use embedder fields but promises are not generally supported as API
874
   * wrappers. The method will return false in those cases.
875
   */
876
  bool IsApiWrapper() const;
877
878
  /**
879
   * True if this object was created from an object template which was marked
880
   * as undetectable. See v8::ObjectTemplate::MarkAsUndetectable for more
881
   * information.
882
   */
883
  bool IsUndetectable() const;
884
885
  /**
886
   * Call an Object as a function if a callback is set by the
887
   * ObjectTemplate::SetCallAsFunctionHandler method.
888
   */
889
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsFunction(Local<Context> context,
890
                                                         Local<Value> recv,
891
                                                         int argc,
892
                                                         Local<Value> argv[]);
893
894
  /**
895
   * Call an Object as a constructor if a callback is set by the
896
   * ObjectTemplate::SetCallAsFunctionHandler method.
897
   * Note: This method behaves like the Function::NewInstance method.
898
   */
899
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsConstructor(
900
      Local<Context> context, int argc, Local<Value> argv[]);
901
902
  /**
903
   * If this object is a Set, Map, WeakSet or WeakMap, this returns a
904
   * representation of the elements of this object as an array.
905
   * If this object is a SetIterator or MapIterator, this returns all
906
   * elements of the underlying collection, starting at the iterator's current
907
   * position.
908
   * For other types, this will return an empty MaybeLocal<Array> (without
909
   * scheduling an exception).
910
   */
911
  MaybeLocal<Array> PreviewEntries(bool* is_key_value);
912
913
  static Local<Object> New(Isolate* isolate);
914
915
  /**
916
   * Creates a JavaScript object with the given properties, and
917
   * a the given prototype_or_null (which can be any JavaScript
918
   * value, and if it's null, the newly created object won't have
919
   * a prototype at all). This is similar to Object.create().
920
   * All properties will be created as enumerable, configurable
921
   * and writable properties.
922
   */
923
  static Local<Object> New(Isolate* isolate, Local<Value> prototype_or_null,
924
                           Local<Name>* names, Local<Value>* values,
925
                           size_t length);
926
927
  V8_INLINE static Object* Cast(Value* obj);
928
929
  /**
930
   * Support for TC39 "dynamic code brand checks" proposal.
931
   *
932
   * This API allows to query whether an object was constructed from a
933
   * "code like" ObjectTemplate.
934
   *
935
   * See also: v8::ObjectTemplate::SetCodeLike
936
   */
937
  bool IsCodeLike(Isolate* isolate) const;
938
939
 private:
940
  static void* Unwrap(v8::Isolate* isolate, internal::Address wrapper_obj,
941
                      CppHeapPointerTagRange tag_range);
942
  static void Wrap(v8::Isolate* isolate, internal::Address wrapper_obj,
943
                   CppHeapPointerTag tag, void* wrappable);
944
945
  Object();
946
  static void CheckCast(Value* obj);
947
  Local<Data> SlowGetInternalField(int index);
948
  void* SlowGetAlignedPointerFromInternalField(int index,
949
                                               EmbedderDataTypeTag tag);
950
  void* SlowGetAlignedPointerFromInternalField(v8::Isolate* isolate, int index,
951
                                               EmbedderDataTypeTag tag);
952
};
953
954
// --- Implementation ---
955
956
0
Local<Data> Object::GetInternalField(int index) {
957
0
#ifndef V8_ENABLE_CHECKS
958
0
  using A = internal::Address;
959
0
  using I = internal::Internals;
960
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
961
  // Fast path: If the object is a plain JSObject, which is the common case, we
962
  // know where to find the internal fields and can return the value directly.
963
0
  int instance_type = I::GetInstanceType(obj);
964
0
  if (I::CanHaveInternalField(instance_type)) {
965
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
966
0
                 (I::kEmbedderDataSlotSize * index);
967
0
    A value = I::ReadRawField<A>(obj, offset);
968
#ifdef V8_COMPRESS_POINTERS
969
    // We read the full pointer value and then decompress it in order to avoid
970
    // dealing with potential endianness issues.
971
    value = I::DecompressTaggedField(obj, static_cast<uint32_t>(value));
972
#endif
973
974
0
    auto* isolate = I::GetCurrentIsolate();
975
0
    return Local<Data>::New(isolate, value);
976
0
  }
977
0
#endif
978
0
  return SlowGetInternalField(index);
979
0
}
980
981
void* Object::GetAlignedPointerFromInternalField(v8::Isolate* isolate,
982
                                                 int index,
983
0
                                                 EmbedderDataTypeTag tag) {
984
0
#if !defined(V8_ENABLE_CHECKS)
985
0
  using A = internal::Address;
986
0
  using I = internal::Internals;
987
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
988
0
  // Fast path: If the object is a plain JSObject, which is the common case, we
989
0
  // know where to find the internal fields and can return the value directly.
990
0
  auto instance_type = I::GetInstanceType(obj);
991
0
  if (V8_LIKELY(I::CanHaveInternalField(instance_type))) {
992
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
993
0
                 (I::kEmbedderDataSlotSize * index) +
994
0
                 I::kEmbedderDataSlotExternalPointerOffset;
995
0
    A value = I::ReadExternalPointerField(isolate, obj, offset,
996
0
                                          ToExternalPointerTag(tag));
997
0
    return reinterpret_cast<void*>(value);
998
0
  }
999
0
#endif
1000
0
  return SlowGetAlignedPointerFromInternalField(isolate, index, tag);
1001
0
}
1002
1003
void* Object::GetAlignedPointerFromInternalField(int index,
1004
0
                                                 EmbedderDataTypeTag tag) {
1005
0
#if !defined(V8_ENABLE_CHECKS)
1006
0
  using A = internal::Address;
1007
0
  using I = internal::Internals;
1008
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
1009
  // Fast path: If the object is a plain JSObject, which is the common case, we
1010
  // know where to find the internal fields and can return the value directly.
1011
0
  auto instance_type = I::GetInstanceType(obj);
1012
0
  if (V8_LIKELY(I::CanHaveInternalField(instance_type))) {
1013
0
    int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
1014
0
                 (I::kEmbedderDataSlotSize * index) +
1015
0
                 I::kEmbedderDataSlotExternalPointerOffset;
1016
0
    Isolate* isolate = I::GetCurrentIsolateForSandbox();
1017
0
    A value = I::ReadExternalPointerField(isolate, obj, offset,
1018
0
                                          ToExternalPointerTag(tag));
1019
0
    return reinterpret_cast<void*>(value);
1020
0
  }
1021
0
#endif
1022
0
  return SlowGetAlignedPointerFromInternalField(index, tag);
1023
0
}
1024
1025
// static
1026
template <CppHeapPointerTag tag, typename T>
1027
T* Object::Unwrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper) {
1028
  CppHeapPointerTagRange tag_range(tag, tag);
1029
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1030
#if !defined(V8_ENABLE_CHECKS)
1031
  return internal::ReadCppHeapPointerField<T>(
1032
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1033
#else   // defined(V8_ENABLE_CHECKS)
1034
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1035
#endif  // defined(V8_ENABLE_CHECKS)
1036
}
1037
1038
// static
1039
template <CppHeapPointerTag tag, typename T>
1040
T* Object::Unwrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper) {
1041
  CppHeapPointerTagRange tag_range(tag, tag);
1042
  auto obj =
1043
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1044
#if !defined(V8_ENABLE_CHECKS)
1045
  return internal::ReadCppHeapPointerField<T>(
1046
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1047
#else   // defined(V8_ENABLE_CHECKS)
1048
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1049
#endif  // defined(V8_ENABLE_CHECKS)
1050
}
1051
1052
// static
1053
template <CppHeapPointerTag tag, typename T>
1054
T* Object::Unwrap(v8::Isolate* isolate,
1055
                  const BasicTracedReference<Object>& wrapper) {
1056
  CppHeapPointerTagRange tag_range(tag, tag);
1057
  auto obj =
1058
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1059
#if !defined(V8_ENABLE_CHECKS)
1060
  return internal::ReadCppHeapPointerField<T>(
1061
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1062
#else   // defined(V8_ENABLE_CHECKS)
1063
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1064
#endif  // defined(V8_ENABLE_CHECKS)
1065
}
1066
1067
// static
1068
template <typename T>
1069
T* Object::Unwrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1070
                  CppHeapPointerTagRange tag_range) {
1071
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1072
#if !defined(V8_ENABLE_CHECKS)
1073
  return internal::ReadCppHeapPointerField<T>(
1074
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1075
#else   // defined(V8_ENABLE_CHECKS)
1076
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1077
#endif  // defined(V8_ENABLE_CHECKS)
1078
}
1079
1080
// static
1081
template <typename T>
1082
T* Object::Unwrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1083
                  CppHeapPointerTagRange tag_range) {
1084
  auto obj =
1085
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1086
#if !defined(V8_ENABLE_CHECKS)
1087
  return internal::ReadCppHeapPointerField<T>(
1088
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1089
#else   // defined(V8_ENABLE_CHECKS)
1090
1091
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1092
#endif  // defined(V8_ENABLE_CHECKS)
1093
}
1094
1095
// static
1096
template <typename T>
1097
T* Object::Unwrap(v8::Isolate* isolate,
1098
                  const BasicTracedReference<Object>& wrapper,
1099
                  CppHeapPointerTagRange tag_range) {
1100
  auto obj =
1101
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1102
#if !defined(V8_ENABLE_CHECKS)
1103
  return internal::ReadCppHeapPointerField<T>(
1104
      isolate, obj, internal::Internals::kJSObjectHeaderSize, tag_range);
1105
#else   // defined(V8_ENABLE_CHECKS)
1106
  return reinterpret_cast<T*>(Unwrap(isolate, obj, tag_range));
1107
#endif  // defined(V8_ENABLE_CHECKS)
1108
}
1109
1110
// static
1111
template <CppHeapPointerTag tag>
1112
void Object::Wrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1113
0
                  v8::Object::Wrappable* wrappable) {
1114
0
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1115
0
  Wrap(isolate, obj, tag, wrappable);
1116
0
}
1117
1118
// static
1119
template <CppHeapPointerTag tag>
1120
void Object::Wrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1121
                  v8::Object::Wrappable* wrappable) {
1122
  auto obj =
1123
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1124
  Wrap(isolate, obj, tag, wrappable);
1125
}
1126
1127
// static
1128
template <CppHeapPointerTag tag>
1129
void Object::Wrap(v8::Isolate* isolate,
1130
                  const BasicTracedReference<Object>& wrapper,
1131
                  v8::Object::Wrappable* wrappable) {
1132
  auto obj =
1133
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1134
  Wrap(isolate, obj, tag, wrappable);
1135
}
1136
1137
// static
1138
void Object::Wrap(v8::Isolate* isolate, const v8::Local<v8::Object>& wrapper,
1139
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1140
0
  auto obj = internal::ValueHelper::ValueAsAddress(*wrapper);
1141
0
  Wrap(isolate, obj, tag, wrappable);
1142
0
}
1143
1144
// static
1145
void Object::Wrap(v8::Isolate* isolate, const PersistentBase<Object>& wrapper,
1146
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1147
0
  auto obj =
1148
0
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1149
0
  Wrap(isolate, obj, tag, wrappable);
1150
0
}
1151
1152
// static
1153
void Object::Wrap(v8::Isolate* isolate,
1154
                  const BasicTracedReference<Object>& wrapper,
1155
0
                  v8::Object::Wrappable* wrappable, CppHeapPointerTag tag) {
1156
0
  auto obj =
1157
0
      internal::ValueHelper::ValueAsAddress(wrapper.template value<Object>());
1158
0
  Wrap(isolate, obj, tag, wrappable);
1159
0
}
1160
1161
0
Private* Private::Cast(Data* data) {
1162
#ifdef V8_ENABLE_CHECKS
1163
  CheckCast(data);
1164
#endif
1165
0
  return reinterpret_cast<Private*>(data);
1166
0
}
1167
1168
0
Object* Object::Cast(v8::Value* value) {
1169
#ifdef V8_ENABLE_CHECKS
1170
  CheckCast(value);
1171
#endif
1172
0
  return static_cast<Object*>(value);
1173
0
}
1174
1175
}  // namespace v8
1176
1177
#endif  // INCLUDE_V8_OBJECT_H_