• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "v8-local-handle.h"       // NOLINT(build/include_directory)
9 #include "v8-maybe.h"              // NOLINT(build/include_directory)
10 #include "v8-persistent-handle.h"  // NOLINT(build/include_directory)
11 #include "v8-primitive.h"          // NOLINT(build/include_directory)
12 #include "v8-traced-handle.h"      // NOLINT(build/include_directory)
13 #include "v8-value.h"              // NOLINT(build/include_directory)
14 #include "v8config.h"              // NOLINT(build/include_directory)
15 
16 namespace v8 {
17 
18 class Array;
19 class Function;
20 class FunctionTemplate;
21 template <typename T>
22 class PropertyCallbackInfo;
23 class Module;
24 class UnboundScript;
25 
26 /**
27  * A private symbol
28  *
29  * This is an experimental feature. Use at your own risk.
30  */
31 class V8_EXPORT Private : public Data {
32  public:
33   /**
34    * Returns the print name string of the private symbol, or undefined if none.
35    */
36   Local<Value> Name() const;
37 
38   /**
39    * Create a private symbol. If name is not empty, it will be the description.
40    */
41   static Local<Private> New(Isolate* isolate,
42                             Local<String> name = Local<String>());
43 
44   /**
45    * Retrieve a global private symbol. If a symbol with this name has not
46    * been retrieved in the same isolate before, it is created.
47    * Note that private symbols created this way are never collected, so
48    * they should only be used for statically fixed properties.
49    * Also, there is only one global name space for the names used as keys.
50    * To minimize the potential for clashes, use qualified names as keys,
51    * e.g., "Class#property".
52    */
53   static Local<Private> ForApi(Isolate* isolate, Local<String> name);
54 
55   V8_INLINE static Private* Cast(Data* data);
56 
57  private:
58   Private();
59 
60   static void CheckCast(Data* that);
61 };
62 
63 /**
64  * An instance of a Property Descriptor, see Ecma-262 6.2.4.
65  *
66  * Properties in a descriptor are present or absent. If you do not set
67  * `enumerable`, `configurable`, and `writable`, they are absent. If `value`,
68  * `get`, or `set` are absent, but you must specify them in the constructor, use
69  * empty handles.
70  *
71  * Accessors `get` and `set` must be callable or undefined if they are present.
72  *
73  * \note Only query properties if they are present, i.e., call `x()` only if
74  * `has_x()` returns true.
75  *
76  * \code
77  * // var desc = {writable: false}
78  * v8::PropertyDescriptor d(Local<Value>()), false);
79  * d.value(); // error, value not set
80  * if (d.has_writable()) {
81  *   d.writable(); // false
82  * }
83  *
84  * // var desc = {value: undefined}
85  * v8::PropertyDescriptor d(v8::Undefined(isolate));
86  *
87  * // var desc = {get: undefined}
88  * v8::PropertyDescriptor d(v8::Undefined(isolate), Local<Value>()));
89  * \endcode
90  */
91 class V8_EXPORT PropertyDescriptor {
92  public:
93   // GenericDescriptor
94   PropertyDescriptor();
95 
96   // DataDescriptor
97   explicit PropertyDescriptor(Local<Value> value);
98 
99   // DataDescriptor with writable property
100   PropertyDescriptor(Local<Value> value, bool writable);
101 
102   // AccessorDescriptor
103   PropertyDescriptor(Local<Value> get, Local<Value> set);
104 
105   ~PropertyDescriptor();
106 
107   Local<Value> value() const;
108   bool has_value() const;
109 
110   Local<Value> get() const;
111   bool has_get() const;
112   Local<Value> set() const;
113   bool has_set() const;
114 
115   void set_enumerable(bool enumerable);
116   bool enumerable() const;
117   bool has_enumerable() const;
118 
119   void set_configurable(bool configurable);
120   bool configurable() const;
121   bool has_configurable() const;
122 
123   bool writable() const;
124   bool has_writable() const;
125 
126   struct PrivateData;
get_private()127   PrivateData* get_private() const { return private_; }
128 
129   PropertyDescriptor(const PropertyDescriptor&) = delete;
130   void operator=(const PropertyDescriptor&) = delete;
131 
132  private:
133   PrivateData* private_;
134 };
135 
136 /**
137  * PropertyAttribute.
138  */
139 enum PropertyAttribute {
140   /** None. **/
141   None = 0,
142   /** ReadOnly, i.e., not writable. **/
143   ReadOnly = 1 << 0,
144   /** DontEnum, i.e., not enumerable. **/
145   DontEnum = 1 << 1,
146   /** DontDelete, i.e., not configurable. **/
147   DontDelete = 1 << 2
148 };
149 
150 /**
151  * Accessor[Getter|Setter] are used as callback functions when
152  * setting|getting a particular property. See Object and ObjectTemplate's
153  * method SetAccessor.
154  */
155 using AccessorGetterCallback =
156     void (*)(Local<String> property, const PropertyCallbackInfo<Value>& info);
157 using AccessorNameGetterCallback =
158     void (*)(Local<Name> property, const PropertyCallbackInfo<Value>& info);
159 
160 using AccessorSetterCallback = void (*)(Local<String> property,
161                                         Local<Value> value,
162                                         const PropertyCallbackInfo<void>& info);
163 using AccessorNameSetterCallback =
164     void (*)(Local<Name> property, Local<Value> value,
165              const PropertyCallbackInfo<void>& info);
166 
167 /**
168  * Access control specifications.
169  *
170  * Some accessors should be accessible across contexts.  These
171  * accessors have an explicit access control parameter which specifies
172  * the kind of cross-context access that should be allowed.
173  *
174  * TODO(dcarney): Remove PROHIBITS_OVERWRITING as it is now unused.
175  */
176 enum AccessControl {
177   DEFAULT = 0,
178   ALL_CAN_READ = 1,
179   ALL_CAN_WRITE = 1 << 1,
180   PROHIBITS_OVERWRITING = 1 << 2
181 };
182 
183 /**
184  * Property filter bits. They can be or'ed to build a composite filter.
185  */
186 enum PropertyFilter {
187   ALL_PROPERTIES = 0,
188   ONLY_WRITABLE = 1,
189   ONLY_ENUMERABLE = 2,
190   ONLY_CONFIGURABLE = 4,
191   SKIP_STRINGS = 8,
192   SKIP_SYMBOLS = 16
193 };
194 
195 /**
196  * Options for marking whether callbacks may trigger JS-observable side effects.
197  * Side-effect-free callbacks are allowlisted during debug evaluation with
198  * throwOnSideEffect. It applies when calling a Function, FunctionTemplate,
199  * or an Accessor callback. For Interceptors, please see
200  * PropertyHandlerFlags's kHasNoSideEffect.
201  * Callbacks that only cause side effects to the receiver are allowlisted if
202  * invoked on receiver objects that are created within the same debug-evaluate
203  * call, as these objects are temporary and the side effect does not escape.
204  */
205 enum class SideEffectType {
206   kHasSideEffect,
207   kHasNoSideEffect,
208   kHasSideEffectToReceiver
209 };
210 
211 /**
212  * Keys/Properties filter enums:
213  *
214  * KeyCollectionMode limits the range of collected properties. kOwnOnly limits
215  * the collected properties to the given Object only. kIncludesPrototypes will
216  * include all keys of the objects's prototype chain as well.
217  */
218 enum class KeyCollectionMode { kOwnOnly, kIncludePrototypes };
219 
220 /**
221  * kIncludesIndices allows for integer indices to be collected, while
222  * kSkipIndices will exclude integer indices from being collected.
223  */
224 enum class IndexFilter { kIncludeIndices, kSkipIndices };
225 
226 /**
227  * kConvertToString will convert integer indices to strings.
228  * kKeepNumbers will return numbers for integer indices.
229  */
230 enum class KeyConversionMode { kConvertToString, kKeepNumbers, kNoNumbers };
231 
232 /**
233  * Integrity level for objects.
234  */
235 enum class IntegrityLevel { kFrozen, kSealed };
236 
237 /**
238  * A JavaScript object (ECMA-262, 4.3.3)
239  */
240 class V8_EXPORT Object : public Value {
241  public:
242   /**
243    * Set only return Just(true) or Empty(), so if it should never fail, use
244    * result.Check().
245    */
246   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
247                                         Local<Value> key, Local<Value> value);
248 
249   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
250                                         Local<Value> value);
251 
252   // Implements CreateDataProperty (ECMA-262, 7.3.4).
253   //
254   // Defines a configurable, writable, enumerable property with the given value
255   // on the object unless the property already exists and is not configurable
256   // or the object is not extensible.
257   //
258   // Returns true on success.
259   V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
260                                                        Local<Name> key,
261                                                        Local<Value> value);
262   V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
263                                                        uint32_t index,
264                                                        Local<Value> value);
265 
266   // Implements DefineOwnProperty.
267   //
268   // In general, CreateDataProperty will be faster, however, does not allow
269   // for specifying attributes.
270   //
271   // Returns true on success.
272   V8_WARN_UNUSED_RESULT Maybe<bool> DefineOwnProperty(
273       Local<Context> context, Local<Name> key, Local<Value> value,
274       PropertyAttribute attributes = None);
275 
276   // Implements Object.DefineProperty(O, P, Attributes), see Ecma-262 19.1.2.4.
277   //
278   // The defineProperty function is used to add an own property or
279   // update the attributes of an existing own property of an object.
280   //
281   // Both data and accessor descriptors can be used.
282   //
283   // In general, CreateDataProperty is faster, however, does not allow
284   // for specifying attributes or an accessor descriptor.
285   //
286   // The PropertyDescriptor can change when redefining a property.
287   //
288   // Returns true on success.
289   V8_WARN_UNUSED_RESULT Maybe<bool> DefineProperty(
290       Local<Context> context, Local<Name> key, PropertyDescriptor& descriptor);
291 
292   V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
293                                               Local<Value> key);
294 
295   V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
296                                               uint32_t index);
297 
298   /**
299    * Gets the property attributes of a property which can be None or
300    * any combination of ReadOnly, DontEnum and DontDelete. Returns
301    * None when the property doesn't exist.
302    */
303   V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetPropertyAttributes(
304       Local<Context> context, Local<Value> key);
305 
306   /**
307    * Returns Object.getOwnPropertyDescriptor as per ES2016 section 19.1.2.6.
308    */
309   V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetOwnPropertyDescriptor(
310       Local<Context> context, Local<Name> key);
311 
312   /**
313    * Object::Has() calls the abstract operation HasProperty(O, P) described
314    * in ECMA-262, 7.3.10. Has() returns
315    * true, if the object has the property, either own or on the prototype chain.
316    * Interceptors, i.e., PropertyQueryCallbacks, are called if present.
317    *
318    * Has() has the same side effects as JavaScript's `variable in object`.
319    * For example, calling Has() on a revoked proxy will throw an exception.
320    *
321    * \note Has() converts the key to a name, which possibly calls back into
322    * JavaScript.
323    *
324    * See also v8::Object::HasOwnProperty() and
325    * v8::Object::HasRealNamedProperty().
326    */
327   V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context,
328                                         Local<Value> key);
329 
330   V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
331                                            Local<Value> key);
332 
333   V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context, uint32_t index);
334 
335   V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
336                                            uint32_t index);
337 
338   /**
339    * Note: SideEffectType affects the getter only, not the setter.
340    */
341   V8_WARN_UNUSED_RESULT Maybe<bool> SetAccessor(
342       Local<Context> context, Local<Name> name,
343       AccessorNameGetterCallback getter,
344       AccessorNameSetterCallback setter = nullptr,
345       MaybeLocal<Value> data = MaybeLocal<Value>(),
346       AccessControl settings = DEFAULT, PropertyAttribute attribute = None,
347       SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
348       SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
349 
350   void SetAccessorProperty(Local<Name> name, Local<Function> getter,
351                            Local<Function> setter = Local<Function>(),
352                            PropertyAttribute attribute = None,
353                            AccessControl settings = DEFAULT);
354 
355   /**
356    * Sets a native data property like Template::SetNativeDataProperty, but
357    * this method sets on this object directly.
358    */
359   V8_WARN_UNUSED_RESULT Maybe<bool> SetNativeDataProperty(
360       Local<Context> context, Local<Name> name,
361       AccessorNameGetterCallback getter,
362       AccessorNameSetterCallback setter = nullptr,
363       Local<Value> data = Local<Value>(), PropertyAttribute attributes = None,
364       SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
365       SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
366 
367   /**
368    * Attempts to create a property with the given name which behaves like a data
369    * property, except that the provided getter is invoked (and provided with the
370    * data value) to supply its value the first time it is read. After the
371    * property is accessed once, it is replaced with an ordinary data property.
372    *
373    * Analogous to Template::SetLazyDataProperty.
374    */
375   V8_WARN_UNUSED_RESULT Maybe<bool> SetLazyDataProperty(
376       Local<Context> context, Local<Name> name,
377       AccessorNameGetterCallback getter, Local<Value> data = Local<Value>(),
378       PropertyAttribute attributes = None,
379       SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
380       SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
381 
382   /**
383    * Functionality for private properties.
384    * This is an experimental feature, use at your own risk.
385    * Note: Private properties are not inherited. Do not rely on this, since it
386    * may change.
387    */
388   Maybe<bool> HasPrivate(Local<Context> context, Local<Private> key);
389   Maybe<bool> SetPrivate(Local<Context> context, Local<Private> key,
390                          Local<Value> value);
391   Maybe<bool> DeletePrivate(Local<Context> context, Local<Private> key);
392   MaybeLocal<Value> GetPrivate(Local<Context> context, Local<Private> key);
393 
394   /**
395    * Returns an array containing the names of the enumerable properties
396    * of this object, including properties from prototype objects.  The
397    * array returned by this method contains the same values as would
398    * be enumerated by a for-in statement over this object.
399    */
400   V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
401       Local<Context> context);
402   V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
403       Local<Context> context, KeyCollectionMode mode,
404       PropertyFilter property_filter, IndexFilter index_filter,
405       KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
406 
407   /**
408    * This function has the same functionality as GetPropertyNames but
409    * the returned array doesn't contain the names of properties from
410    * prototype objects.
411    */
412   V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
413       Local<Context> context);
414 
415   /**
416    * Returns an array containing the names of the filtered properties
417    * of this object, including properties from prototype objects.  The
418    * array returned by this method contains the same values as would
419    * be enumerated by a for-in statement over this object.
420    */
421   V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
422       Local<Context> context, PropertyFilter filter,
423       KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
424 
425   /**
426    * Get the prototype object (same as getting __proto__ property).  This does
427    * not consult the security handler.
428    * TODO(333672197): rename back to GetPrototype() once the old version goes
429    * through the deprecation process and is removed.
430    */
431   Local<Value> GetPrototypeV2();
432 
433   /**
434    * Set the prototype object (same as setting __proto__ property).  This does
435    * does not consult the security handler.
436    * TODO(333672197): rename back to SetPrototype() once the old version goes
437    * through the deprecation process and is removed.
438    */
439   V8_WARN_UNUSED_RESULT Maybe<bool> SetPrototypeV2(Local<Context> context,
440                                                    Local<Value> prototype);
441 
442   /**
443    * Get the prototype object.  This does not skip objects marked to
444    * be skipped by __proto__ and it does not consult the security
445    * handler.
446    */
447   Local<Value> GetPrototype();
448 
449   /**
450    * Set the prototype object.  This does not skip objects marked to
451    * be skipped by __proto__ and it does not consult the security
452    * handler.
453    */
454   V8_WARN_UNUSED_RESULT Maybe<bool> SetPrototype(Local<Context> context,
455                                                  Local<Value> prototype);
456 
457   /**
458    * Finds an instance of the given function template in the prototype
459    * chain.
460    */
461   Local<Object> FindInstanceInPrototypeChain(Local<FunctionTemplate> tmpl);
462 
463   /**
464    * Call builtin Object.prototype.toString on this object.
465    * This is different from Value::ToString() that may call
466    * user-defined toString function. This one does not.
467    */
468   V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
469       Local<Context> context);
470 
471   /**
472    * Returns the name of the function invoked as a constructor for this object.
473    */
474   Local<String> GetConstructorName();
475 
476   /**
477    * Sets the integrity level of the object.
478    */
479   Maybe<bool> SetIntegrityLevel(Local<Context> context, IntegrityLevel level);
480 
481   /** Gets the number of internal fields for this Object. */
482   int InternalFieldCount() const;
483 
484   /** Same as above, but works for PersistentBase. */
InternalFieldCount(const PersistentBase<Object> & object)485   V8_INLINE static int InternalFieldCount(
486       const PersistentBase<Object>& object) {
487     return object.val_->InternalFieldCount();
488   }
489 
490   /** Same as above, but works for BasicTracedReference. */
InternalFieldCount(const BasicTracedReference<Object> & object)491   V8_INLINE static int InternalFieldCount(
492       const BasicTracedReference<Object>& object) {
493     return object->InternalFieldCount();
494   }
495 
496   /** Gets the value from an internal field. */
497   V8_INLINE Local<Value> GetInternalField(int index);
498 
499   /** Sets the value in an internal field. */
500   void SetInternalField(int index, Local<Value> value);
501 
502   /**
503    * Warning: These are Node.js-specific extentions used to avoid breaking
504    * changes in Node.js v18.x. They do not exist in V8 upstream and will
505    * not exist in Node.js v21.x. Node.js embedders and addon authors should
506    * not use them from v18.x.
507    */
508 #ifndef NODE_WANT_INTERNALS
509   V8_DEPRECATED("This extention should only be used by Node.js core")
510 #endif
511   void SetInternalFieldForNodeCore(int index, Local<Module> value);
512 #ifndef NODE_WANT_INTERNALS
513   V8_DEPRECATED("This extention should only be used by Node.js core")
514 #endif
515   void SetInternalFieldForNodeCore(int index, Local<UnboundScript> value);
516 
517   /**
518    * Gets a 2-byte-aligned native pointer from an internal field. This field
519    * must have been set by SetAlignedPointerInInternalField, everything else
520    * leads to undefined behavior.
521    */
522   V8_INLINE void* GetAlignedPointerFromInternalField(int index);
523 
524   /** Same as above, but works for PersistentBase. */
GetAlignedPointerFromInternalField(const PersistentBase<Object> & object,int index)525   V8_INLINE static void* GetAlignedPointerFromInternalField(
526       const PersistentBase<Object>& object, int index) {
527     return object.val_->GetAlignedPointerFromInternalField(index);
528   }
529 
530   /** Same as above, but works for TracedReference. */
GetAlignedPointerFromInternalField(const BasicTracedReference<Object> & object,int index)531   V8_INLINE static void* GetAlignedPointerFromInternalField(
532       const BasicTracedReference<Object>& object, int index) {
533     return object->GetAlignedPointerFromInternalField(index);
534   }
535 
536   /**
537    * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
538    * a field, GetAlignedPointerFromInternalField must be used, everything else
539    * leads to undefined behavior.
540    */
541   void SetAlignedPointerInInternalField(int index, void* value);
542   void SetAlignedPointerInInternalFields(int argc, int indices[],
543                                          void* values[]);
544 
545   /**
546    * HasOwnProperty() is like JavaScript's Object.prototype.hasOwnProperty().
547    *
548    * See also v8::Object::Has() and v8::Object::HasRealNamedProperty().
549    */
550   V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
551                                                    Local<Name> key);
552   V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
553                                                    uint32_t index);
554   /**
555    * Use HasRealNamedProperty() if you want to check if an object has an own
556    * property without causing side effects, i.e., without calling interceptors.
557    *
558    * This function is similar to v8::Object::HasOwnProperty(), but it does not
559    * call interceptors.
560    *
561    * \note Consider using non-masking interceptors, i.e., the interceptors are
562    * not called if the receiver has the real named property. See
563    * `v8::PropertyHandlerFlags::kNonMasking`.
564    *
565    * See also v8::Object::Has().
566    */
567   V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
568                                                          Local<Name> key);
569   V8_WARN_UNUSED_RESULT Maybe<bool> HasRealIndexedProperty(
570       Local<Context> context, uint32_t index);
571   V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedCallbackProperty(
572       Local<Context> context, Local<Name> key);
573 
574   /**
575    * If result.IsEmpty() no real property was located in the prototype chain.
576    * This means interceptors in the prototype chain are not called.
577    */
578   V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedPropertyInPrototypeChain(
579       Local<Context> context, Local<Name> key);
580 
581   /**
582    * Gets the property attributes of a real property in the prototype chain,
583    * which can be None or any combination of ReadOnly, DontEnum and DontDelete.
584    * Interceptors in the prototype chain are not called.
585    */
586   V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute>
587   GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,
588                                                  Local<Name> key);
589 
590   /**
591    * If result.IsEmpty() no real property was located on the object or
592    * in the prototype chain.
593    * This means interceptors in the prototype chain are not called.
594    */
595   V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedProperty(
596       Local<Context> context, Local<Name> key);
597 
598   /**
599    * Gets the property attributes of a real property which can be
600    * None or any combination of ReadOnly, DontEnum and DontDelete.
601    * Interceptors in the prototype chain are not called.
602    */
603   V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetRealNamedPropertyAttributes(
604       Local<Context> context, Local<Name> key);
605 
606   /** Tests for a named lookup interceptor.*/
607   bool HasNamedLookupInterceptor() const;
608 
609   /** Tests for an index lookup interceptor.*/
610   bool HasIndexedLookupInterceptor() const;
611 
612   /**
613    * Returns the identity hash for this object. The current implementation
614    * uses a hidden property on the object to store the identity hash.
615    *
616    * The return value will never be 0. Also, it is not guaranteed to be
617    * unique.
618    */
619   int GetIdentityHash();
620 
621   /**
622    * Clone this object with a fast but shallow copy.  Values will point
623    * to the same values as the original object.
624    */
625   // TODO(dcarney): take an isolate and optionally bail out?
626   Local<Object> Clone();
627 
628   /**
629    * Returns the context in which the object was created.
630    */
631   V8_DEPRECATED("Use MaybeLocal<Context> GetCreationContext()")
632   Local<Context> CreationContext();
633   MaybeLocal<Context> GetCreationContext();
634 
635   /**
636    * Shortcut for GetCreationContext().ToLocalChecked().
637    **/
638   Local<Context> GetCreationContextChecked();
639 
640   /** Same as above, but works for Persistents */
641   V8_DEPRECATED(
642       "Use MaybeLocal<Context> GetCreationContext(const "
643       "PersistentBase<Object>& object)")
644   static Local<Context> CreationContext(const PersistentBase<Object>& object);
GetCreationContext(const PersistentBase<Object> & object)645   V8_INLINE static MaybeLocal<Context> GetCreationContext(
646       const PersistentBase<Object>& object) {
647     return object.val_->GetCreationContext();
648   }
649 
650   /**
651    * Checks whether a callback is set by the
652    * ObjectTemplate::SetCallAsFunctionHandler method.
653    * When an Object is callable this method returns true.
654    */
655   bool IsCallable() const;
656 
657   /**
658    * True if this object is a constructor.
659    */
660   bool IsConstructor() const;
661 
662   /**
663    * True if this object can carry information relevant to the embedder in its
664    * embedder fields, false otherwise. This is generally true for objects
665    * constructed through function templates but also holds for other types where
666    * V8 automatically adds internal fields at compile time, such as e.g.
667    * v8::ArrayBuffer.
668    */
669   bool IsApiWrapper() const;
670 
671   /**
672    * True if this object was created from an object template which was marked
673    * as undetectable. See v8::ObjectTemplate::MarkAsUndetectable for more
674    * information.
675    */
676   bool IsUndetectable() const;
677 
678   /**
679    * Call an Object as a function if a callback is set by the
680    * ObjectTemplate::SetCallAsFunctionHandler method.
681    */
682   V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsFunction(Local<Context> context,
683                                                          Local<Value> recv,
684                                                          int argc,
685                                                          Local<Value> argv[]);
686 
687   /**
688    * Call an Object as a constructor if a callback is set by the
689    * ObjectTemplate::SetCallAsFunctionHandler method.
690    * Note: This method behaves like the Function::NewInstance method.
691    */
692   V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsConstructor(
693       Local<Context> context, int argc, Local<Value> argv[]);
694 
695   /**
696    * Return the isolate to which the Object belongs to.
697    */
698   Isolate* GetIsolate();
699 
700   /**
701    * If this object is a Set, Map, WeakSet or WeakMap, this returns a
702    * representation of the elements of this object as an array.
703    * If this object is a SetIterator or MapIterator, this returns all
704    * elements of the underlying collection, starting at the iterator's current
705    * position.
706    * For other types, this will return an empty MaybeLocal<Array> (without
707    * scheduling an exception).
708    */
709   MaybeLocal<Array> PreviewEntries(bool* is_key_value);
710 
711   static Local<Object> New(Isolate* isolate);
712 
713   /**
714    * Creates a JavaScript object with the given properties, and
715    * a the given prototype_or_null (which can be any JavaScript
716    * value, and if it's null, the newly created object won't have
717    * a prototype at all). This is similar to Object.create().
718    * All properties will be created as enumerable, configurable
719    * and writable properties.
720    */
721   static Local<Object> New(Isolate* isolate, Local<Value> prototype_or_null,
722                            Local<Name>* names, Local<Value>* values,
723                            size_t length);
724 
725   V8_INLINE static Object* Cast(Value* obj);
726 
727   /**
728    * Support for TC39 "dynamic code brand checks" proposal.
729    *
730    * This API allows to query whether an object was constructed from a
731    * "code like" ObjectTemplate.
732    *
733    * See also: v8::ObjectTemplate::SetCodeLike
734    */
735   bool IsCodeLike(Isolate* isolate) const;
736 
737  private:
738   Object();
739   static void CheckCast(Value* obj);
740   Local<Value> SlowGetInternalField(int index);
741   void* SlowGetAlignedPointerFromInternalField(int index);
742 };
743 
744 // --- Implementation ---
745 
GetInternalField(int index)746 Local<Value> Object::GetInternalField(int index) {
747 #ifndef V8_ENABLE_CHECKS
748   using A = internal::Address;
749   using I = internal::Internals;
750   A obj = *reinterpret_cast<A*>(this);
751   // Fast path: If the object is a plain JSObject, which is the common case, we
752   // know where to find the internal fields and can return the value directly.
753   int instance_type = I::GetInstanceType(obj);
754   if (v8::internal::CanHaveInternalField(instance_type)) {
755     int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
756     A value = I::ReadRawField<A>(obj, offset);
757 #ifdef V8_COMPRESS_POINTERS
758     // We read the full pointer value and then decompress it in order to avoid
759     // dealing with potential endiannes issues.
760     value = I::DecompressTaggedAnyField(obj, static_cast<uint32_t>(value));
761 #endif
762     internal::Isolate* isolate =
763         internal::IsolateFromNeverReadOnlySpaceObject(obj);
764     A* result = HandleScope::CreateHandle(isolate, value);
765     return Local<Value>(reinterpret_cast<Value*>(result));
766   }
767 #endif
768   return SlowGetInternalField(index);
769 }
770 
GetAlignedPointerFromInternalField(int index)771 void* Object::GetAlignedPointerFromInternalField(int index) {
772 #if !defined(V8_ENABLE_CHECKS)
773   using A = internal::Address;
774   using I = internal::Internals;
775   A obj = *reinterpret_cast<A*>(this);
776   // Fast path: If the object is a plain JSObject, which is the common case, we
777   // know where to find the internal fields and can return the value directly.
778   auto instance_type = I::GetInstanceType(obj);
779   if (v8::internal::CanHaveInternalField(instance_type)) {
780     int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
781 #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
782     offset += I::kEmbedderDataSlotRawPayloadOffset;
783 #endif
784     internal::Isolate* isolate = I::GetIsolateForSandbox(obj);
785     A value = I::ReadExternalPointerField(
786         isolate, obj, offset, internal::kEmbedderDataSlotPayloadTag);
787     return reinterpret_cast<void*>(value);
788   }
789 #endif
790   return SlowGetAlignedPointerFromInternalField(index);
791 }
792 
Cast(Data * data)793 Private* Private::Cast(Data* data) {
794 #ifdef V8_ENABLE_CHECKS
795   CheckCast(data);
796 #endif
797   return reinterpret_cast<Private*>(data);
798 }
799 
Cast(v8::Value * value)800 Object* Object::Cast(v8::Value* value) {
801 #ifdef V8_ENABLE_CHECKS
802   CheckCast(value);
803 #endif
804   return static_cast<Object*>(value);
805 }
806 
807 }  // namespace v8
808 
809 #endif  // INCLUDE_V8_OBJECT_H_
810