Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/deps/v8/include/v8-value.h
Line
Count
Source
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_VALUE_H_
6
#define INCLUDE_V8_VALUE_H_
7
8
#include "v8-data.h"          // NOLINT(build/include_directory)
9
#include "v8-internal.h"      // NOLINT(build/include_directory)
10
#include "v8-local-handle.h"  // NOLINT(build/include_directory)
11
#include "v8-maybe.h"         // NOLINT(build/include_directory)
12
#include "v8config.h"         // NOLINT(build/include_directory)
13
14
/**
15
 * The v8 JavaScript engine.
16
 */
17
namespace v8 {
18
19
class Primitive;
20
class Numeric;
21
class BigInt;
22
class Int32;
23
class Integer;
24
class Number;
25
class Object;
26
class String;
27
class Uint32;
28
29
/**
30
 * The superclass of all JavaScript values and objects.
31
 */
32
class V8_EXPORT Value : public Data {
33
 public:
34
  /**
35
   * Returns true if this value is the undefined value.  See ECMA-262
36
   * 4.3.10.
37
   *
38
   * This is equivalent to `value === undefined` in JS.
39
   */
40
  V8_INLINE bool IsUndefined() const;
41
42
  /**
43
   * Returns true if this value is the null value.  See ECMA-262
44
   * 4.3.11.
45
   *
46
   * This is equivalent to `value === null` in JS.
47
   */
48
  V8_INLINE bool IsNull() const;
49
50
  /**
51
   * Returns true if this value is either the null or the undefined value.
52
   * See ECMA-262
53
   * 4.3.11. and 4.3.12
54
   *
55
   * This is equivalent to `value == null` in JS.
56
   */
57
  V8_INLINE bool IsNullOrUndefined() const;
58
59
  /**
60
   * Returns true if this value is true.
61
   *
62
   * This is not the same as `BooleanValue()`. The latter performs a
63
   * conversion to boolean, i.e. the result of `Boolean(value)` in JS, whereas
64
   * this checks `value === true`.
65
   */
66
  V8_INLINE bool IsTrue() const;
67
68
  /**
69
   * Returns true if this value is false.
70
   *
71
   * This is not the same as `!BooleanValue()`. The latter performs a
72
   * conversion to boolean, i.e. the result of `!Boolean(value)` in JS, whereas
73
   * this checks `value === false`.
74
   */
75
  V8_INLINE bool IsFalse() const;
76
77
  /**
78
   * Returns true if this value is a symbol or a string.
79
   *
80
   * This is equivalent to
81
   * `typeof value === 'string' || typeof value === 'symbol'` in JS.
82
   */
83
  bool IsName() const;
84
85
  /**
86
   * Returns true if this value is an instance of the String type.
87
   * See ECMA-262 8.4.
88
   *
89
   * This is equivalent to `typeof value === 'string'` in JS.
90
   */
91
  V8_INLINE bool IsString() const;
92
93
  /**
94
   * Returns true if this value is a symbol.
95
   *
96
   * This is equivalent to `typeof value === 'symbol'` in JS.
97
   */
98
  bool IsSymbol() const;
99
100
  /**
101
   * Returns true if this value is a function.
102
   *
103
   * This is equivalent to `typeof value === 'function'` in JS.
104
   */
105
  bool IsFunction() const;
106
107
  /**
108
   * Returns true if this value is an array. Note that it will return false for
109
   * an Proxy for an array.
110
   */
111
  bool IsArray() const;
112
113
  /**
114
   * Returns true if this value is an object.
115
   */
116
  bool IsObject() const;
117
118
  /**
119
   * Returns true if this value is a bigint.
120
   *
121
   * This is equivalent to `typeof value === 'bigint'` in JS.
122
   */
123
  bool IsBigInt() const;
124
125
  /**
126
   * Returns true if this value is boolean.
127
   *
128
   * This is equivalent to `typeof value === 'boolean'` in JS.
129
   */
130
  bool IsBoolean() const;
131
132
  /**
133
   * Returns true if this value is a number.
134
   *
135
   * This is equivalent to `typeof value === 'number'` in JS.
136
   */
137
  bool IsNumber() const;
138
139
  /**
140
   * Returns true if this value is an `External` object.
141
   */
142
  bool IsExternal() const;
143
144
  /**
145
   * Returns true if this value is a 32-bit signed integer.
146
   */
147
  bool IsInt32() const;
148
149
  /**
150
   * Returns true if this value is a 32-bit unsigned integer.
151
   */
152
  bool IsUint32() const;
153
154
  /**
155
   * Returns true if this value is a Date.
156
   */
157
  bool IsDate() const;
158
159
  /**
160
   * Returns true if this value is an Arguments object.
161
   */
162
  bool IsArgumentsObject() const;
163
164
  /**
165
   * Returns true if this value is a BigInt object.
166
   */
167
  bool IsBigIntObject() const;
168
169
  /**
170
   * Returns true if this value is a Boolean object.
171
   */
172
  bool IsBooleanObject() const;
173
174
  /**
175
   * Returns true if this value is a Number object.
176
   */
177
  bool IsNumberObject() const;
178
179
  /**
180
   * Returns true if this value is a String object.
181
   */
182
  bool IsStringObject() const;
183
184
  /**
185
   * Returns true if this value is a Symbol object.
186
   */
187
  bool IsSymbolObject() const;
188
189
  /**
190
   * Returns true if this value is a NativeError.
191
   */
192
  bool IsNativeError() const;
193
194
  /**
195
   * Returns true if this value is a RegExp.
196
   */
197
  bool IsRegExp() const;
198
199
  /**
200
   * Returns true if this value is an async function.
201
   */
202
  bool IsAsyncFunction() const;
203
204
  /**
205
   * Returns true if this value is a Generator function.
206
   */
207
  bool IsGeneratorFunction() const;
208
209
  /**
210
   * Returns true if this value is a Generator object (iterator).
211
   */
212
  bool IsGeneratorObject() const;
213
214
  /**
215
   * Returns true if this value is a Promise.
216
   */
217
  bool IsPromise() const;
218
219
  /**
220
   * Returns true if this value is a Map.
221
   */
222
  bool IsMap() const;
223
224
  /**
225
   * Returns true if this value is a Set.
226
   */
227
  bool IsSet() const;
228
229
  /**
230
   * Returns true if this value is a Map Iterator.
231
   */
232
  bool IsMapIterator() const;
233
234
  /**
235
   * Returns true if this value is a Set Iterator.
236
   */
237
  bool IsSetIterator() const;
238
239
  /**
240
   * Returns true if this value is a WeakMap.
241
   */
242
  bool IsWeakMap() const;
243
244
  /**
245
   * Returns true if this value is a WeakSet.
246
   */
247
  bool IsWeakSet() const;
248
249
  /**
250
   * Returns true if this value is a WeakRef.
251
   */
252
  bool IsWeakRef() const;
253
254
  /**
255
   * Returns true if this value is an ArrayBuffer.
256
   */
257
  bool IsArrayBuffer() const;
258
259
  /**
260
   * Returns true if this value is an ArrayBufferView.
261
   */
262
  bool IsArrayBufferView() const;
263
264
  /**
265
   * Returns true if this value is one of TypedArrays.
266
   */
267
  bool IsTypedArray() const;
268
269
  /**
270
   * Returns true if this value is an Uint8Array.
271
   */
272
  bool IsUint8Array() const;
273
274
  /**
275
   * Returns true if this value is an Uint8ClampedArray.
276
   */
277
  bool IsUint8ClampedArray() const;
278
279
  /**
280
   * Returns true if this value is an Int8Array.
281
   */
282
  bool IsInt8Array() const;
283
284
  /**
285
   * Returns true if this value is an Uint16Array.
286
   */
287
  bool IsUint16Array() const;
288
289
  /**
290
   * Returns true if this value is an Int16Array.
291
   */
292
  bool IsInt16Array() const;
293
294
  /**
295
   * Returns true if this value is an Uint32Array.
296
   */
297
  bool IsUint32Array() const;
298
299
  /**
300
   * Returns true if this value is an Int32Array.
301
   */
302
  bool IsInt32Array() const;
303
304
  /**
305
   * Returns true if this value is a Float16Array.
306
   */
307
  bool IsFloat16Array() const;
308
309
  /**
310
   * Returns true if this value is a Float32Array.
311
   */
312
  bool IsFloat32Array() const;
313
314
  /**
315
   * Returns true if this value is a Float64Array.
316
   */
317
  bool IsFloat64Array() const;
318
319
  /**
320
   * Returns true if this value is a BigInt64Array.
321
   */
322
  bool IsBigInt64Array() const;
323
324
  /**
325
   * Returns true if this value is a BigUint64Array.
326
   */
327
  bool IsBigUint64Array() const;
328
329
  /**
330
   * Returns true if this value is a DataView.
331
   */
332
  bool IsDataView() const;
333
334
  /**
335
   * Returns true if this value is a SharedArrayBuffer.
336
   */
337
  bool IsSharedArrayBuffer() const;
338
339
  /**
340
   * Returns true if this value is a JavaScript Proxy.
341
   */
342
  bool IsProxy() const;
343
344
  /**
345
   * Returns true if this value is a WasmMemoryObject.
346
   */
347
  bool IsWasmMemoryObject() const;
348
349
  /**
350
   * Returns true if this value is a WasmMemoryMapDescriptor.
351
   */
352
  bool IsWasmMemoryMapDescriptor() const;
353
354
  /**
355
   * Returns true if this value is a WasmModuleObject.
356
   */
357
  bool IsWasmModuleObject() const;
358
359
  /**
360
   * Returns true if this value is the WasmNull object.
361
   */
362
  bool IsWasmNull() const;
363
364
  /**
365
   * Returns true if the value is a Module Namespace Object.
366
   */
367
  bool IsModuleNamespaceObject() const;
368
369
  /**
370
   * Returns true if the value is a primitive.
371
   */
372
  bool IsPrimitive() const;
373
374
  /**
375
   * Perform `ToPrimitive(value)` as specified in:
376
   * https://tc39.es/ecma262/#sec-toprimitive.
377
   */
378
  V8_WARN_UNUSED_RESULT MaybeLocal<Primitive> ToPrimitive(
379
      Local<Context> context) const;
380
  /**
381
   * Perform `ToNumeric(value)` as specified in:
382
   * https://tc39.es/ecma262/#sec-tonumeric.
383
   */
384
  V8_WARN_UNUSED_RESULT MaybeLocal<Numeric> ToNumeric(
385
      Local<Context> context) const;
386
  /**
387
   * Perform the equivalent of `BigInt(value)` in JS.
388
   */
389
  V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
390
      Local<Context> context) const;
391
  /**
392
   * Perform the equivalent of `Number(value)` in JS.
393
   */
394
  V8_WARN_UNUSED_RESULT MaybeLocal<Number> ToNumber(
395
      Local<Context> context) const;
396
  /**
397
   * Perform the equivalent of `String(value)` in JS.
398
   */
399
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
400
      Local<Context> context) const;
401
  /**
402
   * Provide a string representation of this value usable for debugging.
403
   * This operation has no observable side effects and will succeed
404
   * unless e.g. execution is being terminated.
405
   */
406
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ToDetailString(
407
      Local<Context> context) const;
408
  /**
409
   * Perform the equivalent of `Tagged<Object>(value)` in JS.
410
   */
411
  V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
412
      Local<Context> context) const;
413
  /**
414
   * Perform the equivalent of `Number(value)` in JS and convert the result
415
   * to an integer. Negative values are rounded up, positive values are rounded
416
   * down. NaN is converted to 0. Infinite values yield undefined results.
417
   */
418
  V8_WARN_UNUSED_RESULT MaybeLocal<Integer> ToInteger(
419
      Local<Context> context) const;
420
  /**
421
   * Perform the equivalent of `Number(value)` in JS and convert the result
422
   * to an unsigned 32-bit integer by performing the steps in
423
   * https://tc39.es/ecma262/#sec-touint32.
424
   */
425
  V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToUint32(
426
      Local<Context> context) const;
427
  /**
428
   * Perform the equivalent of `Number(value)` in JS and convert the result
429
   * to a signed 32-bit integer by performing the steps in
430
   * https://tc39.es/ecma262/#sec-toint32.
431
   */
432
  V8_WARN_UNUSED_RESULT MaybeLocal<Int32> ToInt32(Local<Context> context) const;
433
434
  /**
435
   * Perform the equivalent of `Boolean(value)` in JS. This can never fail.
436
   */
437
  Local<Boolean> ToBoolean(Isolate* isolate) const;
438
439
  /**
440
   * Attempts to convert a string to an array index.
441
   * Returns an empty handle if the conversion fails.
442
   */
443
  V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToArrayIndex(
444
      Local<Context> context) const;
445
446
  /** Returns the equivalent of `ToBoolean()->Value()`. */
447
  bool BooleanValue(Isolate* isolate) const;
448
449
  /** Returns the equivalent of `ToNumber()->Value()`. */
450
  V8_WARN_UNUSED_RESULT Maybe<double> NumberValue(Local<Context> context) const;
451
  /** Returns the equivalent of `ToInteger()->Value()`. */
452
  V8_WARN_UNUSED_RESULT Maybe<int64_t> IntegerValue(
453
      Local<Context> context) const;
454
  /** Returns the equivalent of `ToUint32()->Value()`. */
455
  V8_WARN_UNUSED_RESULT Maybe<uint32_t> Uint32Value(
456
      Local<Context> context) const;
457
  /** Returns the equivalent of `ToInt32()->Value()`. */
458
  V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
459
460
  /** JS == */
461
  V8_WARN_UNUSED_RESULT Maybe<bool> Equals(Local<Context> context,
462
                                           Local<Value> that) const;
463
  bool StrictEquals(Local<Value> that) const;
464
  bool SameValue(Local<Value> that) const;
465
466
  template <class T>
467
  V8_INLINE static Value* Cast(T* value) {
468
    return static_cast<Value*>(value);
469
  }
470
471
  Local<String> TypeOf(Isolate*);
472
473
  Maybe<bool> InstanceOf(Local<Context> context, Local<Object> object);
474
475
  /**
476
   * Get the hash of this value. The hash is not guaranteed to be
477
   * unique. For |Object| and |Name| instances the result is equal to
478
   * |GetIdentityHash|. Hashes are not guaranteed to be stable across
479
   * different isolates or processes.
480
   */
481
  uint32_t GetHash();
482
483
 private:
484
  V8_INLINE bool QuickIsUndefined() const;
485
  V8_INLINE bool QuickIsNull() const;
486
  V8_INLINE bool QuickIsNullOrUndefined() const;
487
#if V8_STATIC_ROOTS_BOOL
488
  V8_INLINE bool QuickIsTrue() const;
489
  V8_INLINE bool QuickIsFalse() const;
490
#endif  // V8_STATIC_ROOTS_BOOL
491
  V8_INLINE bool QuickIsString() const;
492
  bool FullIsUndefined() const;
493
  bool FullIsNull() const;
494
  bool FullIsTrue() const;
495
  bool FullIsFalse() const;
496
  bool FullIsString() const;
497
498
  static void CheckCast(Data* that);
499
};
500
501
/**
502
 * Can be used to avoid repeated expensive type checks for groups of objects
503
 * that are expected to be similar (e.g. when Blink converts a bunch of
504
 * JavaScript objects to "ScriptWrappable" after a "HasInstance" check) by
505
 * making use of V8-internal "hidden classes". An object that has passed the
506
 * full check can be remembered via {Update}; further objects can be queried
507
 * using {Matches}.
508
 * Note that the answer will be conservative/"best-effort": when {Matches}
509
 * returns true, then the {candidate} can be relied upon to have the same
510
 * shape/constructor/prototype/etc. as the {baseline}. Otherwise, no reliable
511
 * statement can be made (the objects might still have indistinguishable shapes
512
 * for all intents and purposes, but this mechanism, being optimized for speed,
513
 * couldn't determine that quickly).
514
 */
515
class V8_EXPORT TypecheckWitness {
516
 public:
517
  explicit TypecheckWitness(Isolate* isolate);
518
519
  /**
520
   * Checks whether {candidate} can cheaply be identified as being "similar"
521
   * to the {baseline} that was passed to {Update} earlier.
522
   * It's safe to call this on an uninitialized {TypecheckWitness} instance:
523
   * it will then return {false} for any input.
524
   */
525
  V8_INLINE bool Matches(Local<Value> candidate) const;
526
527
  /**
528
   * Remembers a new baseline for future {Matches} queries.
529
   */
530
  void Update(Local<Value> baseline);
531
532
 private:
533
  Local<Data> cached_map_;
534
};
535
536
template <>
537
0
V8_INLINE Value* Value::Cast(Data* value) {
538
0
#ifdef V8_ENABLE_CHECKS
539
0
  CheckCast(value);
540
0
#endif
541
0
  return static_cast<Value*>(value);
542
0
}
543
544
74
bool Value::IsUndefined() const {
545
#ifdef V8_ENABLE_CHECKS
546
  return FullIsUndefined();
547
#else
548
74
  return QuickIsUndefined();
549
74
#endif
550
74
}
551
552
74
bool Value::QuickIsUndefined() const {
553
74
  using A = internal::Address;
554
74
  using I = internal::Internals;
555
74
  A obj = internal::ValueHelper::ValueAsAddress(this);
556
#if V8_STATIC_ROOTS_BOOL
557
  return I::is_identical(obj, I::StaticReadOnlyRoot::kUndefinedValue);
558
#else
559
74
  if (!I::HasHeapObjectTag(obj)) return false;
560
4
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
561
4
  return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
562
4
#endif  // V8_STATIC_ROOTS_BOOL
563
4
}
564
565
0
bool Value::IsNull() const {
566
#ifdef V8_ENABLE_CHECKS
567
  return FullIsNull();
568
#else
569
0
  return QuickIsNull();
570
0
#endif
571
0
}
572
573
0
bool Value::QuickIsNull() const {
574
0
  using A = internal::Address;
575
0
  using I = internal::Internals;
576
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
577
#if V8_STATIC_ROOTS_BOOL
578
  return I::is_identical(obj, I::StaticReadOnlyRoot::kNullValue);
579
#else
580
0
  if (!I::HasHeapObjectTag(obj)) return false;
581
0
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
582
0
  return (I::GetOddballKind(obj) == I::kNullOddballKind);
583
0
#endif  // V8_STATIC_ROOTS_BOOL
584
0
}
585
586
0
bool Value::IsNullOrUndefined() const {
587
#ifdef V8_ENABLE_CHECKS
588
  return FullIsNull() || FullIsUndefined();
589
#else
590
0
  return QuickIsNullOrUndefined();
591
0
#endif
592
0
}
593
594
0
bool Value::QuickIsNullOrUndefined() const {
595
#if V8_STATIC_ROOTS_BOOL
596
  return QuickIsNull() || QuickIsUndefined();
597
#else
598
0
  using A = internal::Address;
599
0
  using I = internal::Internals;
600
0
  A obj = internal::ValueHelper::ValueAsAddress(this);
601
0
  if (!I::HasHeapObjectTag(obj)) return false;
602
0
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
603
0
  int kind = I::GetOddballKind(obj);
604
0
  return kind == I::kNullOddballKind || kind == I::kUndefinedOddballKind;
605
0
#endif  // V8_STATIC_ROOTS_BOOL
606
0
}
607
608
669
bool Value::IsTrue() const {
609
#if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
610
  return QuickIsTrue();
611
#else
612
669
  return FullIsTrue();
613
669
#endif
614
669
}
615
616
#if V8_STATIC_ROOTS_BOOL
617
bool Value::QuickIsTrue() const {
618
  using A = internal::Address;
619
  using I = internal::Internals;
620
  A obj = internal::ValueHelper::ValueAsAddress(this);
621
  return I::is_identical(obj, I::StaticReadOnlyRoot::kTrueValue);
622
}
623
#endif  // V8_STATIC_ROOTS_BOOL
624
625
0
bool Value::IsFalse() const {
626
#if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
627
  return QuickIsFalse();
628
#else
629
0
  return FullIsFalse();
630
0
#endif
631
0
}
632
633
#if V8_STATIC_ROOTS_BOOL
634
bool Value::QuickIsFalse() const {
635
  using A = internal::Address;
636
  using I = internal::Internals;
637
  A obj = internal::ValueHelper::ValueAsAddress(this);
638
  return I::is_identical(obj, I::StaticReadOnlyRoot::kFalseValue);
639
}
640
#endif  // V8_STATIC_ROOTS_BOOL
641
642
249k
bool Value::IsString() const {
643
#ifdef V8_ENABLE_CHECKS
644
  return FullIsString();
645
#else
646
249k
  return QuickIsString();
647
249k
#endif
648
249k
}
649
650
249k
bool Value::QuickIsString() const {
651
249k
  using A = internal::Address;
652
249k
  using I = internal::Internals;
653
249k
  A obj = internal::ValueHelper::ValueAsAddress(this);
654
249k
  if (!I::HasHeapObjectTag(obj)) return false;
655
#if V8_STATIC_ROOTS_BOOL && !V8_MAP_PACKING
656
  return I::CheckInstanceMapRange(obj,
657
                                  I::StaticReadOnlyRoot::kStringMapLowerBound,
658
                                  I::StaticReadOnlyRoot::kStringMapUpperBound);
659
#else
660
249k
  return (I::GetInstanceType(obj) < I::kFirstNonstringType);
661
249k
#endif  // V8_STATIC_ROOTS_BOOL
662
249k
}
663
664
0
bool TypecheckWitness::Matches(Local<Value> candidate) const {
665
0
  internal::Address obj = internal::ValueHelper::ValueAsAddress(*candidate);
666
0
  internal::Address obj_map = internal::Internals::LoadMap(obj);
667
0
  internal::Address cached =
668
0
      internal::ValueHelper::ValueAsAddress(*cached_map_);
669
0
  return obj_map == cached;
670
0
}
671
672
}  // namespace v8
673
674
#endif  // INCLUDE_V8_VALUE_H_