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