Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-16 09:15:23

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef INCLUDE_V8_VALUE_H_
0006 #define INCLUDE_V8_VALUE_H_
0007 
0008 #include "v8-data.h"          // NOLINT(build/include_directory)
0009 #include "v8-internal.h"      // NOLINT(build/include_directory)
0010 #include "v8-local-handle.h"  // NOLINT(build/include_directory)
0011 #include "v8-maybe.h"         // NOLINT(build/include_directory)
0012 #include "v8config.h"         // NOLINT(build/include_directory)
0013 
0014 /**
0015  * The v8 JavaScript engine.
0016  */
0017 namespace v8 {
0018 
0019 class Primitive;
0020 class Numeric;
0021 class BigInt;
0022 class Int32;
0023 class Integer;
0024 class Number;
0025 class Object;
0026 class String;
0027 class Uint32;
0028 
0029 /**
0030  * The superclass of all JavaScript values and objects.
0031  */
0032 class V8_EXPORT Value : public Data {
0033  public:
0034   /**
0035    * Returns true if this value is the undefined value.  See ECMA-262
0036    * 4.3.10.
0037    *
0038    * This is equivalent to `value === undefined` in JS.
0039    */
0040   V8_INLINE bool IsUndefined() const;
0041 
0042   /**
0043    * Returns true if this value is the null value.  See ECMA-262
0044    * 4.3.11.
0045    *
0046    * This is equivalent to `value === null` in JS.
0047    */
0048   V8_INLINE bool IsNull() const;
0049 
0050   /**
0051    * Returns true if this value is either the null or the undefined value.
0052    * See ECMA-262
0053    * 4.3.11. and 4.3.12
0054    *
0055    * This is equivalent to `value == null` in JS.
0056    */
0057   V8_INLINE bool IsNullOrUndefined() const;
0058 
0059   /**
0060    * Returns true if this value is true.
0061    *
0062    * This is not the same as `BooleanValue()`. The latter performs a
0063    * conversion to boolean, i.e. the result of `Boolean(value)` in JS, whereas
0064    * this checks `value === true`.
0065    */
0066   V8_INLINE bool IsTrue() const;
0067 
0068   /**
0069    * Returns true if this value is false.
0070    *
0071    * This is not the same as `!BooleanValue()`. The latter performs a
0072    * conversion to boolean, i.e. the result of `!Boolean(value)` in JS, whereas
0073    * this checks `value === false`.
0074    */
0075   V8_INLINE bool IsFalse() const;
0076 
0077   /**
0078    * Returns true if this value is a symbol or a string.
0079    *
0080    * This is equivalent to
0081    * `typeof value === 'string' || typeof value === 'symbol'` in JS.
0082    */
0083   bool IsName() const;
0084 
0085   /**
0086    * Returns true if this value is an instance of the String type.
0087    * See ECMA-262 8.4.
0088    *
0089    * This is equivalent to `typeof value === 'string'` in JS.
0090    */
0091   V8_INLINE bool IsString() const;
0092 
0093   /**
0094    * Returns true if this value is a symbol.
0095    *
0096    * This is equivalent to `typeof value === 'symbol'` in JS.
0097    */
0098   bool IsSymbol() const;
0099 
0100   /**
0101    * Returns true if this value is a function.
0102    *
0103    * This is equivalent to `typeof value === 'function'` in JS.
0104    */
0105   bool IsFunction() const;
0106 
0107   /**
0108    * Returns true if this value is an array. Note that it will return false for
0109    * an Proxy for an array.
0110    */
0111   bool IsArray() const;
0112 
0113   /**
0114    * Returns true if this value is an object.
0115    */
0116   bool IsObject() const;
0117 
0118   /**
0119    * Returns true if this value is a bigint.
0120    *
0121    * This is equivalent to `typeof value === 'bigint'` in JS.
0122    */
0123   bool IsBigInt() const;
0124 
0125   /**
0126    * Returns true if this value is boolean.
0127    *
0128    * This is equivalent to `typeof value === 'boolean'` in JS.
0129    */
0130   bool IsBoolean() const;
0131 
0132   /**
0133    * Returns true if this value is a number.
0134    *
0135    * This is equivalent to `typeof value === 'number'` in JS.
0136    */
0137   bool IsNumber() const;
0138 
0139   /**
0140    * Returns true if this value is an `External` object.
0141    */
0142   bool IsExternal() const;
0143 
0144   /**
0145    * Returns true if this value is a 32-bit signed integer.
0146    */
0147   bool IsInt32() const;
0148 
0149   /**
0150    * Returns true if this value is a 32-bit unsigned integer.
0151    */
0152   bool IsUint32() const;
0153 
0154   /**
0155    * Returns true if this value is a Date.
0156    */
0157   bool IsDate() const;
0158 
0159   /**
0160    * Returns true if this value is an Arguments object.
0161    */
0162   bool IsArgumentsObject() const;
0163 
0164   /**
0165    * Returns true if this value is a BigInt object.
0166    */
0167   bool IsBigIntObject() const;
0168 
0169   /**
0170    * Returns true if this value is a Boolean object.
0171    */
0172   bool IsBooleanObject() const;
0173 
0174   /**
0175    * Returns true if this value is a Number object.
0176    */
0177   bool IsNumberObject() const;
0178 
0179   /**
0180    * Returns true if this value is a String object.
0181    */
0182   bool IsStringObject() const;
0183 
0184   /**
0185    * Returns true if this value is a Symbol object.
0186    */
0187   bool IsSymbolObject() const;
0188 
0189   /**
0190    * Returns true if this value is a NativeError.
0191    */
0192   bool IsNativeError() const;
0193 
0194   /**
0195    * Returns true if this value is a RegExp.
0196    */
0197   bool IsRegExp() const;
0198 
0199   /**
0200    * Returns true if this value is an async function.
0201    */
0202   bool IsAsyncFunction() const;
0203 
0204   /**
0205    * Returns true if this value is a Generator function.
0206    */
0207   bool IsGeneratorFunction() const;
0208 
0209   /**
0210    * Returns true if this value is a Generator object (iterator).
0211    */
0212   bool IsGeneratorObject() const;
0213 
0214   /**
0215    * Returns true if this value is a Promise.
0216    */
0217   bool IsPromise() const;
0218 
0219   /**
0220    * Returns true if this value is a Map.
0221    */
0222   bool IsMap() const;
0223 
0224   /**
0225    * Returns true if this value is a Set.
0226    */
0227   bool IsSet() const;
0228 
0229   /**
0230    * Returns true if this value is a Map Iterator.
0231    */
0232   bool IsMapIterator() const;
0233 
0234   /**
0235    * Returns true if this value is a Set Iterator.
0236    */
0237   bool IsSetIterator() const;
0238 
0239   /**
0240    * Returns true if this value is a WeakMap.
0241    */
0242   bool IsWeakMap() const;
0243 
0244   /**
0245    * Returns true if this value is a WeakSet.
0246    */
0247   bool IsWeakSet() const;
0248 
0249   /**
0250    * Returns true if this value is a WeakRef.
0251    */
0252   bool IsWeakRef() const;
0253 
0254   /**
0255    * Returns true if this value is an ArrayBuffer.
0256    */
0257   bool IsArrayBuffer() const;
0258 
0259   /**
0260    * Returns true if this value is an ArrayBufferView.
0261    */
0262   bool IsArrayBufferView() const;
0263 
0264   /**
0265    * Returns true if this value is one of TypedArrays.
0266    */
0267   bool IsTypedArray() const;
0268 
0269   /**
0270    * Returns true if this value is an Uint8Array.
0271    */
0272   bool IsUint8Array() const;
0273 
0274   /**
0275    * Returns true if this value is an Uint8ClampedArray.
0276    */
0277   bool IsUint8ClampedArray() const;
0278 
0279   /**
0280    * Returns true if this value is an Int8Array.
0281    */
0282   bool IsInt8Array() const;
0283 
0284   /**
0285    * Returns true if this value is an Uint16Array.
0286    */
0287   bool IsUint16Array() const;
0288 
0289   /**
0290    * Returns true if this value is an Int16Array.
0291    */
0292   bool IsInt16Array() const;
0293 
0294   /**
0295    * Returns true if this value is an Uint32Array.
0296    */
0297   bool IsUint32Array() const;
0298 
0299   /**
0300    * Returns true if this value is an Int32Array.
0301    */
0302   bool IsInt32Array() const;
0303 
0304   /**
0305    * Returns true if this value is a Float16Array.
0306    */
0307   bool IsFloat16Array() const;
0308 
0309   /**
0310    * Returns true if this value is a Float32Array.
0311    */
0312   bool IsFloat32Array() const;
0313 
0314   /**
0315    * Returns true if this value is a Float64Array.
0316    */
0317   bool IsFloat64Array() const;
0318 
0319   /**
0320    * Returns true if this value is a BigInt64Array.
0321    */
0322   bool IsBigInt64Array() const;
0323 
0324   /**
0325    * Returns true if this value is a BigUint64Array.
0326    */
0327   bool IsBigUint64Array() const;
0328 
0329   /**
0330    * Returns true if this value is a DataView.
0331    */
0332   bool IsDataView() const;
0333 
0334   /**
0335    * Returns true if this value is a SharedArrayBuffer.
0336    */
0337   bool IsSharedArrayBuffer() const;
0338 
0339   /**
0340    * Returns true if this value is a JavaScript Proxy.
0341    */
0342   bool IsProxy() const;
0343 
0344   /**
0345    * Returns true if this value is a WasmMemoryObject.
0346    */
0347   bool IsWasmMemoryObject() const;
0348 
0349   /**
0350    * Returns true if this value is a WasmMemoryMapDescriptor.
0351    */
0352   bool IsWasmMemoryMapDescriptor() const;
0353 
0354   /**
0355    * Returns true if this value is a WasmModuleObject.
0356    */
0357   bool IsWasmModuleObject() const;
0358 
0359   /**
0360    * Returns true if this value is the WasmNull object.
0361    */
0362   bool IsWasmNull() const;
0363 
0364   /**
0365    * Returns true if the value is a Module Namespace Object.
0366    */
0367   bool IsModuleNamespaceObject() const;
0368 
0369   /**
0370    * Returns true if the value is a primitive.
0371    */
0372   bool IsPrimitive() const;
0373 
0374   /**
0375    * Perform `ToPrimitive(value)` as specified in:
0376    * https://tc39.es/ecma262/#sec-toprimitive.
0377    */
0378   V8_WARN_UNUSED_RESULT MaybeLocal<Primitive> ToPrimitive(
0379       Local<Context> context) const;
0380   /**
0381    * Perform `ToNumeric(value)` as specified in:
0382    * https://tc39.es/ecma262/#sec-tonumeric.
0383    */
0384   V8_WARN_UNUSED_RESULT MaybeLocal<Numeric> ToNumeric(
0385       Local<Context> context) const;
0386   /**
0387    * Perform the equivalent of `BigInt(value)` in JS.
0388    */
0389   V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
0390       Local<Context> context) const;
0391   /**
0392    * Perform the equivalent of `Number(value)` in JS.
0393    */
0394   V8_WARN_UNUSED_RESULT MaybeLocal<Number> ToNumber(
0395       Local<Context> context) const;
0396   /**
0397    * Perform the equivalent of `String(value)` in JS.
0398    */
0399   V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
0400       Local<Context> context) const;
0401   /**
0402    * Provide a string representation of this value usable for debugging.
0403    * This operation has no observable side effects and will succeed
0404    * unless e.g. execution is being terminated.
0405    */
0406   V8_WARN_UNUSED_RESULT MaybeLocal<String> ToDetailString(
0407       Local<Context> context) const;
0408   /**
0409    * Perform the equivalent of `Tagged<Object>(value)` in JS.
0410    */
0411   V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
0412       Local<Context> context) const;
0413   /**
0414    * Perform the equivalent of `Number(value)` in JS and convert the result
0415    * to an integer. Negative values are rounded up, positive values are rounded
0416    * down. NaN is converted to 0. Infinite values yield undefined results.
0417    */
0418   V8_WARN_UNUSED_RESULT MaybeLocal<Integer> ToInteger(
0419       Local<Context> context) const;
0420   /**
0421    * Perform the equivalent of `Number(value)` in JS and convert the result
0422    * to an unsigned 32-bit integer by performing the steps in
0423    * https://tc39.es/ecma262/#sec-touint32.
0424    */
0425   V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToUint32(
0426       Local<Context> context) const;
0427   /**
0428    * Perform the equivalent of `Number(value)` in JS and convert the result
0429    * to a signed 32-bit integer by performing the steps in
0430    * https://tc39.es/ecma262/#sec-toint32.
0431    */
0432   V8_WARN_UNUSED_RESULT MaybeLocal<Int32> ToInt32(Local<Context> context) const;
0433 
0434   /**
0435    * Perform the equivalent of `Boolean(value)` in JS. This can never fail.
0436    */
0437   Local<Boolean> ToBoolean(Isolate* isolate) const;
0438 
0439   /**
0440    * Attempts to convert a string to an array index.
0441    * Returns an empty handle if the conversion fails.
0442    */
0443   V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToArrayIndex(
0444       Local<Context> context) const;
0445 
0446   /** Returns the equivalent of `ToBoolean()->Value()`. */
0447   bool BooleanValue(Isolate* isolate) const;
0448 
0449   /** Returns the equivalent of `ToNumber()->Value()`. */
0450   V8_WARN_UNUSED_RESULT Maybe<double> NumberValue(Local<Context> context) const;
0451   /** Returns the equivalent of `ToInteger()->Value()`. */
0452   V8_WARN_UNUSED_RESULT Maybe<int64_t> IntegerValue(
0453       Local<Context> context) const;
0454   /** Returns the equivalent of `ToUint32()->Value()`. */
0455   V8_WARN_UNUSED_RESULT Maybe<uint32_t> Uint32Value(
0456       Local<Context> context) const;
0457   /** Returns the equivalent of `ToInt32()->Value()`. */
0458   V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
0459 
0460   /** JS == */
0461   V8_WARN_UNUSED_RESULT Maybe<bool> Equals(Local<Context> context,
0462                                            Local<Value> that) const;
0463   bool StrictEquals(Local<Value> that) const;
0464   bool SameValue(Local<Value> that) const;
0465 
0466   template <class T>
0467   V8_INLINE static Value* Cast(T* value) {
0468     return static_cast<Value*>(value);
0469   }
0470 
0471   Local<String> TypeOf(Isolate*);
0472 
0473   Maybe<bool> InstanceOf(Local<Context> context, Local<Object> object);
0474 
0475   /**
0476    * Get the hash of this value. The hash is not guaranteed to be
0477    * unique. For |Object| and |Name| instances the result is equal to
0478    * |GetIdentityHash|. Hashes are not guaranteed to be stable across
0479    * different isolates or processes.
0480    */
0481   uint32_t GetHash();
0482 
0483  private:
0484   V8_INLINE bool QuickIsUndefined() const;
0485   V8_INLINE bool QuickIsNull() const;
0486   V8_INLINE bool QuickIsNullOrUndefined() const;
0487 #if V8_STATIC_ROOTS_BOOL
0488   V8_INLINE bool QuickIsTrue() const;
0489   V8_INLINE bool QuickIsFalse() const;
0490 #endif  // V8_STATIC_ROOTS_BOOL
0491   V8_INLINE bool QuickIsString() const;
0492   bool FullIsUndefined() const;
0493   bool FullIsNull() const;
0494   bool FullIsTrue() const;
0495   bool FullIsFalse() const;
0496   bool FullIsString() const;
0497 
0498   static void CheckCast(Data* that);
0499 };
0500 
0501 /**
0502  * Can be used to avoid repeated expensive type checks for groups of objects
0503  * that are expected to be similar (e.g. when Blink converts a bunch of
0504  * JavaScript objects to "ScriptWrappable" after a "HasInstance" check) by
0505  * making use of V8-internal "hidden classes". An object that has passed the
0506  * full check can be remembered via {Update}; further objects can be queried
0507  * using {Matches}.
0508  * Note that the answer will be conservative/"best-effort": when {Matches}
0509  * returns true, then the {candidate} can be relied upon to have the same
0510  * shape/constructor/prototype/etc. as the {baseline}. Otherwise, no reliable
0511  * statement can be made (the objects might still have indistinguishable shapes
0512  * for all intents and purposes, but this mechanism, being optimized for speed,
0513  * couldn't determine that quickly).
0514  */
0515 class V8_EXPORT TypecheckWitness {
0516  public:
0517   explicit TypecheckWitness(Isolate* isolate);
0518 
0519   /**
0520    * Checks whether {candidate} can cheaply be identified as being "similar"
0521    * to the {baseline} that was passed to {Update} earlier.
0522    * It's safe to call this on an uninitialized {TypecheckWitness} instance:
0523    * it will then return {false} for any input.
0524    */
0525   V8_INLINE bool Matches(Local<Value> candidate) const;
0526 
0527   /**
0528    * Remembers a new baseline for future {Matches} queries.
0529    */
0530   void Update(Local<Value> baseline);
0531 
0532  private:
0533   Local<Data> cached_map_;
0534 };
0535 
0536 template <>
0537 V8_INLINE Value* Value::Cast(Data* value) {
0538 #ifdef V8_ENABLE_CHECKS
0539   CheckCast(value);
0540 #endif
0541   return static_cast<Value*>(value);
0542 }
0543 
0544 bool Value::IsUndefined() const {
0545 #ifdef V8_ENABLE_CHECKS
0546   return FullIsUndefined();
0547 #else
0548   return QuickIsUndefined();
0549 #endif
0550 }
0551 
0552 bool Value::QuickIsUndefined() const {
0553   using A = internal::Address;
0554   using I = internal::Internals;
0555   A obj = internal::ValueHelper::ValueAsAddress(this);
0556 #if V8_STATIC_ROOTS_BOOL
0557   return I::is_identical(obj, I::StaticReadOnlyRoot::kUndefinedValue);
0558 #else
0559   if (!I::HasHeapObjectTag(obj)) return false;
0560   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0561   return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
0562 #endif  // V8_STATIC_ROOTS_BOOL
0563 }
0564 
0565 bool Value::IsNull() const {
0566 #ifdef V8_ENABLE_CHECKS
0567   return FullIsNull();
0568 #else
0569   return QuickIsNull();
0570 #endif
0571 }
0572 
0573 bool Value::QuickIsNull() const {
0574   using A = internal::Address;
0575   using I = internal::Internals;
0576   A obj = internal::ValueHelper::ValueAsAddress(this);
0577 #if V8_STATIC_ROOTS_BOOL
0578   return I::is_identical(obj, I::StaticReadOnlyRoot::kNullValue);
0579 #else
0580   if (!I::HasHeapObjectTag(obj)) return false;
0581   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0582   return (I::GetOddballKind(obj) == I::kNullOddballKind);
0583 #endif  // V8_STATIC_ROOTS_BOOL
0584 }
0585 
0586 bool Value::IsNullOrUndefined() const {
0587 #ifdef V8_ENABLE_CHECKS
0588   return FullIsNull() || FullIsUndefined();
0589 #else
0590   return QuickIsNullOrUndefined();
0591 #endif
0592 }
0593 
0594 bool Value::QuickIsNullOrUndefined() const {
0595 #if V8_STATIC_ROOTS_BOOL
0596   return QuickIsNull() || QuickIsUndefined();
0597 #else
0598   using A = internal::Address;
0599   using I = internal::Internals;
0600   A obj = internal::ValueHelper::ValueAsAddress(this);
0601   if (!I::HasHeapObjectTag(obj)) return false;
0602   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0603   int kind = I::GetOddballKind(obj);
0604   return kind == I::kNullOddballKind || kind == I::kUndefinedOddballKind;
0605 #endif  // V8_STATIC_ROOTS_BOOL
0606 }
0607 
0608 bool Value::IsTrue() const {
0609 #if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
0610   return QuickIsTrue();
0611 #else
0612   return FullIsTrue();
0613 #endif
0614 }
0615 
0616 #if V8_STATIC_ROOTS_BOOL
0617 bool Value::QuickIsTrue() const {
0618   using A = internal::Address;
0619   using I = internal::Internals;
0620   A obj = internal::ValueHelper::ValueAsAddress(this);
0621   return I::is_identical(obj, I::StaticReadOnlyRoot::kTrueValue);
0622 }
0623 #endif  // V8_STATIC_ROOTS_BOOL
0624 
0625 bool Value::IsFalse() const {
0626 #if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
0627   return QuickIsFalse();
0628 #else
0629   return FullIsFalse();
0630 #endif
0631 }
0632 
0633 #if V8_STATIC_ROOTS_BOOL
0634 bool Value::QuickIsFalse() const {
0635   using A = internal::Address;
0636   using I = internal::Internals;
0637   A obj = internal::ValueHelper::ValueAsAddress(this);
0638   return I::is_identical(obj, I::StaticReadOnlyRoot::kFalseValue);
0639 }
0640 #endif  // V8_STATIC_ROOTS_BOOL
0641 
0642 bool Value::IsString() const {
0643 #ifdef V8_ENABLE_CHECKS
0644   return FullIsString();
0645 #else
0646   return QuickIsString();
0647 #endif
0648 }
0649 
0650 bool Value::QuickIsString() const {
0651   using A = internal::Address;
0652   using I = internal::Internals;
0653   A obj = internal::ValueHelper::ValueAsAddress(this);
0654   if (!I::HasHeapObjectTag(obj)) return false;
0655 #if V8_STATIC_ROOTS_BOOL && !V8_MAP_PACKING
0656   return I::CheckInstanceMapRange(obj,
0657                                   I::StaticReadOnlyRoot::kStringMapLowerBound,
0658                                   I::StaticReadOnlyRoot::kStringMapUpperBound);
0659 #else
0660   return (I::GetInstanceType(obj) < I::kFirstNonstringType);
0661 #endif  // V8_STATIC_ROOTS_BOOL
0662 }
0663 
0664 bool TypecheckWitness::Matches(Local<Value> candidate) const {
0665   internal::Address obj = internal::ValueHelper::ValueAsAddress(*candidate);
0666   internal::Address obj_map = internal::Internals::LoadMap(obj);
0667   internal::Address cached =
0668       internal::ValueHelper::ValueAsAddress(*cached_map_);
0669   return obj_map == cached;
0670 }
0671 
0672 }  // namespace v8
0673 
0674 #endif  // INCLUDE_V8_VALUE_H_