Coverage Report

Created: 2025-08-28 09:57

/src/node/deps/v8/include/v8-value.h
Line
Count
Source (jump to first uncovered line)
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 Float32Array.
306
   */
307
  bool IsFloat32Array() const;
308
309
  /**
310
   * Returns true if this value is a Float64Array.
311
   */
312
  bool IsFloat64Array() const;
313
314
  /**
315
   * Returns true if this value is a BigInt64Array.
316
   */
317
  bool IsBigInt64Array() const;
318
319
  /**
320
   * Returns true if this value is a BigUint64Array.
321
   */
322
  bool IsBigUint64Array() const;
323
324
  /**
325
   * Returns true if this value is a DataView.
326
   */
327
  bool IsDataView() const;
328
329
  /**
330
   * Returns true if this value is a SharedArrayBuffer.
331
   */
332
  bool IsSharedArrayBuffer() const;
333
334
  /**
335
   * Returns true if this value is a JavaScript Proxy.
336
   */
337
  bool IsProxy() const;
338
339
  /**
340
   * Returns true if this value is a WasmMemoryObject.
341
   */
342
  bool IsWasmMemoryObject() const;
343
344
  /**
345
   * Returns true if this value is a WasmModuleObject.
346
   */
347
  bool IsWasmModuleObject() const;
348
349
  /**
350
   * Returns true if this value is the WasmNull object.
351
   */
352
  bool IsWasmNull() const;
353
354
  /**
355
   * Returns true if the value is a Module Namespace Object.
356
   */
357
  bool IsModuleNamespaceObject() const;
358
359
  /**
360
   * Perform `ToPrimitive(value)` as specified in:
361
   * https://tc39.es/ecma262/#sec-toprimitive.
362
   */
363
  V8_WARN_UNUSED_RESULT MaybeLocal<Primitive> ToPrimitive(
364
      Local<Context> context) const;
365
  /**
366
   * Perform `ToNumeric(value)` as specified in:
367
   * https://tc39.es/ecma262/#sec-tonumeric.
368
   */
369
  V8_WARN_UNUSED_RESULT MaybeLocal<Numeric> ToNumeric(
370
      Local<Context> context) const;
371
  /**
372
   * Perform the equivalent of `BigInt(value)` in JS.
373
   */
374
  V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
375
      Local<Context> context) const;
376
  /**
377
   * Perform the equivalent of `Number(value)` in JS.
378
   */
379
  V8_WARN_UNUSED_RESULT MaybeLocal<Number> ToNumber(
380
      Local<Context> context) const;
381
  /**
382
   * Perform the equivalent of `String(value)` in JS.
383
   */
384
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
385
      Local<Context> context) const;
386
  /**
387
   * Provide a string representation of this value usable for debugging.
388
   * This operation has no observable side effects and will succeed
389
   * unless e.g. execution is being terminated.
390
   */
391
  V8_WARN_UNUSED_RESULT MaybeLocal<String> ToDetailString(
392
      Local<Context> context) const;
393
  /**
394
   * Perform the equivalent of `Tagged<Object>(value)` in JS.
395
   */
396
  V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
397
      Local<Context> context) const;
398
  /**
399
   * Perform the equivalent of `Number(value)` in JS and convert the result
400
   * to an integer. Negative values are rounded up, positive values are rounded
401
   * down. NaN is converted to 0. Infinite values yield undefined results.
402
   */
403
  V8_WARN_UNUSED_RESULT MaybeLocal<Integer> ToInteger(
404
      Local<Context> context) const;
405
  /**
406
   * Perform the equivalent of `Number(value)` in JS and convert the result
407
   * to an unsigned 32-bit integer by performing the steps in
408
   * https://tc39.es/ecma262/#sec-touint32.
409
   */
410
  V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToUint32(
411
      Local<Context> context) const;
412
  /**
413
   * Perform the equivalent of `Number(value)` in JS and convert the result
414
   * to a signed 32-bit integer by performing the steps in
415
   * https://tc39.es/ecma262/#sec-toint32.
416
   */
417
  V8_WARN_UNUSED_RESULT MaybeLocal<Int32> ToInt32(Local<Context> context) const;
418
419
  /**
420
   * Perform the equivalent of `Boolean(value)` in JS. This can never fail.
421
   */
422
  Local<Boolean> ToBoolean(Isolate* isolate) const;
423
424
  /**
425
   * Attempts to convert a string to an array index.
426
   * Returns an empty handle if the conversion fails.
427
   */
428
  V8_WARN_UNUSED_RESULT MaybeLocal<Uint32> ToArrayIndex(
429
      Local<Context> context) const;
430
431
  /** Returns the equivalent of `ToBoolean()->Value()`. */
432
  bool BooleanValue(Isolate* isolate) const;
433
434
  /** Returns the equivalent of `ToNumber()->Value()`. */
435
  V8_WARN_UNUSED_RESULT Maybe<double> NumberValue(Local<Context> context) const;
436
  /** Returns the equivalent of `ToInteger()->Value()`. */
437
  V8_WARN_UNUSED_RESULT Maybe<int64_t> IntegerValue(
438
      Local<Context> context) const;
439
  /** Returns the equivalent of `ToUint32()->Value()`. */
440
  V8_WARN_UNUSED_RESULT Maybe<uint32_t> Uint32Value(
441
      Local<Context> context) const;
442
  /** Returns the equivalent of `ToInt32()->Value()`. */
443
  V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
444
445
  /** JS == */
446
  V8_WARN_UNUSED_RESULT Maybe<bool> Equals(Local<Context> context,
447
                                           Local<Value> that) const;
448
  bool StrictEquals(Local<Value> that) const;
449
  bool SameValue(Local<Value> that) const;
450
451
  template <class T>
452
  V8_INLINE static Value* Cast(T* value) {
453
    return static_cast<Value*>(value);
454
  }
455
456
  Local<String> TypeOf(Isolate*);
457
458
  Maybe<bool> InstanceOf(Local<Context> context, Local<Object> object);
459
460
 private:
461
  V8_INLINE bool QuickIsUndefined() const;
462
  V8_INLINE bool QuickIsNull() const;
463
  V8_INLINE bool QuickIsNullOrUndefined() const;
464
#if V8_STATIC_ROOTS_BOOL
465
  V8_INLINE bool QuickIsTrue() const;
466
  V8_INLINE bool QuickIsFalse() const;
467
#endif  // V8_STATIC_ROOTS_BOOL
468
  V8_INLINE bool QuickIsString() const;
469
  bool FullIsUndefined() const;
470
  bool FullIsNull() const;
471
  bool FullIsTrue() const;
472
  bool FullIsFalse() const;
473
  bool FullIsString() const;
474
475
  static void CheckCast(Data* that);
476
};
477
478
/**
479
 * Can be used to avoid repeated expensive type checks for groups of objects
480
 * that are expected to be similar (e.g. when Blink converts a bunch of
481
 * JavaScript objects to "ScriptWrappable" after a "HasInstance" check) by
482
 * making use of V8-internal "hidden classes". An object that has passed the
483
 * full check can be remembered via {Update}; further objects can be queried
484
 * using {Matches}.
485
 * Note that the answer will be conservative/"best-effort": when {Matches}
486
 * returns true, then the {candidate} can be relied upon to have the same
487
 * shape/constructor/prototype/etc. as the {baseline}. Otherwise, no reliable
488
 * statement can be made (the objects might still have indistinguishable shapes
489
 * for all intents and purposes, but this mechanism, being optimized for speed,
490
 * couldn't determine that quickly).
491
 */
492
class V8_EXPORT TypecheckWitness {
493
 public:
494
  explicit TypecheckWitness(Isolate* isolate);
495
496
  /**
497
   * Checks whether {candidate} can cheaply be identified as being "similar"
498
   * to the {baseline} that was passed to {Update} earlier.
499
   * It's safe to call this on an uninitialized {TypecheckWitness} instance:
500
   * it will then return {false} for any input.
501
   */
502
  V8_INLINE bool Matches(Local<Value> candidate) const;
503
504
  /**
505
   * Remembers a new baseline for future {Matches} queries.
506
   */
507
  void Update(Local<Value> baseline);
508
509
 private:
510
  Local<Data> cached_map_;
511
};
512
513
template <>
514
0
V8_INLINE Value* Value::Cast(Data* value) {
515
0
#ifdef V8_ENABLE_CHECKS
516
0
  CheckCast(value);
517
0
#endif
518
0
  return static_cast<Value*>(value);
519
0
}
520
521
680k
bool Value::IsUndefined() const {
522
#ifdef V8_ENABLE_CHECKS
523
  return FullIsUndefined();
524
#else
525
680k
  return QuickIsUndefined();
526
680k
#endif
527
680k
}
528
529
680k
bool Value::QuickIsUndefined() const {
530
680k
  using A = internal::Address;
531
680k
  using I = internal::Internals;
532
680k
  A obj = internal::ValueHelper::ValueAsAddress(this);
533
#if V8_STATIC_ROOTS_BOOL
534
  return I::is_identical(obj, I::StaticReadOnlyRoot::kUndefinedValue);
535
#else
536
680k
  if (!I::HasHeapObjectTag(obj)) return false;
537
398k
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
538
154k
  return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
539
398k
#endif  // V8_STATIC_ROOTS_BOOL
540
398k
}
541
542
5.53k
bool Value::IsNull() const {
543
#ifdef V8_ENABLE_CHECKS
544
  return FullIsNull();
545
#else
546
5.53k
  return QuickIsNull();
547
5.53k
#endif
548
5.53k
}
549
550
5.53k
bool Value::QuickIsNull() const {
551
5.53k
  using A = internal::Address;
552
5.53k
  using I = internal::Internals;
553
5.53k
  A obj = internal::ValueHelper::ValueAsAddress(this);
554
#if V8_STATIC_ROOTS_BOOL
555
  return I::is_identical(obj, I::StaticReadOnlyRoot::kNullValue);
556
#else
557
5.53k
  if (!I::HasHeapObjectTag(obj)) return false;
558
5.53k
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
559
0
  return (I::GetOddballKind(obj) == I::kNullOddballKind);
560
5.53k
#endif  // V8_STATIC_ROOTS_BOOL
561
5.53k
}
562
563
2.13k
bool Value::IsNullOrUndefined() const {
564
#ifdef V8_ENABLE_CHECKS
565
  return FullIsNull() || FullIsUndefined();
566
#else
567
2.13k
  return QuickIsNullOrUndefined();
568
2.13k
#endif
569
2.13k
}
570
571
2.13k
bool Value::QuickIsNullOrUndefined() const {
572
#if V8_STATIC_ROOTS_BOOL
573
  return QuickIsNull() || QuickIsUndefined();
574
#else
575
2.13k
  using A = internal::Address;
576
2.13k
  using I = internal::Internals;
577
2.13k
  A obj = internal::ValueHelper::ValueAsAddress(this);
578
2.13k
  if (!I::HasHeapObjectTag(obj)) return false;
579
2.13k
  if (I::GetInstanceType(obj) != I::kOddballType) return false;
580
2.13k
  int kind = I::GetOddballKind(obj);
581
2.13k
  return kind == I::kNullOddballKind || kind == I::kUndefinedOddballKind;
582
2.13k
#endif  // V8_STATIC_ROOTS_BOOL
583
2.13k
}
584
585
235k
bool Value::IsTrue() const {
586
#if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
587
  return QuickIsTrue();
588
#else
589
235k
  return FullIsTrue();
590
235k
#endif
591
235k
}
592
593
#if V8_STATIC_ROOTS_BOOL
594
bool Value::QuickIsTrue() const {
595
  using A = internal::Address;
596
  using I = internal::Internals;
597
  A obj = internal::ValueHelper::ValueAsAddress(this);
598
  return I::is_identical(obj, I::StaticReadOnlyRoot::kTrueValue);
599
}
600
#endif  // V8_STATIC_ROOTS_BOOL
601
602
81.1k
bool Value::IsFalse() const {
603
#if V8_STATIC_ROOTS_BOOL && !defined(V8_ENABLE_CHECKS)
604
  return QuickIsFalse();
605
#else
606
81.1k
  return FullIsFalse();
607
81.1k
#endif
608
81.1k
}
609
610
#if V8_STATIC_ROOTS_BOOL
611
bool Value::QuickIsFalse() const {
612
  using A = internal::Address;
613
  using I = internal::Internals;
614
  A obj = internal::ValueHelper::ValueAsAddress(this);
615
  return I::is_identical(obj, I::StaticReadOnlyRoot::kFalseValue);
616
}
617
#endif  // V8_STATIC_ROOTS_BOOL
618
619
16.3M
bool Value::IsString() const {
620
#ifdef V8_ENABLE_CHECKS
621
  return FullIsString();
622
#else
623
16.3M
  return QuickIsString();
624
16.3M
#endif
625
16.3M
}
626
627
16.3M
bool Value::QuickIsString() const {
628
16.3M
  using A = internal::Address;
629
16.3M
  using I = internal::Internals;
630
16.3M
  A obj = internal::ValueHelper::ValueAsAddress(this);
631
16.3M
  if (!I::HasHeapObjectTag(obj)) return false;
632
#if V8_STATIC_ROOTS_BOOL && !V8_MAP_PACKING
633
  return I::CheckInstanceMapRange(obj, I::StaticReadOnlyRoot::kFirstStringMap,
634
                                  I::StaticReadOnlyRoot::kLastStringMap);
635
#else
636
16.3M
  return (I::GetInstanceType(obj) < I::kFirstNonstringType);
637
16.3M
#endif  // V8_STATIC_ROOTS_BOOL
638
16.3M
}
639
640
0
bool TypecheckWitness::Matches(Local<Value> candidate) const {
641
0
  internal::Address obj = internal::ValueHelper::ValueAsAddress(*candidate);
642
0
  internal::Address obj_map = internal::Internals::LoadMap(obj);
643
0
  internal::Address cached =
644
0
      internal::ValueHelper::ValueAsAddress(*cached_map_);
645
0
  return obj_map == cached;
646
0
}
647
648
}  // namespace v8
649
650
#endif  // INCLUDE_V8_VALUE_H_