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()125 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 // Implements CreateDataProperty (ECMA-262, 7.3.4).
251 //
252 // Defines a configurable, writable, enumerable property with the given value
253 // on the object unless the property already exists and is not configurable
254 // or the object is not extensible.
255 //
256 // Returns true on success.
257 V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
258 Local<Name> key,
259 Local<Value> value);
260 V8_WARN_UNUSED_RESULT Maybe<bool> CreateDataProperty(Local<Context> context,
261 uint32_t index,
262 Local<Value> value);
263
264 // Implements DefineOwnProperty.
265 //
266 // In general, CreateDataProperty will be faster, however, does not allow
267 // for specifying attributes.
268 //
269 // Returns true on success.
270 V8_WARN_UNUSED_RESULT Maybe<bool> DefineOwnProperty(
271 Local<Context> context, Local<Name> key, Local<Value> value,
272 PropertyAttribute attributes = None);
273
274 // Implements Object.DefineProperty(O, P, Attributes), see Ecma-262 19.1.2.4.
275 //
276 // The defineProperty function is used to add an own property or
277 // update the attributes of an existing own property of an object.
278 //
279 // Both data and accessor descriptors can be used.
280 //
281 // In general, CreateDataProperty is faster, however, does not allow
282 // for specifying attributes or an accessor descriptor.
283 //
284 // The PropertyDescriptor can change when redefining a property.
285 //
286 // Returns true on success.
287 V8_WARN_UNUSED_RESULT Maybe<bool> DefineProperty(
288 Local<Context> context, Local<Name> key, PropertyDescriptor& descriptor);
289
290 V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
291 Local<Value> key);
292
293 V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
294 uint32_t index);
295
296 /**
297 * Gets the property attributes of a property which can be None or
298 * any combination of ReadOnly, DontEnum and DontDelete. Returns
299 * None when the property doesn't exist.
300 */
301 V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetPropertyAttributes(
302 Local<Context> context, Local<Value> key);
303
304 /**
305 * Returns Object.getOwnPropertyDescriptor as per ES2016 section 19.1.2.6.
306 */
307 V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetOwnPropertyDescriptor(
308 Local<Context> context, Local<Name> key);
309
310 /**
311 * Object::Has() calls the abstract operation HasProperty(O, P) described
312 * in ECMA-262, 7.3.10. Has() returns
313 * true, if the object has the property, either own or on the prototype chain.
314 * Interceptors, i.e., PropertyQueryCallbacks, are called if present.
315 *
316 * Has() has the same side effects as JavaScript's `variable in object`.
317 * For example, calling Has() on a revoked proxy will throw an exception.
318 *
319 * \note Has() converts the key to a name, which possibly calls back into
320 * JavaScript.
321 *
322 * See also v8::Object::HasOwnProperty() and
323 * v8::Object::HasRealNamedProperty().
324 */
325 V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context,
326 Local<Value> key);
327
328 V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
329 Local<Value> key);
330
331 V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context, uint32_t index);
332
333 V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,
334 uint32_t index);
335
336 /**
337 * Note: SideEffectType affects the getter only, not the setter.
338 */
339 V8_WARN_UNUSED_RESULT Maybe<bool> SetAccessor(
340 Local<Context> context, Local<Name> name,
341 AccessorNameGetterCallback getter,
342 AccessorNameSetterCallback setter = nullptr,
343 MaybeLocal<Value> data = MaybeLocal<Value>(),
344 AccessControl settings = DEFAULT, PropertyAttribute attribute = None,
345 SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
346 SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
347
348 void SetAccessorProperty(Local<Name> name, Local<Function> getter,
349 Local<Function> setter = Local<Function>(),
350 PropertyAttribute attribute = None,
351 AccessControl settings = DEFAULT);
352
353 /**
354 * Sets a native data property like Template::SetNativeDataProperty, but
355 * this method sets on this object directly.
356 */
357 V8_WARN_UNUSED_RESULT Maybe<bool> SetNativeDataProperty(
358 Local<Context> context, Local<Name> name,
359 AccessorNameGetterCallback getter,
360 AccessorNameSetterCallback setter = nullptr,
361 Local<Value> data = Local<Value>(), PropertyAttribute attributes = None,
362 SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
363 SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
364
365 /**
366 * Attempts to create a property with the given name which behaves like a data
367 * property, except that the provided getter is invoked (and provided with the
368 * data value) to supply its value the first time it is read. After the
369 * property is accessed once, it is replaced with an ordinary data property.
370 *
371 * Analogous to Template::SetLazyDataProperty.
372 */
373 V8_WARN_UNUSED_RESULT Maybe<bool> SetLazyDataProperty(
374 Local<Context> context, Local<Name> name,
375 AccessorNameGetterCallback getter, Local<Value> data = Local<Value>(),
376 PropertyAttribute attributes = None,
377 SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
378 SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
379
380 /**
381 * Functionality for private properties.
382 * This is an experimental feature, use at your own risk.
383 * Note: Private properties are not inherited. Do not rely on this, since it
384 * may change.
385 */
386 Maybe<bool> HasPrivate(Local<Context> context, Local<Private> key);
387 Maybe<bool> SetPrivate(Local<Context> context, Local<Private> key,
388 Local<Value> value);
389 Maybe<bool> DeletePrivate(Local<Context> context, Local<Private> key);
390 MaybeLocal<Value> GetPrivate(Local<Context> context, Local<Private> key);
391
392 /**
393 * Returns an array containing the names of the enumerable properties
394 * of this object, including properties from prototype objects. The
395 * array returned by this method contains the same values as would
396 * be enumerated by a for-in statement over this object.
397 */
398 V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
399 Local<Context> context);
400 V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
401 Local<Context> context, KeyCollectionMode mode,
402 PropertyFilter property_filter, IndexFilter index_filter,
403 KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
404
405 /**
406 * This function has the same functionality as GetPropertyNames but
407 * the returned array doesn't contain the names of properties from
408 * prototype objects.
409 */
410 V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
411 Local<Context> context);
412
413 /**
414 * Returns an array containing the names of the filtered properties
415 * of this object, including properties from prototype objects. The
416 * array returned by this method contains the same values as would
417 * be enumerated by a for-in statement over this object.
418 */
419 V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
420 Local<Context> context, PropertyFilter filter,
421 KeyConversionMode key_conversion = KeyConversionMode::kKeepNumbers);
422
423 /**
424 * Get the prototype object. This does not skip objects marked to
425 * be skipped by __proto__ and it does not consult the security
426 * handler.
427 */
428 Local<Value> GetPrototype();
429
430 /**
431 * Set the prototype object. This does not skip objects marked to
432 * be skipped by __proto__ and it does not consult the security
433 * handler.
434 */
435 V8_WARN_UNUSED_RESULT Maybe<bool> SetPrototype(Local<Context> context,
436 Local<Value> prototype);
437
438 /**
439 * Finds an instance of the given function template in the prototype
440 * chain.
441 */
442 Local<Object> FindInstanceInPrototypeChain(Local<FunctionTemplate> tmpl);
443
444 /**
445 * Call builtin Object.prototype.toString on this object.
446 * This is different from Value::ToString() that may call
447 * user-defined toString function. This one does not.
448 */
449 V8_WARN_UNUSED_RESULT MaybeLocal<String> ObjectProtoToString(
450 Local<Context> context);
451
452 /**
453 * Returns the name of the function invoked as a constructor for this object.
454 */
455 Local<String> GetConstructorName();
456
457 /**
458 * Sets the integrity level of the object.
459 */
460 Maybe<bool> SetIntegrityLevel(Local<Context> context, IntegrityLevel level);
461
462 /** Gets the number of internal fields for this Object. */
463 int InternalFieldCount() const;
464
465 /** Same as above, but works for PersistentBase. */
InternalFieldCount(const PersistentBase<Object> & object)466 V8_INLINE static int InternalFieldCount(
467 const PersistentBase<Object>& object) {
468 return object.val_->InternalFieldCount();
469 }
470
471 /** Same as above, but works for BasicTracedReference. */
InternalFieldCount(const BasicTracedReference<Object> & object)472 V8_INLINE static int InternalFieldCount(
473 const BasicTracedReference<Object>& object) {
474 return object->InternalFieldCount();
475 }
476
477 /** Gets the value from an internal field. */
478 V8_INLINE Local<Value> GetInternalField(int index);
479
480 /** Sets the value in an internal field. */
481 void SetInternalField(int index, Local<Value> value);
482
483 /**
484 * Gets a 2-byte-aligned native pointer from an internal field. This field
485 * must have been set by SetAlignedPointerInInternalField, everything else
486 * leads to undefined behavior.
487 */
488 V8_INLINE void* GetAlignedPointerFromInternalField(int index);
489
490 /** Same as above, but works for PersistentBase. */
GetAlignedPointerFromInternalField(const PersistentBase<Object> & object,int index)491 V8_INLINE static void* GetAlignedPointerFromInternalField(
492 const PersistentBase<Object>& object, int index) {
493 return object.val_->GetAlignedPointerFromInternalField(index);
494 }
495
496 /** Same as above, but works for TracedReference. */
GetAlignedPointerFromInternalField(const BasicTracedReference<Object> & object,int index)497 V8_INLINE static void* GetAlignedPointerFromInternalField(
498 const BasicTracedReference<Object>& object, int index) {
499 return object->GetAlignedPointerFromInternalField(index);
500 }
501
502 /**
503 * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
504 * a field, GetAlignedPointerFromInternalField must be used, everything else
505 * leads to undefined behavior.
506 */
507 void SetAlignedPointerInInternalField(int index, void* value);
508 void SetAlignedPointerInInternalFields(int argc, int indices[],
509 void* values[]);
510
511 /**
512 * HasOwnProperty() is like JavaScript's Object.prototype.hasOwnProperty().
513 *
514 * See also v8::Object::Has() and v8::Object::HasRealNamedProperty().
515 */
516 V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
517 Local<Name> key);
518 V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
519 uint32_t index);
520 /**
521 * Use HasRealNamedProperty() if you want to check if an object has an own
522 * property without causing side effects, i.e., without calling interceptors.
523 *
524 * This function is similar to v8::Object::HasOwnProperty(), but it does not
525 * call interceptors.
526 *
527 * \note Consider using non-masking interceptors, i.e., the interceptors are
528 * not called if the receiver has the real named property. See
529 * `v8::PropertyHandlerFlags::kNonMasking`.
530 *
531 * See also v8::Object::Has().
532 */
533 V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
534 Local<Name> key);
535 V8_WARN_UNUSED_RESULT Maybe<bool> HasRealIndexedProperty(
536 Local<Context> context, uint32_t index);
537 V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedCallbackProperty(
538 Local<Context> context, Local<Name> key);
539
540 /**
541 * If result.IsEmpty() no real property was located in the prototype chain.
542 * This means interceptors in the prototype chain are not called.
543 */
544 V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedPropertyInPrototypeChain(
545 Local<Context> context, Local<Name> key);
546
547 /**
548 * Gets the property attributes of a real property in the prototype chain,
549 * which can be None or any combination of ReadOnly, DontEnum and DontDelete.
550 * Interceptors in the prototype chain are not called.
551 */
552 V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute>
553 GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,
554 Local<Name> key);
555
556 /**
557 * If result.IsEmpty() no real property was located on the object or
558 * in the prototype chain.
559 * This means interceptors in the prototype chain are not called.
560 */
561 V8_WARN_UNUSED_RESULT MaybeLocal<Value> GetRealNamedProperty(
562 Local<Context> context, Local<Name> key);
563
564 /**
565 * Gets the property attributes of a real property which can be
566 * None or any combination of ReadOnly, DontEnum and DontDelete.
567 * Interceptors in the prototype chain are not called.
568 */
569 V8_WARN_UNUSED_RESULT Maybe<PropertyAttribute> GetRealNamedPropertyAttributes(
570 Local<Context> context, Local<Name> key);
571
572 /** Tests for a named lookup interceptor.*/
573 bool HasNamedLookupInterceptor() const;
574
575 /** Tests for an index lookup interceptor.*/
576 bool HasIndexedLookupInterceptor() const;
577
578 /**
579 * Returns the identity hash for this object. The current implementation
580 * uses a hidden property on the object to store the identity hash.
581 *
582 * The return value will never be 0. Also, it is not guaranteed to be
583 * unique.
584 */
585 int GetIdentityHash();
586
587 /**
588 * Clone this object with a fast but shallow copy. Values will point
589 * to the same values as the original object.
590 */
591 // TODO(dcarney): take an isolate and optionally bail out?
592 Local<Object> Clone();
593
594 /**
595 * Returns the context in which the object was created.
596 */
597 V8_DEPRECATED("Use MaybeLocal<Context> GetCreationContext()")
598 Local<Context> CreationContext();
599 MaybeLocal<Context> GetCreationContext();
600
601 /**
602 * Shortcut for GetCreationContext().ToLocalChecked().
603 **/
604 Local<Context> GetCreationContextChecked();
605
606 /** Same as above, but works for Persistents */
607 V8_DEPRECATED(
608 "Use MaybeLocal<Context> GetCreationContext(const "
609 "PersistentBase<Object>& object)")
610 static Local<Context> CreationContext(const PersistentBase<Object>& object);
GetCreationContext(const PersistentBase<Object> & object)611 V8_INLINE static MaybeLocal<Context> GetCreationContext(
612 const PersistentBase<Object>& object) {
613 return object.val_->GetCreationContext();
614 }
615
616 /**
617 * Checks whether a callback is set by the
618 * ObjectTemplate::SetCallAsFunctionHandler method.
619 * When an Object is callable this method returns true.
620 */
621 bool IsCallable() const;
622
623 /**
624 * True if this object is a constructor.
625 */
626 bool IsConstructor() const;
627
628 /**
629 * True if this object can carry information relevant to the embedder in its
630 * embedder fields, false otherwise. This is generally true for objects
631 * constructed through function templates but also holds for other types where
632 * V8 automatically adds internal fields at compile time, such as e.g.
633 * v8::ArrayBuffer.
634 */
635 bool IsApiWrapper() const;
636
637 /**
638 * True if this object was created from an object template which was marked
639 * as undetectable. See v8::ObjectTemplate::MarkAsUndetectable for more
640 * information.
641 */
642 bool IsUndetectable() const;
643
644 /**
645 * Call an Object as a function if a callback is set by the
646 * ObjectTemplate::SetCallAsFunctionHandler method.
647 */
648 V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsFunction(Local<Context> context,
649 Local<Value> recv,
650 int argc,
651 Local<Value> argv[]);
652
653 /**
654 * Call an Object as a constructor if a callback is set by the
655 * ObjectTemplate::SetCallAsFunctionHandler method.
656 * Note: This method behaves like the Function::NewInstance method.
657 */
658 V8_WARN_UNUSED_RESULT MaybeLocal<Value> CallAsConstructor(
659 Local<Context> context, int argc, Local<Value> argv[]);
660
661 /**
662 * Return the isolate to which the Object belongs to.
663 */
664 Isolate* GetIsolate();
665
666 /**
667 * If this object is a Set, Map, WeakSet or WeakMap, this returns a
668 * representation of the elements of this object as an array.
669 * If this object is a SetIterator or MapIterator, this returns all
670 * elements of the underlying collection, starting at the iterator's current
671 * position.
672 * For other types, this will return an empty MaybeLocal<Array> (without
673 * scheduling an exception).
674 */
675 MaybeLocal<Array> PreviewEntries(bool* is_key_value);
676
677 static Local<Object> New(Isolate* isolate);
678
679 /**
680 * Creates a JavaScript object with the given properties, and
681 * a the given prototype_or_null (which can be any JavaScript
682 * value, and if it's null, the newly created object won't have
683 * a prototype at all). This is similar to Object.create().
684 * All properties will be created as enumerable, configurable
685 * and writable properties.
686 */
687 static Local<Object> New(Isolate* isolate, Local<Value> prototype_or_null,
688 Local<Name>* names, Local<Value>* values,
689 size_t length);
690
691 V8_INLINE static Object* Cast(Value* obj);
692
693 /**
694 * Support for TC39 "dynamic code brand checks" proposal.
695 *
696 * This API allows to query whether an object was constructed from a
697 * "code like" ObjectTemplate.
698 *
699 * See also: v8::ObjectTemplate::SetCodeLike
700 */
701 bool IsCodeLike(Isolate* isolate) const;
702
703 private:
704 Object();
705 static void CheckCast(Value* obj);
706 Local<Value> SlowGetInternalField(int index);
707 void* SlowGetAlignedPointerFromInternalField(int index);
708 };
709
710 // --- Implementation ---
711
GetInternalField(int index)712 Local<Value> Object::GetInternalField(int index) {
713 #ifndef V8_ENABLE_CHECKS
714 using A = internal::Address;
715 using I = internal::Internals;
716 A obj = *reinterpret_cast<A*>(this);
717 // Fast path: If the object is a plain JSObject, which is the common case, we
718 // know where to find the internal fields and can return the value directly.
719 int instance_type = I::GetInstanceType(obj);
720 if (v8::internal::CanHaveInternalField(instance_type)) {
721 int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
722 A value = I::ReadRawField<A>(obj, offset);
723 #ifdef V8_COMPRESS_POINTERS
724 // We read the full pointer value and then decompress it in order to avoid
725 // dealing with potential endiannes issues.
726 value = I::DecompressTaggedAnyField(obj, static_cast<uint32_t>(value));
727 #endif
728 internal::Isolate* isolate =
729 internal::IsolateFromNeverReadOnlySpaceObject(obj);
730 A* result = HandleScope::CreateHandle(isolate, value);
731 return Local<Value>(reinterpret_cast<Value*>(result));
732 }
733 #endif
734 return SlowGetInternalField(index);
735 }
736
GetAlignedPointerFromInternalField(int index)737 void* Object::GetAlignedPointerFromInternalField(int index) {
738 #if !defined(V8_ENABLE_CHECKS)
739 using A = internal::Address;
740 using I = internal::Internals;
741 A obj = *reinterpret_cast<A*>(this);
742 // Fast path: If the object is a plain JSObject, which is the common case, we
743 // know where to find the internal fields and can return the value directly.
744 auto instance_type = I::GetInstanceType(obj);
745 if (v8::internal::CanHaveInternalField(instance_type)) {
746 int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
747 #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
748 offset += I::kEmbedderDataSlotRawPayloadOffset;
749 #endif
750 internal::Isolate* isolate = I::GetIsolateForSandbox(obj);
751 A value = I::ReadExternalPointerField(
752 isolate, obj, offset, internal::kEmbedderDataSlotPayloadTag);
753 return reinterpret_cast<void*>(value);
754 }
755 #endif
756 return SlowGetAlignedPointerFromInternalField(index);
757 }
758
Cast(Data * data)759 Private* Private::Cast(Data* data) {
760 #ifdef V8_ENABLE_CHECKS
761 CheckCast(data);
762 #endif
763 return reinterpret_cast<Private*>(data);
764 }
765
Cast(v8::Value * value)766 Object* Object::Cast(v8::Value* value) {
767 #ifdef V8_ENABLE_CHECKS
768 CheckCast(value);
769 #endif
770 return static_cast<Object*>(value);
771 }
772
773 } // namespace v8
774
775 #endif // INCLUDE_V8_OBJECT_H_
776