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