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_PRIMITIVE_H_
6 #define INCLUDE_V8_PRIMITIVE_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-value.h" // NOLINT(build/include_directory)
12 #include "v8config.h" // NOLINT(build/include_directory)
13
14 namespace v8 {
15
16 class Context;
17 class Isolate;
18 class String;
19
20 namespace internal {
21 class ExternalString;
22 class ScopedExternalStringLock;
23 } // namespace internal
24
25 /**
26 * The superclass of primitive values. See ECMA-262 4.3.2.
27 */
28 class V8_EXPORT Primitive : public Value {};
29
30 /**
31 * A primitive boolean value (ECMA-262, 4.3.14). Either the true
32 * or false value.
33 */
34 class V8_EXPORT Boolean : public Primitive {
35 public:
36 bool Value() const;
Cast(v8::Data * data)37 V8_INLINE static Boolean* Cast(v8::Data* data) {
38 #ifdef V8_ENABLE_CHECKS
39 CheckCast(data);
40 #endif
41 return static_cast<Boolean*>(data);
42 }
43
44 V8_INLINE static Local<Boolean> New(Isolate* isolate, bool value);
45
46 private:
47 static void CheckCast(v8::Data* that);
48 };
49
50 /**
51 * An array to hold Primitive values. This is used by the embedder to
52 * pass host defined options to the ScriptOptions during compilation.
53 *
54 * This is passed back to the embedder as part of
55 * HostImportModuleDynamicallyCallback for module loading.
56 */
57 class V8_EXPORT PrimitiveArray {
58 public:
59 static Local<PrimitiveArray> New(Isolate* isolate, int length);
60 int Length() const;
61 void Set(Isolate* isolate, int index, Local<Primitive> item);
62 Local<Primitive> Get(Isolate* isolate, int index);
63 };
64
65 /**
66 * A superclass for symbols and strings.
67 */
68 class V8_EXPORT Name : public Primitive {
69 public:
70 /**
71 * Returns the identity hash for this object. The current implementation
72 * uses an inline property on the object to store the identity hash.
73 *
74 * The return value will never be 0. Also, it is not guaranteed to be
75 * unique.
76 */
77 int GetIdentityHash();
78
Cast(Data * data)79 V8_INLINE static Name* Cast(Data* data) {
80 #ifdef V8_ENABLE_CHECKS
81 CheckCast(data);
82 #endif
83 return static_cast<Name*>(data);
84 }
85
86 private:
87 static void CheckCast(Data* that);
88 };
89
90 /**
91 * A flag describing different modes of string creation.
92 *
93 * Aside from performance implications there are no differences between the two
94 * creation modes.
95 */
96 enum class NewStringType {
97 /**
98 * Create a new string, always allocating new storage memory.
99 */
100 kNormal,
101
102 /**
103 * Acts as a hint that the string should be created in the
104 * old generation heap space and be deduplicated if an identical string
105 * already exists.
106 */
107 kInternalized
108 };
109
110 /**
111 * A JavaScript string value (ECMA-262, 4.3.17).
112 */
113 class V8_EXPORT String : public Name {
114 public:
115 static constexpr int kMaxLength =
116 internal::kApiSystemPointerSize == 4 ? (1 << 28) - 16 : (1 << 29) - 24;
117
118 enum Encoding {
119 UNKNOWN_ENCODING = 0x1,
120 TWO_BYTE_ENCODING = 0x0,
121 ONE_BYTE_ENCODING = 0x8
122 };
123 /**
124 * Returns the number of characters (UTF-16 code units) in this string.
125 */
126 int Length() const;
127
128 /**
129 * Returns the number of bytes in the UTF-8 encoded
130 * representation of this string.
131 */
132 int Utf8Length(Isolate* isolate) const;
133
134 /**
135 * Returns whether this string is known to contain only one byte data,
136 * i.e. ISO-8859-1 code points.
137 * Does not read the string.
138 * False negatives are possible.
139 */
140 bool IsOneByte() const;
141
142 /**
143 * Returns whether this string contain only one byte data,
144 * i.e. ISO-8859-1 code points.
145 * Will read the entire string in some cases.
146 */
147 bool ContainsOnlyOneByte() const;
148
149 /**
150 * Write the contents of the string to an external buffer.
151 * If no arguments are given, expects the buffer to be large
152 * enough to hold the entire string and NULL terminator. Copies
153 * the contents of the string and the NULL terminator into the
154 * buffer.
155 *
156 * WriteUtf8 will not write partial UTF-8 sequences, preferring to stop
157 * before the end of the buffer.
158 *
159 * Copies up to length characters into the output buffer.
160 * Only null-terminates if there is enough space in the buffer.
161 *
162 * \param buffer The buffer into which the string will be copied.
163 * \param start The starting position within the string at which
164 * copying begins.
165 * \param length The number of characters to copy from the string. For
166 * WriteUtf8 the number of bytes in the buffer.
167 * \param nchars_ref The number of characters written, can be NULL.
168 * \param options Various options that might affect performance of this or
169 * subsequent operations.
170 * \return The number of characters copied to the buffer excluding the null
171 * terminator. For WriteUtf8: The number of bytes copied to the buffer
172 * including the null terminator (if written).
173 */
174 enum WriteOptions {
175 NO_OPTIONS = 0,
176 HINT_MANY_WRITES_EXPECTED = 1,
177 NO_NULL_TERMINATION = 2,
178 PRESERVE_ONE_BYTE_NULL = 4,
179 // Used by WriteUtf8 to replace orphan surrogate code units with the
180 // unicode replacement character. Needs to be set to guarantee valid UTF-8
181 // output.
182 REPLACE_INVALID_UTF8 = 8
183 };
184
185 // 16-bit character codes.
186 int Write(Isolate* isolate, uint16_t* buffer, int start = 0, int length = -1,
187 int options = NO_OPTIONS) const;
188 // One byte characters.
189 int WriteOneByte(Isolate* isolate, uint8_t* buffer, int start = 0,
190 int length = -1, int options = NO_OPTIONS) const;
191 // UTF-8 encoded characters.
192 int WriteUtf8(Isolate* isolate, char* buffer, int length = -1,
193 int* nchars_ref = nullptr, int options = NO_OPTIONS) const;
194
195 /**
196 * A zero length string.
197 */
198 V8_INLINE static Local<String> Empty(Isolate* isolate);
199
200 /**
201 * Returns true if the string is external.
202 */
203 bool IsExternal() const;
204
205 /**
206 * Returns true if the string is both external and two-byte.
207 */
208 bool IsExternalTwoByte() const;
209
210 /**
211 * Returns true if the string is both external and one-byte.
212 */
213 bool IsExternalOneByte() const;
214
215 class V8_EXPORT ExternalStringResourceBase {
216 public:
217 virtual ~ExternalStringResourceBase() = default;
218
219 /**
220 * If a string is cacheable, the value returned by
221 * ExternalStringResource::data() may be cached, otherwise it is not
222 * expected to be stable beyond the current top-level task.
223 */
IsCacheable()224 virtual bool IsCacheable() const { return true; }
225
226 // Disallow copying and assigning.
227 ExternalStringResourceBase(const ExternalStringResourceBase&) = delete;
228 void operator=(const ExternalStringResourceBase&) = delete;
229
230 protected:
231 ExternalStringResourceBase() = default;
232
233 /**
234 * Internally V8 will call this Dispose method when the external string
235 * resource is no longer needed. The default implementation will use the
236 * delete operator. This method can be overridden in subclasses to
237 * control how allocated external string resources are disposed.
238 */
Dispose()239 virtual void Dispose() { delete this; }
240
241 /**
242 * For a non-cacheable string, the value returned by
243 * |ExternalStringResource::data()| has to be stable between |Lock()| and
244 * |Unlock()|, that is the string must behave as is |IsCacheable()| returned
245 * true.
246 *
247 * These two functions must be thread-safe, and can be called from anywhere.
248 * They also must handle lock depth, in the sense that each can be called
249 * several times, from different threads, and unlocking should only happen
250 * when the balance of Lock() and Unlock() calls is 0.
251 */
Lock()252 virtual void Lock() const {}
253
254 /**
255 * Unlocks the string.
256 */
Unlock()257 virtual void Unlock() const {}
258
259 private:
260 friend class internal::ExternalString;
261 friend class v8::String;
262 friend class internal::ScopedExternalStringLock;
263 };
264
265 /**
266 * An ExternalStringResource is a wrapper around a two-byte string
267 * buffer that resides outside V8's heap. Implement an
268 * ExternalStringResource to manage the life cycle of the underlying
269 * buffer. Note that the string data must be immutable.
270 */
271 class V8_EXPORT ExternalStringResource : public ExternalStringResourceBase {
272 public:
273 /**
274 * Override the destructor to manage the life cycle of the underlying
275 * buffer.
276 */
277 ~ExternalStringResource() override = default;
278
279 /**
280 * The string data from the underlying buffer. If the resource is cacheable
281 * then data() must return the same value for all invocations.
282 */
283 virtual const uint16_t* data() const = 0;
284
285 /**
286 * The length of the string. That is, the number of two-byte characters.
287 */
288 virtual size_t length() const = 0;
289
290 /**
291 * Returns the cached data from the underlying buffer. This method can be
292 * called only for cacheable resources (i.e. IsCacheable() == true) and only
293 * after UpdateDataCache() was called.
294 */
cached_data()295 const uint16_t* cached_data() const {
296 CheckCachedDataInvariants();
297 return cached_data_;
298 }
299
300 /**
301 * Update {cached_data_} with the data from the underlying buffer. This can
302 * be called only for cacheable resources.
303 */
304 void UpdateDataCache();
305
306 protected:
307 ExternalStringResource() = default;
308
309 private:
310 void CheckCachedDataInvariants() const;
311
312 const uint16_t* cached_data_ = nullptr;
313 };
314
315 /**
316 * An ExternalOneByteStringResource is a wrapper around an one-byte
317 * string buffer that resides outside V8's heap. Implement an
318 * ExternalOneByteStringResource to manage the life cycle of the
319 * underlying buffer. Note that the string data must be immutable
320 * and that the data must be Latin-1 and not UTF-8, which would require
321 * special treatment internally in the engine and do not allow efficient
322 * indexing. Use String::New or convert to 16 bit data for non-Latin1.
323 */
324
325 class V8_EXPORT ExternalOneByteStringResource
326 : public ExternalStringResourceBase {
327 public:
328 /**
329 * Override the destructor to manage the life cycle of the underlying
330 * buffer.
331 */
332 ~ExternalOneByteStringResource() override = default;
333
334 /**
335 * The string data from the underlying buffer. If the resource is cacheable
336 * then data() must return the same value for all invocations.
337 */
338 virtual const char* data() const = 0;
339
340 /** The number of Latin-1 characters in the string.*/
341 virtual size_t length() const = 0;
342
343 /**
344 * Returns the cached data from the underlying buffer. If the resource is
345 * uncacheable or if UpdateDataCache() was not called before, it has
346 * undefined behaviour.
347 */
cached_data()348 const char* cached_data() const {
349 CheckCachedDataInvariants();
350 return cached_data_;
351 }
352
353 /**
354 * Update {cached_data_} with the data from the underlying buffer. This can
355 * be called only for cacheable resources.
356 */
357 void UpdateDataCache();
358
359 protected:
360 ExternalOneByteStringResource() = default;
361
362 private:
363 void CheckCachedDataInvariants() const;
364
365 const char* cached_data_ = nullptr;
366 };
367
368 /**
369 * If the string is an external string, return the ExternalStringResourceBase
370 * regardless of the encoding, otherwise return NULL. The encoding of the
371 * string is returned in encoding_out.
372 */
373 V8_INLINE ExternalStringResourceBase* GetExternalStringResourceBase(
374 Encoding* encoding_out) const;
375
376 /**
377 * Get the ExternalStringResource for an external string. Returns
378 * NULL if IsExternal() doesn't return true.
379 */
380 V8_INLINE ExternalStringResource* GetExternalStringResource() const;
381
382 /**
383 * Get the ExternalOneByteStringResource for an external one-byte string.
384 * Returns NULL if IsExternalOneByte() doesn't return true.
385 */
386 const ExternalOneByteStringResource* GetExternalOneByteStringResource() const;
387
Cast(v8::Data * data)388 V8_INLINE static String* Cast(v8::Data* data) {
389 #ifdef V8_ENABLE_CHECKS
390 CheckCast(data);
391 #endif
392 return static_cast<String*>(data);
393 }
394
395 /**
396 * Allocates a new string from a UTF-8 literal. This is equivalent to calling
397 * String::NewFromUtf(isolate, "...").ToLocalChecked(), but without the check
398 * overhead.
399 *
400 * When called on a string literal containing '\0', the inferred length is the
401 * length of the input array minus 1 (for the final '\0') and not the value
402 * returned by strlen.
403 **/
404 template <int N>
405 static V8_WARN_UNUSED_RESULT Local<String> NewFromUtf8Literal(
406 Isolate* isolate, const char (&literal)[N],
407 NewStringType type = NewStringType::kNormal) {
408 static_assert(N <= kMaxLength, "String is too long");
409 return NewFromUtf8Literal(isolate, literal, type, N - 1);
410 }
411
412 /** Allocates a new string from UTF-8 data. Only returns an empty value when
413 * length > kMaxLength. **/
414 static V8_WARN_UNUSED_RESULT MaybeLocal<String> NewFromUtf8(
415 Isolate* isolate, const char* data,
416 NewStringType type = NewStringType::kNormal, int length = -1);
417
418 /** Allocates a new string from Latin-1 data. Only returns an empty value
419 * when length > kMaxLength. **/
420 static V8_WARN_UNUSED_RESULT MaybeLocal<String> NewFromOneByte(
421 Isolate* isolate, const uint8_t* data,
422 NewStringType type = NewStringType::kNormal, int length = -1);
423
424 /** Allocates a new string from UTF-16 data. Only returns an empty value when
425 * length > kMaxLength. **/
426 static V8_WARN_UNUSED_RESULT MaybeLocal<String> NewFromTwoByte(
427 Isolate* isolate, const uint16_t* data,
428 NewStringType type = NewStringType::kNormal, int length = -1);
429
430 /**
431 * Creates a new string by concatenating the left and the right strings
432 * passed in as parameters.
433 */
434 static Local<String> Concat(Isolate* isolate, Local<String> left,
435 Local<String> right);
436
437 /**
438 * Creates a new external string using the data defined in the given
439 * resource. When the external string is no longer live on V8's heap the
440 * resource will be disposed by calling its Dispose method. The caller of
441 * this function should not otherwise delete or modify the resource. Neither
442 * should the underlying buffer be deallocated or modified except through the
443 * destructor of the external string resource.
444 */
445 static V8_WARN_UNUSED_RESULT MaybeLocal<String> NewExternalTwoByte(
446 Isolate* isolate, ExternalStringResource* resource);
447
448 /**
449 * Associate an external string resource with this string by transforming it
450 * in place so that existing references to this string in the JavaScript heap
451 * will use the external string resource. The external string resource's
452 * character contents need to be equivalent to this string.
453 * Returns true if the string has been changed to be an external string.
454 * The string is not modified if the operation fails. See NewExternal for
455 * information on the lifetime of the resource.
456 */
457 bool MakeExternal(ExternalStringResource* resource);
458
459 /**
460 * Creates a new external string using the one-byte data defined in the given
461 * resource. When the external string is no longer live on V8's heap the
462 * resource will be disposed by calling its Dispose method. The caller of
463 * this function should not otherwise delete or modify the resource. Neither
464 * should the underlying buffer be deallocated or modified except through the
465 * destructor of the external string resource.
466 */
467 static V8_WARN_UNUSED_RESULT MaybeLocal<String> NewExternalOneByte(
468 Isolate* isolate, ExternalOneByteStringResource* resource);
469
470 /**
471 * Associate an external string resource with this string by transforming it
472 * in place so that existing references to this string in the JavaScript heap
473 * will use the external string resource. The external string resource's
474 * character contents need to be equivalent to this string.
475 * Returns true if the string has been changed to be an external string.
476 * The string is not modified if the operation fails. See NewExternal for
477 * information on the lifetime of the resource.
478 */
479 bool MakeExternal(ExternalOneByteStringResource* resource);
480
481 /**
482 * Returns true if this string can be made external.
483 */
484 bool CanMakeExternal() const;
485
486 /**
487 * Returns true if the strings values are equal. Same as JS ==/===.
488 */
489 bool StringEquals(Local<String> str) const;
490
491 /**
492 * Converts an object to a UTF-8-encoded character array. Useful if
493 * you want to print the object. If conversion to a string fails
494 * (e.g. due to an exception in the toString() method of the object)
495 * then the length() method returns 0 and the * operator returns
496 * NULL.
497 */
498 class V8_EXPORT Utf8Value {
499 public:
500 Utf8Value(Isolate* isolate, Local<v8::Value> obj);
501 ~Utf8Value();
502 char* operator*() { return str_; }
503 const char* operator*() const { return str_; }
length()504 int length() const { return length_; }
505
506 // Disallow copying and assigning.
507 Utf8Value(const Utf8Value&) = delete;
508 void operator=(const Utf8Value&) = delete;
509
510 private:
511 char* str_;
512 int length_;
513 };
514
515 /**
516 * Converts an object to a two-byte (UTF-16-encoded) string.
517 * If conversion to a string fails (eg. due to an exception in the toString()
518 * method of the object) then the length() method returns 0 and the * operator
519 * returns NULL.
520 */
521 class V8_EXPORT Value {
522 public:
523 Value(Isolate* isolate, Local<v8::Value> obj);
524 ~Value();
525 uint16_t* operator*() { return str_; }
526 const uint16_t* operator*() const { return str_; }
length()527 int length() const { return length_; }
528
529 // Disallow copying and assigning.
530 Value(const Value&) = delete;
531 void operator=(const Value&) = delete;
532
533 private:
534 uint16_t* str_;
535 int length_;
536 };
537
538 private:
539 void VerifyExternalStringResourceBase(ExternalStringResourceBase* v,
540 Encoding encoding) const;
541 void VerifyExternalStringResource(ExternalStringResource* val) const;
542 ExternalStringResource* GetExternalStringResourceSlow() const;
543 ExternalStringResourceBase* GetExternalStringResourceBaseSlow(
544 String::Encoding* encoding_out) const;
545
546 static Local<v8::String> NewFromUtf8Literal(Isolate* isolate,
547 const char* literal,
548 NewStringType type, int length);
549
550 static void CheckCast(v8::Data* that);
551 };
552
553 // Zero-length string specialization (templated string size includes
554 // terminator).
555 template <>
NewFromUtf8Literal(Isolate * isolate,const char (& literal)[1],NewStringType type)556 inline V8_WARN_UNUSED_RESULT Local<String> String::NewFromUtf8Literal(
557 Isolate* isolate, const char (&literal)[1], NewStringType type) {
558 return String::Empty(isolate);
559 }
560
561 /**
562 * Interface for iterating through all external resources in the heap.
563 */
564 class V8_EXPORT ExternalResourceVisitor {
565 public:
566 virtual ~ExternalResourceVisitor() = default;
VisitExternalString(Local<String> string)567 virtual void VisitExternalString(Local<String> string) {}
568 };
569
570 /**
571 * A JavaScript symbol (ECMA-262 edition 6)
572 */
573 class V8_EXPORT Symbol : public Name {
574 public:
575 /**
576 * Returns the description string of the symbol, or undefined if none.
577 */
578 V8_DEPRECATE_SOON("Use Symbol::Description(isolate)")
579 Local<Value> Description() const;
580 Local<Value> Description(Isolate* isolate) const;
581
582 /**
583 * Create a symbol. If description is not empty, it will be used as the
584 * description.
585 */
586 static Local<Symbol> New(Isolate* isolate,
587 Local<String> description = Local<String>());
588
589 /**
590 * Access global symbol registry.
591 * Note that symbols created this way are never collected, so
592 * they should only be used for statically fixed properties.
593 * Also, there is only one global name space for the descriptions used as
594 * keys.
595 * To minimize the potential for clashes, use qualified names as keys.
596 */
597 static Local<Symbol> For(Isolate* isolate, Local<String> description);
598
599 /**
600 * Retrieve a global symbol. Similar to |For|, but using a separate
601 * registry that is not accessible by (and cannot clash with) JavaScript code.
602 */
603 static Local<Symbol> ForApi(Isolate* isolate, Local<String> description);
604
605 // Well-known symbols
606 static Local<Symbol> GetAsyncIterator(Isolate* isolate);
607 static Local<Symbol> GetHasInstance(Isolate* isolate);
608 static Local<Symbol> GetIsConcatSpreadable(Isolate* isolate);
609 static Local<Symbol> GetIterator(Isolate* isolate);
610 static Local<Symbol> GetMatch(Isolate* isolate);
611 static Local<Symbol> GetReplace(Isolate* isolate);
612 static Local<Symbol> GetSearch(Isolate* isolate);
613 static Local<Symbol> GetSplit(Isolate* isolate);
614 static Local<Symbol> GetToPrimitive(Isolate* isolate);
615 static Local<Symbol> GetToStringTag(Isolate* isolate);
616 static Local<Symbol> GetUnscopables(Isolate* isolate);
617
Cast(Data * data)618 V8_INLINE static Symbol* Cast(Data* data) {
619 #ifdef V8_ENABLE_CHECKS
620 CheckCast(data);
621 #endif
622 return static_cast<Symbol*>(data);
623 }
624
625 private:
626 Symbol();
627 static void CheckCast(Data* that);
628 };
629
630 /**
631 * A JavaScript number value (ECMA-262, 4.3.20)
632 */
633 class V8_EXPORT Number : public Primitive {
634 public:
635 double Value() const;
636 static Local<Number> New(Isolate* isolate, double value);
Cast(v8::Data * data)637 V8_INLINE static Number* Cast(v8::Data* data) {
638 #ifdef V8_ENABLE_CHECKS
639 CheckCast(data);
640 #endif
641 return static_cast<Number*>(data);
642 }
643
644 private:
645 Number();
646 static void CheckCast(v8::Data* that);
647 };
648
649 /**
650 * A JavaScript value representing a signed integer.
651 */
652 class V8_EXPORT Integer : public Number {
653 public:
654 static Local<Integer> New(Isolate* isolate, int32_t value);
655 static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value);
656 int64_t Value() const;
Cast(v8::Data * data)657 V8_INLINE static Integer* Cast(v8::Data* data) {
658 #ifdef V8_ENABLE_CHECKS
659 CheckCast(data);
660 #endif
661 return static_cast<Integer*>(data);
662 }
663
664 private:
665 Integer();
666 static void CheckCast(v8::Data* that);
667 };
668
669 /**
670 * A JavaScript value representing a 32-bit signed integer.
671 */
672 class V8_EXPORT Int32 : public Integer {
673 public:
674 int32_t Value() const;
Cast(v8::Data * data)675 V8_INLINE static Int32* Cast(v8::Data* data) {
676 #ifdef V8_ENABLE_CHECKS
677 CheckCast(data);
678 #endif
679 return static_cast<Int32*>(data);
680 }
681
682 private:
683 Int32();
684 static void CheckCast(v8::Data* that);
685 };
686
687 /**
688 * A JavaScript value representing a 32-bit unsigned integer.
689 */
690 class V8_EXPORT Uint32 : public Integer {
691 public:
692 uint32_t Value() const;
Cast(v8::Data * data)693 V8_INLINE static Uint32* Cast(v8::Data* data) {
694 #ifdef V8_ENABLE_CHECKS
695 CheckCast(data);
696 #endif
697 return static_cast<Uint32*>(data);
698 }
699
700 private:
701 Uint32();
702 static void CheckCast(v8::Data* that);
703 };
704
705 /**
706 * A JavaScript BigInt value (https://tc39.github.io/proposal-bigint)
707 */
708 class V8_EXPORT BigInt : public Primitive {
709 public:
710 static Local<BigInt> New(Isolate* isolate, int64_t value);
711 static Local<BigInt> NewFromUnsigned(Isolate* isolate, uint64_t value);
712 /**
713 * Creates a new BigInt object using a specified sign bit and a
714 * specified list of digits/words.
715 * The resulting number is calculated as:
716 *
717 * (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...)
718 */
719 static MaybeLocal<BigInt> NewFromWords(Local<Context> context, int sign_bit,
720 int word_count, const uint64_t* words);
721
722 /**
723 * Returns the value of this BigInt as an unsigned 64-bit integer.
724 * If `lossless` is provided, it will reflect whether the return value was
725 * truncated or wrapped around. In particular, it is set to `false` if this
726 * BigInt is negative.
727 */
728 uint64_t Uint64Value(bool* lossless = nullptr) const;
729
730 /**
731 * Returns the value of this BigInt as a signed 64-bit integer.
732 * If `lossless` is provided, it will reflect whether this BigInt was
733 * truncated or not.
734 */
735 int64_t Int64Value(bool* lossless = nullptr) const;
736
737 /**
738 * Returns the number of 64-bit words needed to store the result of
739 * ToWordsArray().
740 */
741 int WordCount() const;
742
743 /**
744 * Writes the contents of this BigInt to a specified memory location.
745 * `sign_bit` must be provided and will be set to 1 if this BigInt is
746 * negative.
747 * `*word_count` has to be initialized to the length of the `words` array.
748 * Upon return, it will be set to the actual number of words that would
749 * be needed to store this BigInt (i.e. the return value of `WordCount()`).
750 */
751 void ToWordsArray(int* sign_bit, int* word_count, uint64_t* words) const;
752
Cast(v8::Data * data)753 V8_INLINE static BigInt* Cast(v8::Data* data) {
754 #ifdef V8_ENABLE_CHECKS
755 CheckCast(data);
756 #endif
757 return static_cast<BigInt*>(data);
758 }
759
760 private:
761 BigInt();
762 static void CheckCast(v8::Data* that);
763 };
764
Empty(Isolate * isolate)765 Local<String> String::Empty(Isolate* isolate) {
766 using S = internal::Address;
767 using I = internal::Internals;
768 I::CheckInitialized(isolate);
769 S* slot = I::GetRoot(isolate, I::kEmptyStringRootIndex);
770 return Local<String>(reinterpret_cast<String*>(slot));
771 }
772
GetExternalStringResource()773 String::ExternalStringResource* String::GetExternalStringResource() const {
774 using A = internal::Address;
775 using I = internal::Internals;
776 A obj = *reinterpret_cast<const A*>(this);
777
778 ExternalStringResource* result;
779 if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
780 internal::Isolate* isolate = I::GetIsolateForHeapSandbox(obj);
781 A value =
782 I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset,
783 internal::kExternalStringResourceTag);
784 result = reinterpret_cast<String::ExternalStringResource*>(value);
785 } else {
786 result = GetExternalStringResourceSlow();
787 }
788 #ifdef V8_ENABLE_CHECKS
789 VerifyExternalStringResource(result);
790 #endif
791 return result;
792 }
793
GetExternalStringResourceBase(String::Encoding * encoding_out)794 String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
795 String::Encoding* encoding_out) const {
796 using A = internal::Address;
797 using I = internal::Internals;
798 A obj = *reinterpret_cast<const A*>(this);
799 int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
800 *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
801 ExternalStringResourceBase* resource;
802 if (type == I::kExternalOneByteRepresentationTag ||
803 type == I::kExternalTwoByteRepresentationTag) {
804 internal::Isolate* isolate = I::GetIsolateForHeapSandbox(obj);
805 A value =
806 I::ReadExternalPointerField(isolate, obj, I::kStringResourceOffset,
807 internal::kExternalStringResourceTag);
808 resource = reinterpret_cast<ExternalStringResourceBase*>(value);
809 } else {
810 resource = GetExternalStringResourceBaseSlow(encoding_out);
811 }
812 #ifdef V8_ENABLE_CHECKS
813 VerifyExternalStringResourceBase(resource, *encoding_out);
814 #endif
815 return resource;
816 }
817
818 // --- Statics ---
819
Undefined(Isolate * isolate)820 V8_INLINE Local<Primitive> Undefined(Isolate* isolate) {
821 using S = internal::Address;
822 using I = internal::Internals;
823 I::CheckInitialized(isolate);
824 S* slot = I::GetRoot(isolate, I::kUndefinedValueRootIndex);
825 return Local<Primitive>(reinterpret_cast<Primitive*>(slot));
826 }
827
Null(Isolate * isolate)828 V8_INLINE Local<Primitive> Null(Isolate* isolate) {
829 using S = internal::Address;
830 using I = internal::Internals;
831 I::CheckInitialized(isolate);
832 S* slot = I::GetRoot(isolate, I::kNullValueRootIndex);
833 return Local<Primitive>(reinterpret_cast<Primitive*>(slot));
834 }
835
True(Isolate * isolate)836 V8_INLINE Local<Boolean> True(Isolate* isolate) {
837 using S = internal::Address;
838 using I = internal::Internals;
839 I::CheckInitialized(isolate);
840 S* slot = I::GetRoot(isolate, I::kTrueValueRootIndex);
841 return Local<Boolean>(reinterpret_cast<Boolean*>(slot));
842 }
843
False(Isolate * isolate)844 V8_INLINE Local<Boolean> False(Isolate* isolate) {
845 using S = internal::Address;
846 using I = internal::Internals;
847 I::CheckInitialized(isolate);
848 S* slot = I::GetRoot(isolate, I::kFalseValueRootIndex);
849 return Local<Boolean>(reinterpret_cast<Boolean*>(slot));
850 }
851
New(Isolate * isolate,bool value)852 Local<Boolean> Boolean::New(Isolate* isolate, bool value) {
853 return value ? True(isolate) : False(isolate);
854 }
855
856 } // namespace v8
857
858 #endif // INCLUDE_V8_PRIMITIVE_H_
859