Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:27

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 WasmModuleObject.
0351    */
0352   bool IsWasmModuleObject() const;
0353 
0354   /**
0355    * Returns true if this value is the WasmNull object.
0356    */
0357   bool IsWasmNull() const;
0358 
0359   /**
0360    * Returns true if the value is a Module Namespace Object.
0361    */
0362   bool IsModuleNamespaceObject() const;
0363 
0364   /**
0365    * Perform `ToPrimitive(value)` as specified in:
0366    * https://tc39.es/ecma262/#sec-toprimitive.
0367    */
0368   V8_WARN_UNUSED_RESULT MaybeLocal<Primitive> ToPrimitive(
0369       Local<Context> context) const;
0370   /**
0371    * Perform `ToNumeric(value)` as specified in:
0372    * https://tc39.es/ecma262/#sec-tonumeric.
0373    */
0374   V8_WARN_UNUSED_RESULT MaybeLocal<Numeric> ToNumeric(
0375       Local<Context> context) const;
0376   /**
0377    * Perform the equivalent of `BigInt(value)` in JS.
0378    */
0379   V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
0380       Local<Context> context) const;
0381   /**
0382    * Perform the equivalent of `Number(value)` in JS.
0383    */
0384   V8_WARN_UNUSED_RESULT MaybeLocal<Number> ToNumber(
0385       Local<Context> context) const;
0386   /**
0387    * Perform the equivalent of `String(value)` in JS.
0388    */
0389   V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
0390       Local<Context> context) const;
0391   /**
0392    * Provide a string representation of this value usable for debugging.
0393    * This operation has no observable side effects and will succeed
0394    * unless e.g. execution is being terminated.
0395    */
0396   V8_WARN_UNUSED_RESULT MaybeLocal<String> ToDetailString(
0397       Local<Context> context) const;
0398   /**
0399    * Perform the equivalent of `Tagged<Object>(value)` in JS.
0400    */
0401   V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
0402       Local<Context> context) const;
0403   /**
0404    * Perform the equivalent of `Number(value)` in JS and convert the result
0405    * to an integer. Negative values are rounded up, positive values are rounded
0406    * down. NaN is converted to 0. Infinite values yield undefined results.
0407    */
0408   V8_WARN_UNUSED_RESULT MaybeLocal<Integer> ToInteger(
0409       Local<Context> context) const;
0410   /**
0411    * Perform the equivalent of `Number(value)` in JS and convert the result
0412    * to an unsigned 32-bit integer by performing the steps in
0413    * https://tc39.es/ecma262/#sec-touint32.
0414    */
0415   V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToUint32(
0416       Local<Context> context) const;
0417   /**
0418    * Perform the equivalent of `Number(value)` in JS and convert the result
0419    * to a signed 32-bit integer by performing the steps in
0420    * https://tc39.es/ecma262/#sec-toint32.
0421    */
0422   V8_WARN_UNUSED_RESULT MaybeLocal<Int32> ToInt32(Local<Context> context) const;
0423 
0424   /**
0425    * Perform the equivalent of `Boolean(value)` in JS. This can never fail.
0426    */
0427   Local<Boolean> ToBoolean(Isolate* isolate) const;
0428 
0429   /**
0430    * Attempts to convert a string to an array index.
0431    * Returns an empty handle if the conversion fails.
0432    */
0433   V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToArrayIndex(
0434       Local<Context> context) const;
0435 
0436   /** Returns the equivalent of `ToBoolean()->Value()`. */
0437   bool BooleanValue(Isolate* isolate) const;
0438 
0439   /** Returns the equivalent of `ToNumber()->Value()`. */
0440   V8_WARN_UNUSED_RESULT Maybe<double> NumberValue(Local<Context> context) const;
0441   /** Returns the equivalent of `ToInteger()->Value()`. */
0442   V8_WARN_UNUSED_RESULT Maybe<int64_t> IntegerValue(
0443       Local<Context> context) const;
0444   /** Returns the equivalent of `ToUint32()->Value()`. */
0445   V8_WARN_UNUSED_RESULT Maybe<uint32_t> Uint32Value(
0446       Local<Context> context) const;
0447   /** Returns the equivalent of `ToInt32()->Value()`. */
0448   V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
0449 
0450   /** JS == */
0451   V8_WARN_UNUSED_RESULT Maybe<bool> Equals(Local<Context> context,
0452                                            Local<Value> that) const;
0453   bool StrictEquals(Local<Value> that) const;
0454   bool SameValue(Local<Value> that) const;
0455 
0456   template <class T>
0457   V8_INLINE static Value* Cast(T* value) {
0458     return static_cast<Value*>(value);
0459   }
0460 
0461   Local<String> TypeOf(Isolate*);
0462 
0463   Maybe<bool> InstanceOf(Local<Context> context, Local<Object> object);
0464 
0465  private:
0466   V8_INLINE bool QuickIsUndefined() const;
0467   V8_INLINE bool QuickIsNull() const;
0468   V8_INLINE bool QuickIsNullOrUndefined() const;
0469 #if V8_STATIC_ROOTS_BOOL
0470   V8_INLINE bool QuickIsTrue() const;
0471   V8_INLINE bool QuickIsFalse() const;
0472 #endif  // V8_STATIC_ROOTS_BOOL
0473   V8_INLINE bool QuickIsString() const;
0474   bool FullIsUndefined() const;
0475   bool FullIsNull() const;
0476   bool FullIsTrue() const;
0477   bool FullIsFalse() const;
0478   bool FullIsString() const;
0479 
0480   static void CheckCast(Data* that);
0481 };
0482 
0483 /**
0484  * Can be used to avoid repeated expensive type checks for groups of objects
0485  * that are expected to be similar (e.g. when Blink converts a bunch of
0486  * JavaScript objects to "ScriptWrappable" after a "HasInstance" check) by
0487  * making use of V8-internal "hidden classes". An object that has passed the
0488  * full check can be remembered via {Update}; further objects can be queried
0489  * using {Matches}.
0490  * Note that the answer will be conservative/"best-effort": when {Matches}
0491  * returns true, then the {candidate} can be relied upon to have the same
0492  * shape/constructor/prototype/etc. as the {baseline}. Otherwise, no reliable
0493  * statement can be made (the objects might still have indistinguishable shapes
0494  * for all intents and purposes, but this mechanism, being optimized for speed,
0495  * couldn't determine that quickly).
0496  */
0497 class V8_EXPORT TypecheckWitness {
0498  public:
0499   explicit TypecheckWitness(Isolate* isolate);
0500 
0501   /**
0502    * Checks whether {candidate} can cheaply be identified as being "similar"
0503    * to the {baseline} that was passed to {Update} earlier.
0504    * It's safe to call this on an uninitialized {TypecheckWitness} instance:
0505    * it will then return {false} for any input.
0506    */
0507   V8_INLINE bool Matches(Local<Value> candidate) const;
0508 
0509   /**
0510    * Remembers a new baseline for future {Matches} queries.
0511    */
0512   void Update(Local<Value> baseline);
0513 
0514  private:
0515   Local<Data> cached_map_;
0516 };
0517 
0518 template <>
0519 V8_INLINE Value* Value::Cast(Data* value) {
0520 #ifdef V8_ENABLE_CHECKS
0521   CheckCast(value);
0522 #endif
0523   return static_cast<Value*>(value);
0524 }
0525 
0526 bool Value::IsUndefined() const {
0527 #ifdef V8_ENABLE_CHECKS
0528   return FullIsUndefined();
0529 #else
0530   return QuickIsUndefined();
0531 #endif
0532 }
0533 
0534 bool Value::QuickIsUndefined() const {
0535   using A = internal::Address;
0536   using I = internal::Internals;
0537   A obj = internal::ValueHelper::ValueAsAddress(this);
0538 #if V8_STATIC_ROOTS_BOOL
0539   return I::is_identical(obj, I::StaticReadOnlyRoot::kUndefinedValue);
0540 #else
0541   if (!I::HasHeapObjectTag(obj)) return false;
0542   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0543   return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
0544 #endif  // V8_STATIC_ROOTS_BOOL
0545 }
0546 
0547 bool Value::IsNull() const {
0548 #ifdef V8_ENABLE_CHECKS
0549   return FullIsNull();
0550 #else
0551   return QuickIsNull();
0552 #endif
0553 }
0554 
0555 bool Value::QuickIsNull() const {
0556   using A = internal::Address;
0557   using I = internal::Internals;
0558   A obj = internal::ValueHelper::ValueAsAddress(this);
0559 #if V8_STATIC_ROOTS_BOOL
0560   return I::is_identical(obj, I::StaticReadOnlyRoot::kNullValue);
0561 #else
0562   if (!I::HasHeapObjectTag(obj)) return false;
0563   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0564   return (I::GetOddballKind(obj) == I::kNullOddballKind);
0565 #endif  // V8_STATIC_ROOTS_BOOL
0566 }
0567 
0568 bool Value::IsNullOrUndefined() const {
0569 #ifdef V8_ENABLE_CHECKS
0570   return FullIsNull() || FullIsUndefined();
0571 #else
0572   return QuickIsNullOrUndefined();
0573 #endif
0574 }
0575 
0576 bool Value::QuickIsNullOrUndefined() const {
0577 #if V8_STATIC_ROOTS_BOOL
0578   return QuickIsNull() || QuickIsUndefined();
0579 #else
0580   using A = internal::Address;
0581   using I = internal::Internals;
0582   A obj = internal::ValueHelper::ValueAsAddress(this);
0583   if (!I::HasHeapObjectTag(obj)) return false;
0584   if (I::GetInstanceType(obj) != I::kOddballType) return false;
0585   int kind = I::GetOddballKind(obj);
0586   return kind == I::kNullOddballKind || kind == I::kUndefinedOddballKind;
0587 #endif  // V8_STATIC_ROOTS_BOOL
0588 }
0589 
0590 bool Value::IsTrue() const {
0591 #if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
0592   return QuickIsTrue();
0593 #else
0594   return FullIsTrue();
0595 #endif
0596 }
0597 
0598 #if V8_STATIC_ROOTS_BOOL
0599 bool Value::QuickIsTrue() const {
0600   using A = internal::Address;
0601   using I = internal::Internals;
0602   A obj = internal::ValueHelper::ValueAsAddress(this);
0603   return I::is_identical(obj, I::StaticReadOnlyRoot::kTrueValue);
0604 }
0605 #endif  // V8_STATIC_ROOTS_BOOL
0606 
0607 bool Value::IsFalse() const {
0608 #if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
0609   return QuickIsFalse();
0610 #else
0611   return FullIsFalse();
0612 #endif
0613 }
0614 
0615 #if V8_STATIC_ROOTS_BOOL
0616 bool Value::QuickIsFalse() const {
0617   using A = internal::Address;
0618   using I = internal::Internals;
0619   A obj = internal::ValueHelper::ValueAsAddress(this);
0620   return I::is_identical(obj, I::StaticReadOnlyRoot::kFalseValue);
0621 }
0622 #endif  // V8_STATIC_ROOTS_BOOL
0623 
0624 bool Value::IsString() const {
0625 #ifdef V8_ENABLE_CHECKS
0626   return FullIsString();
0627 #else
0628   return QuickIsString();
0629 #endif
0630 }
0631 
0632 bool Value::QuickIsString() const {
0633   using A = internal::Address;
0634   using I = internal::Internals;
0635   A obj = internal::ValueHelper::ValueAsAddress(this);
0636   if (!I::HasHeapObjectTag(obj)) return false;
0637 #if V8_STATIC_ROOTS_BOOL && !V8_MAP_PACKING
0638   return I::CheckInstanceMapRange(obj, I::StaticReadOnlyRoot::kFirstStringMap,
0639                                   I::StaticReadOnlyRoot::kLastStringMap);
0640 #else
0641   return (I::GetInstanceType(obj) < I::kFirstNonstringType);
0642 #endif  // V8_STATIC_ROOTS_BOOL
0643 }
0644 
0645 bool TypecheckWitness::Matches(Local<Value> candidate) const {
0646   internal::Address obj = internal::ValueHelper::ValueAsAddress(*candidate);
0647   internal::Address obj_map = internal::Internals::LoadMap(obj);
0648   internal::Address cached =
0649       internal::ValueHelper::ValueAsAddress(*cached_map_);
0650   return obj_map == cached;
0651 }
0652 
0653 }  // namespace v8
0654 
0655 #endif  // INCLUDE_V8_VALUE_H_