• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_TAGGED_VALUE_INL_H
17 #define ECMASCRIPT_TAGGED_VALUE_INL_H
18 
19 #include "ecmascript/js_tagged_value.h"
20 
21 #include "ecmascript/accessor_data.h"
22 #include "ecmascript/base/error_helper.h"
23 #include "ecmascript/base/number_helper.h"
24 #include "ecmascript/base/string_helper.h"
25 #include "ecmascript/ecma_macros.h"
26 #include "ecmascript/ecma_runtime_call_info.h"
27 #include "ecmascript/ecma_string-inl.h"
28 #include "ecmascript/js_bigint.h"
29 #include "ecmascript/js_hclass-inl.h"
30 #include "ecmascript/js_object.h"
31 #include "ecmascript/js_proxy.h"
32 #include "ecmascript/js_symbol.h"
33 #include "ecmascript/js_tagged_number.h"
34 #include "ecmascript/js_thread.h"
35 #include "ecmascript/mem/c_containers.h"
36 #include "ecmascript/mem/tagged_object-inl.h"
37 #include "ecmascript/object_factory.h"
38 
39 namespace panda::ecmascript {
40 // ecma6 7.1 Type Conversion
41 static constexpr double SAFE_NUMBER = 9007199254740991LL;
42 static constexpr uint32_t MAX_INDEX_LEN = 10;
43 
ToBoolean()44 inline bool JSTaggedValue::ToBoolean() const
45 {
46     if (IsInt()) {
47         return GetInt() != 0;
48     }
49     if (IsDouble()) {
50         double d = GetDouble();
51         return !std::isnan(d) && d != 0;
52     }
53     switch (GetRawData()) {
54         case JSTaggedValue::VALUE_UNDEFINED:
55             [[fallthrough]];
56         case JSTaggedValue::VALUE_HOLE:
57             [[fallthrough]];
58         case JSTaggedValue::VALUE_NULL:
59             [[fallthrough]];
60         case JSTaggedValue::VALUE_FALSE: {
61             return false;
62         }
63         case JSTaggedValue::VALUE_TRUE: {
64             return true;
65         }
66         default: {
67             break;
68         }
69     }
70 
71     if (IsBigInt()) {
72         BigInt *bigint = BigInt::Cast(GetTaggedObject());
73         return !bigint->IsZero();
74     }
75     if (IsHeapObject()) {
76         TaggedObject *obj = GetTaggedObject();
77         if (IsString()) {
78             auto str = static_cast<EcmaString *>(obj);
79             return str->GetLength() != 0;
80         }
81         return true;
82     }
83 
84     UNREACHABLE();
85 }
86 
ToNumber(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)87 inline JSTaggedNumber JSTaggedValue::ToNumber(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
88 {
89     if (tagged->IsInt() || tagged->IsDouble()) {
90         return JSTaggedNumber(tagged.GetTaggedValue());
91     }
92 
93     switch (tagged->GetRawData()) {
94         case JSTaggedValue::VALUE_UNDEFINED:
95         case JSTaggedValue::VALUE_HOLE: {
96             return JSTaggedNumber(base::NAN_VALUE);
97         }
98         case JSTaggedValue::VALUE_TRUE: {
99             return JSTaggedNumber(1);
100         }
101         case JSTaggedValue::VALUE_FALSE:
102         case JSTaggedValue::VALUE_NULL: {
103             return JSTaggedNumber(0);
104         }
105         default: {
106             break;
107         }
108     }
109 
110     if (tagged->IsString()) {
111         Span<const uint8_t> str;
112         auto strObj = static_cast<EcmaString *>(tagged->GetTaggedObject());
113         size_t strLen = strObj->GetLength();
114         if (strLen == 0) {
115             return JSTaggedNumber(0);
116         }
117         [[maybe_unused]] CVector<uint8_t> buf;  // Span will use buf.data(), shouldn't define inside 'if'
118         if (UNLIKELY(strObj->IsUtf16())) {
119             size_t len = base::utf_helper::Utf16ToUtf8Size(strObj->GetDataUtf16(), strLen) - 1;
120             buf.reserve(len);
121             len = base::utf_helper::ConvertRegionUtf16ToUtf8(strObj->GetDataUtf16(), buf.data(), strLen, len, 0);
122             str = Span<const uint8_t>(buf.data(), len);
123         } else {
124             str = Span<const uint8_t>(strObj->GetDataUtf8(), strLen);
125         }
126         double d = base::NumberHelper::StringToDouble(str.begin(), str.end(), 0,
127                                                       base::ALLOW_BINARY + base::ALLOW_OCTAL + base::ALLOW_HEX);
128         return JSTaggedNumber(d);
129     }
130     if (tagged->IsECMAObject()) {
131         JSHandle<JSTaggedValue> primValue(thread, ToPrimitive(thread, tagged, PREFER_NUMBER));
132         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedNumber::Exception());
133         return ToNumber(thread, primValue);
134     }
135     if (tagged->IsSymbol()) {
136         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Symbol value to a number", JSTaggedNumber::Exception());
137     }
138     if (tagged->IsBigInt()) {
139         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a BigInt value to a number", JSTaggedNumber::Exception());
140     }
141     THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Unknown value to a number", JSTaggedNumber::Exception());
142 }
143 
ToBigInt(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)144 inline JSTaggedValue JSTaggedValue::ToBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
145 {
146     JSHandle<JSTaggedValue> primValue(thread, ToPrimitive(thread, tagged));
147     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
148     switch (primValue->GetRawData()) {
149         case JSTaggedValue::VALUE_UNDEFINED:
150         case JSTaggedValue::VALUE_NULL: {
151             THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a undefine or null value to a BigInt",
152                                         JSTaggedValue::Exception());
153         }
154         case JSTaggedValue::VALUE_TRUE: {
155             return BigInt::Int32ToBigInt(thread, 1).GetTaggedValue();
156         }
157         case JSTaggedValue::VALUE_FALSE: {
158             return BigInt::Int32ToBigInt(thread, 0).GetTaggedValue();
159         }
160         default: {
161             break;
162         }
163     }
164 
165     if (primValue->IsNumber()) {
166         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Number value to a BigInt", JSTaggedNumber::Exception());
167     }
168     if (primValue->IsString()) {
169         JSHandle<JSTaggedValue> value(thread, base::NumberHelper::StringToBigInt(thread, primValue));
170         if (value->IsBigInt()) {
171             return value.GetTaggedValue();
172         }
173         THROW_SYNTAX_ERROR_AND_RETURN(thread, "Cannot convert string to a BigInt,"
174                                       "because not allow Infinity, decimal points, or exponents",
175                                       JSTaggedValue::Exception());
176     }
177     if (primValue->IsSymbol()) {
178         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Symbol value to a BigInt", JSTaggedNumber::Exception());
179     }
180     if (primValue->IsBigInt()) {
181         return primValue.GetTaggedValue();
182     }
183     THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Unknown value to a BigInt", JSTaggedNumber::Exception());
184 }
185 
ToBigInt64(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)186 inline JSTaggedValue JSTaggedValue::ToBigInt64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
187 {
188     JSHandle<BigInt> value(thread, ToBigInt(thread, tagged));
189     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
190     JSHandle<BigInt> exponent = BigInt::Int32ToBigInt(thread, 64); // 64 : bits
191     JSHandle<BigInt> exponentone = BigInt::Int32ToBigInt(thread, 63); // 63 : bits
192     JSHandle<BigInt> base = BigInt::Int32ToBigInt(thread, 2); // 2 : base value
193     JSHandle<BigInt> tVal  = BigInt::Exponentiate(thread, base, exponent);
194     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
195     JSHandle<BigInt> int64bitVal = BigInt::FloorMod(thread, value, tVal);
196     JSHandle<BigInt> resValue = BigInt::Exponentiate(thread, base, exponentone);
197     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
198     if (!BigInt::LessThan(int64bitVal.GetTaggedValue(), resValue.GetTaggedValue())) {
199         return BigInt::Subtract(thread, int64bitVal, tVal).GetTaggedValue();
200     } else {
201         return int64bitVal.GetTaggedValue();
202     }
203 }
204 
ToBigUint64(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)205 inline JSTaggedValue JSTaggedValue::ToBigUint64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
206 {
207     JSHandle<BigInt> value(thread, ToBigInt(thread, tagged));
208     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
209     JSHandle<BigInt> exponent = BigInt::Int32ToBigInt(thread, 64); // 64 : exponet value
210     JSHandle<BigInt> base = BigInt::Int32ToBigInt(thread, 2); // 2 : base value
211     JSHandle<BigInt> tVal = BigInt::Exponentiate(thread, base, exponent);
212     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
213     return BigInt::FloorMod(thread, value, tVal).GetTaggedValue();
214 }
215 
ToInteger(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)216 inline JSTaggedNumber JSTaggedValue::ToInteger(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
217 {
218     JSTaggedNumber number = ToNumber(thread, tagged);
219     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedNumber::Exception());
220 
221     return JSTaggedNumber(base::NumberHelper::TruncateDouble(number.GetNumber()));
222 }
223 
ToInt32(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)224 inline int32_t JSTaggedValue::ToInt32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
225 {
226     JSTaggedNumber number = ToNumber(thread, tagged);
227     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
228     return base::NumberHelper::DoubleToInt(number.GetNumber(), base::INT32_BITS);
229 }
230 
ToUint32(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)231 inline uint32_t JSTaggedValue::ToUint32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
232 {
233     return ToInt32(thread, tagged);
234 }
235 
ToInt16(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)236 inline int16_t JSTaggedValue::ToInt16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
237 {
238     JSTaggedNumber number = ToNumber(thread, tagged);
239     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
240 
241     return base::NumberHelper::DoubleToInt(number.GetNumber(), base::INT16_BITS);
242 }
243 
ToUint16(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)244 inline uint16_t JSTaggedValue::ToUint16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
245 {
246     return ToInt16(thread, tagged);
247 }
248 
ToInt8(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)249 inline int8_t JSTaggedValue::ToInt8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
250 {
251     JSTaggedNumber number = ToNumber(thread, tagged);
252     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
253 
254     return base::NumberHelper::DoubleToInt(number.GetNumber(), base::INT8_BITS);
255 }
256 
ToUint8(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)257 inline uint8_t JSTaggedValue::ToUint8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
258 {
259     return ToInt8(thread, tagged);
260 }
261 
ToUint8Clamp(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)262 inline uint8_t JSTaggedValue::ToUint8Clamp(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
263 {
264     JSTaggedNumber number = ToNumber(thread, tagged);
265     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
266 
267     double d = number.GetNumber();
268     if (std::isnan(d) || d <= 0) {
269         return 0;
270     }
271     if (d >= UINT8_MAX) {
272         return UINT8_MAX;
273     }
274 
275     return lrint(d);
276 }
277 
ToLength(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)278 inline JSTaggedNumber JSTaggedValue::ToLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
279 {
280     JSTaggedNumber len = ToInteger(thread, tagged);
281     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedNumber::Exception());
282     if (len.GetNumber() < 0.0) {
283         return JSTaggedNumber(static_cast<double>(0));
284     }
285     if (len.GetNumber() > SAFE_NUMBER) {
286         return JSTaggedNumber(static_cast<double>(SAFE_NUMBER));
287     }
288     return len;
289 }
290 
291 // ecma6 7.2 Testing and Comparison Operations
RequireObjectCoercible(JSThread * thread,const JSHandle<JSTaggedValue> & tagged)292 inline JSHandle<JSTaggedValue> JSTaggedValue::RequireObjectCoercible(JSThread *thread,
293                                                                      const JSHandle<JSTaggedValue> &tagged)
294 {
295     if (tagged->IsUndefined() || tagged->IsNull()) {
296         THROW_TYPE_ERROR_AND_RETURN(thread, "RequireObjectCoercible",
297                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
298     }
299     return tagged;
300 }
301 
IsCallable()302 inline bool JSTaggedValue::IsCallable() const
303 {
304     return IsHeapObject() && GetTaggedObject()->GetClass()->IsCallable();
305 }
306 
IsConstructor()307 inline bool JSTaggedValue::IsConstructor() const
308 {
309     return IsHeapObject() && GetTaggedObject()->GetClass()->IsConstructor();
310 }
311 
IsExtensible(JSThread * thread)312 inline bool JSTaggedValue::IsExtensible(JSThread *thread) const
313 {
314     if (UNLIKELY(IsJSProxy())) {
315         return JSProxy::IsExtensible(thread, JSHandle<JSProxy>(thread, *this));
316     }
317 
318     return IsHeapObject() && GetTaggedObject()->GetClass()->IsExtensible();
319 }
320 
IsClassConstructor()321 inline bool JSTaggedValue::IsClassConstructor() const
322 {
323     return IsHeapObject() && GetTaggedObject()->GetClass()->IsClassConstructor();
324 }
325 
IsClassPrototype()326 inline bool JSTaggedValue::IsClassPrototype() const
327 {
328     return IsHeapObject() && GetTaggedObject()->GetClass()->IsClassPrototype();
329 }
330 
IsPropertyKey(const JSHandle<JSTaggedValue> & key)331 inline bool JSTaggedValue::IsPropertyKey(const JSHandle<JSTaggedValue> &key)
332 {
333     return key->IsStringOrSymbol() || key->IsNumber();
334 }
335 
SameValue(const JSTaggedValue & x,const JSTaggedValue & y)336 inline bool JSTaggedValue::SameValue(const JSTaggedValue &x, const JSTaggedValue &y)
337 {
338     // same object or special type must be same value
339     if (x == y) {
340         return true;
341     }
342     if (x.IsNumber() && y.IsNumber()) {
343         return SameValueNumberic(x, y);
344     }
345     if (x.IsString() && y.IsString()) {
346         return EcmaString::StringsAreEqual(static_cast<EcmaString *>(x.GetTaggedObject()),
347                                            static_cast<EcmaString *>(y.GetTaggedObject()));
348     }
349     if (x.IsBigInt() && y.IsBigInt()) {
350         return BigInt::SameValue(x, y);
351     }
352     return false;
353 }
354 
SameValue(const JSHandle<JSTaggedValue> & xHandle,const JSHandle<JSTaggedValue> & yHandle)355 inline bool JSTaggedValue::SameValue(const JSHandle<JSTaggedValue> &xHandle, const JSHandle<JSTaggedValue> &yHandle)
356 {
357     return SameValue(xHandle.GetTaggedValue(), yHandle.GetTaggedValue());
358 }
359 
SameValueZero(const JSTaggedValue & x,const JSTaggedValue & y)360 inline bool JSTaggedValue::SameValueZero(const JSTaggedValue &x, const JSTaggedValue &y)
361 {
362     if (x == y) {
363         return true;
364     }
365 
366     if (x.IsNumber() && y.IsNumber()) {
367         double xValue = x.ExtractNumber();
368         double yValue = y.ExtractNumber();
369         // Compare xValue with yValue to deal with -0.0
370         return (xValue == yValue) || (std::isnan(xValue) && std::isnan(yValue));
371     }
372 
373     if (x.IsString() && y.IsString()) {
374         return EcmaString::StringsAreEqual(static_cast<EcmaString *>(x.GetTaggedObject()),
375                                            static_cast<EcmaString *>(y.GetTaggedObject()));
376     }
377     if (x.IsBigInt() && y.IsBigInt()) {
378         return BigInt::SameValueZero(x, y);
379     }
380     return false;
381 }
382 
SameValueNumberic(const JSTaggedValue & x,const JSTaggedValue & y)383 inline bool JSTaggedValue::SameValueNumberic(const JSTaggedValue &x, const JSTaggedValue &y)
384 {
385     double xValue = x.ExtractNumber();
386     double yValue = y.ExtractNumber();
387     // SameNumberValue(NaN, NaN) is true.
388     if (xValue != yValue) {
389         return std::isnan(xValue) && std::isnan(yValue);
390     }
391     // SameNumberValue(0.0, -0.0) is false.
392     return (std::signbit(xValue) == std::signbit(yValue));
393 }
394 
Less(JSThread * thread,const JSHandle<JSTaggedValue> & x,const JSHandle<JSTaggedValue> & y)395 inline bool JSTaggedValue::Less(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y)
396 {
397     ComparisonResult result = Compare(thread, x, y);
398     return result == ComparisonResult::LESS;
399 }
400 
StrictNumberEquals(double x,double y)401 inline bool JSTaggedValue::StrictNumberEquals(double x, double y)
402 {
403     // Must check explicitly for NaN's on Windows, but -0 works fine.
404     if (std::isnan(x) || std::isnan(y)) {
405         return false;
406     }
407     return x == y;
408 }
409 
StrictEqual(const JSThread * thread,const JSHandle<JSTaggedValue> & x,const JSHandle<JSTaggedValue> & y)410 inline bool JSTaggedValue::StrictEqual([[maybe_unused]] const JSThread *thread, const JSHandle<JSTaggedValue> &x,
411                                        const JSHandle<JSTaggedValue> &y)
412 {
413     if (x->IsNumber() && y->IsNumber()) {
414         return StrictNumberEquals(x->ExtractNumber(), y->ExtractNumber());
415     }
416 
417     if (x.GetTaggedValue() == y.GetTaggedValue()) {
418         return true;
419     }
420     if (x->IsString() && y->IsString()) {
421         return EcmaString::StringsAreEqual(x.GetObject<EcmaString>(), y.GetObject<EcmaString>());
422     }
423     if (x->IsBigInt() && y->IsBigInt()) {
424         return BigInt::Equal(x.GetTaggedValue(), y.GetTaggedValue());
425     }
426     return false;
427 }
428 
StrictNumberCompare(double x,double y)429 inline ComparisonResult JSTaggedValue::StrictNumberCompare(double x, double y)
430 {
431     if (std::isnan(x) || std::isnan(y)) {
432         return ComparisonResult::UNDEFINED;
433     }
434     if (x < y) {
435         return ComparisonResult::LESS;
436     }
437     if (x > y) {
438         return ComparisonResult::GREAT;
439     }
440     return ComparisonResult::EQUAL;
441 }
442 
IsNumber()443 inline bool JSTaggedValue::IsNumber() const
444 {
445     return IsInt() || IsDouble();
446 }
447 
IsString()448 inline bool JSTaggedValue::IsString() const
449 {
450     return IsHeapObject() && GetTaggedObject()->GetClass()->IsString();
451 }
452 
IsBigInt()453 inline bool JSTaggedValue::IsBigInt() const
454 {
455     return IsHeapObject() && GetTaggedObject()->GetClass()->IsBigInt();
456 }
457 
IsStringOrSymbol()458 inline bool JSTaggedValue::IsStringOrSymbol() const
459 {
460     return IsHeapObject() && GetTaggedObject()->GetClass()->IsStringOrSymbol();
461 }
462 
IsTaggedArray()463 inline bool JSTaggedValue::IsTaggedArray() const
464 {
465     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTaggedArray();
466 }
467 
IsNativePointer()468 inline bool JSTaggedValue::IsNativePointer() const
469 {
470     return IsJSNativePointer();
471 }
472 
IsJSNativePointer()473 inline bool JSTaggedValue::IsJSNativePointer() const
474 {
475     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSNativePointer();
476 }
477 
IsSymbol()478 inline bool JSTaggedValue::IsSymbol() const
479 {
480     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSSymbol();
481 }
482 
IsJSProxy()483 inline bool JSTaggedValue::IsJSProxy() const
484 {
485     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSProxy();
486 }
487 
IsBoolean()488 inline bool JSTaggedValue::IsBoolean() const
489 {
490     return IsTrue() || IsFalse();
491 }
492 
IsJSObject()493 inline bool JSTaggedValue::IsJSObject() const
494 {
495     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSObject();
496 }
497 
IsECMAObject()498 inline bool JSTaggedValue::IsECMAObject() const
499 {
500     return IsHeapObject() && GetTaggedObject()->GetClass()->IsECMAObject();
501 }
502 
IsJSPromise()503 inline bool JSTaggedValue::IsJSPromise() const
504 {
505     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPromise();
506 }
507 
IsRecord()508 inline bool JSTaggedValue::IsRecord() const
509 {
510     return IsHeapObject() && GetTaggedObject()->GetClass()->IsRecord();
511 }
512 
IsPromiseReaction()513 inline bool JSTaggedValue::IsPromiseReaction() const
514 {
515     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseReaction();
516 }
517 
IsJSPromiseReactionFunction()518 inline bool JSTaggedValue::IsJSPromiseReactionFunction() const
519 {
520     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPromiseReactionFunction();
521 }
522 
IsProgram()523 inline bool JSTaggedValue::IsProgram() const
524 {
525     return IsHeapObject() && GetTaggedObject()->GetClass()->IsProgram();
526 }
527 
IsJSPromiseExecutorFunction()528 inline bool JSTaggedValue::IsJSPromiseExecutorFunction() const
529 {
530     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPromiseExecutorFunction();
531 }
532 
IsJSPromiseAllResolveElementFunction()533 inline bool JSTaggedValue::IsJSPromiseAllResolveElementFunction() const
534 {
535     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPromiseAllResolveElementFunction();
536 }
537 
IsCompletionRecord()538 inline bool JSTaggedValue::IsCompletionRecord() const
539 {
540     return IsHeapObject() && GetTaggedObject()->GetClass()->IsCompletionRecord();
541 }
542 
IsResolvingFunctionsRecord()543 inline bool JSTaggedValue::IsResolvingFunctionsRecord() const
544 {
545     return IsHeapObject() && GetTaggedObject()->GetClass()->IsResolvingFunctionsRecord();
546 }
547 
IsPromiseRecord()548 inline bool JSTaggedValue::IsPromiseRecord() const
549 {
550     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseRecord();
551 }
552 
IsJSLocale()553 inline bool JSTaggedValue::IsJSLocale() const
554 {
555     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSLocale();
556 }
557 
IsJSIntl()558 inline bool JSTaggedValue::IsJSIntl() const
559 {
560     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSIntl();
561 }
562 
IsJSDateTimeFormat()563 inline bool JSTaggedValue::IsJSDateTimeFormat() const
564 {
565     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSDateTimeFormat();
566 }
567 
IsJSRelativeTimeFormat()568 inline bool JSTaggedValue::IsJSRelativeTimeFormat() const
569 {
570     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSRelativeTimeFormat();
571 }
572 
IsJSNumberFormat()573 inline bool JSTaggedValue::IsJSNumberFormat() const
574 {
575     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSNumberFormat();
576 }
577 
IsJSCollator()578 inline bool JSTaggedValue::IsJSCollator() const
579 {
580     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSCollator();
581 }
582 
IsJSPluralRules()583 inline bool JSTaggedValue::IsJSPluralRules() const
584 {
585     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPluralRules();
586 }
587 
IsJSAPIArrayList()588 inline bool JSTaggedValue::IsJSAPIArrayList() const
589 {
590     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIArrayList();
591 }
592 
IsJSAPITreeMap()593 inline bool JSTaggedValue::IsJSAPITreeMap() const
594 {
595     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPITreeMap();
596 }
597 
IsJSAPITreeSet()598 inline bool JSTaggedValue::IsJSAPITreeSet() const
599 {
600     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPITreeSet();
601 }
602 
IsSpecialContainer()603 inline bool JSTaggedValue::IsSpecialContainer() const
604 {
605     return IsHeapObject() && GetTaggedObject()->GetClass()->IsSpecialContainer();
606 }
607 
IsPromiseIteratorRecord()608 inline bool JSTaggedValue::IsPromiseIteratorRecord() const
609 {
610     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseIteratorRecord();
611 }
612 
IsPromiseCapability()613 inline bool JSTaggedValue::IsPromiseCapability() const
614 {
615     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseCapability();
616 }
617 
IsJSError()618 inline bool JSTaggedValue::IsJSError() const
619 {
620     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSError();
621 }
622 
IsMicroJobQueue()623 inline bool JSTaggedValue::IsMicroJobQueue() const
624 {
625     return IsHeapObject() && GetTaggedObject()->GetClass()->IsMicroJobQueue();
626 }
627 
IsPendingJob()628 inline bool JSTaggedValue::IsPendingJob() const
629 {
630     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPendingJob();
631 }
632 
IsArguments()633 inline bool JSTaggedValue::IsArguments() const
634 {
635     return IsHeapObject() && GetTaggedObject()->GetClass()->IsArguments();
636 }
637 
IsDate()638 inline bool JSTaggedValue::IsDate() const
639 {
640     return IsHeapObject() && GetTaggedObject()->GetClass()->IsDate();
641 }
642 
IsArray(JSThread * thread)643 inline bool JSTaggedValue::IsArray(JSThread *thread) const
644 {
645     if (!IsHeapObject()) {
646         return false;
647     }
648     JSHClass *jsHclass = GetTaggedObject()->GetClass();
649     if (jsHclass->IsJSArray()) {
650         return true;
651     }
652 
653     if (jsHclass->IsJSProxy()) {
654         return JSProxy::Cast(GetTaggedObject())->IsArray(thread);
655     }
656     return false;
657 }
658 
IsJSArray()659 inline bool JSTaggedValue::IsJSArray() const
660 {
661     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSArray();
662 }
663 
IsStableJSArray(JSThread * thread)664 inline bool JSTaggedValue::IsStableJSArray(JSThread *thread) const
665 {
666     return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableJSArray() &&
667            !thread->IsStableArrayElementsGuardiansInvalid();
668 }
669 
IsStableJSArguments(JSThread * thread)670 inline bool JSTaggedValue::IsStableJSArguments(JSThread *thread) const
671 {
672     return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableJSArguments() &&
673            !thread->IsStableArrayElementsGuardiansInvalid();
674 }
675 
HasStableElements(JSThread * thread)676 inline bool JSTaggedValue::HasStableElements(JSThread *thread) const
677 {
678     return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableElements() &&
679            !thread->IsStableArrayElementsGuardiansInvalid();
680 }
681 
IsTypedArray()682 inline bool JSTaggedValue::IsTypedArray() const
683 {
684     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTypedArray();
685 }
686 
IsJSTypedArray()687 inline bool JSTaggedValue::IsJSTypedArray() const
688 {
689     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSTypedArray();
690 }
691 
IsJSInt8Array()692 inline bool JSTaggedValue::IsJSInt8Array() const
693 {
694     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSInt8Array();
695 }
696 
IsJSUint8Array()697 inline bool JSTaggedValue::IsJSUint8Array() const
698 {
699     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSUint8Array();
700 }
701 
IsJSUint8ClampedArray()702 inline bool JSTaggedValue::IsJSUint8ClampedArray() const
703 {
704     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSUint8ClampedArray();
705 }
706 
IsJSInt16Array()707 inline bool JSTaggedValue::IsJSInt16Array() const
708 {
709     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSInt16Array();
710 }
711 
IsJSUint16Array()712 inline bool JSTaggedValue::IsJSUint16Array() const
713 {
714     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSUint16Array();
715 }
716 
IsJSInt32Array()717 inline bool JSTaggedValue::IsJSInt32Array() const
718 {
719     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSInt32Array();
720 }
721 
IsJSUint32Array()722 inline bool JSTaggedValue::IsJSUint32Array() const
723 {
724     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSUint32Array();
725 }
726 
IsJSFloat32Array()727 inline bool JSTaggedValue::IsJSFloat32Array() const
728 {
729     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSFloat32Array();
730 }
731 
IsJSFloat64Array()732 inline bool JSTaggedValue::IsJSFloat64Array() const
733 {
734     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSFloat64Array();
735 }
736 
IsJSMap()737 inline bool JSTaggedValue::IsJSMap() const
738 {
739     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSMap();
740 }
741 
IsJSWeakMap()742 inline bool JSTaggedValue::IsJSWeakMap() const
743 {
744     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSWeakMap();
745 }
746 
IsJSWeakSet()747 inline bool JSTaggedValue::IsJSWeakSet() const
748 {
749     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSWeakSet();
750 }
751 
IsJSSet()752 inline bool JSTaggedValue::IsJSSet() const
753 {
754     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSSet();
755 }
756 
IsJSRegExp()757 inline bool JSTaggedValue::IsJSRegExp() const
758 {
759     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSRegExp();
760 }
761 
IsJSFunction()762 inline bool JSTaggedValue::IsJSFunction() const
763 {
764     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSFunction();
765 }
766 
IsJSFunctionBase()767 inline bool JSTaggedValue::IsJSFunctionBase() const
768 {
769     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSFunctionBase();
770 }
771 
IsBoundFunction()772 inline bool JSTaggedValue::IsBoundFunction() const
773 {
774     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJsBoundFunction();
775 }
776 
IsJSIntlBoundFunction()777 inline bool JSTaggedValue::IsJSIntlBoundFunction() const
778 {
779     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSIntlBoundFunction();
780 }
781 
IsProxyRevocFunction()782 inline bool JSTaggedValue::IsProxyRevocFunction() const
783 {
784     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSProxyRevocFunction();
785 }
786 
IsJSAsyncFunction()787 inline bool JSTaggedValue::IsJSAsyncFunction() const
788 {
789     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAsyncFunction();
790 }
791 
IsJSAsyncAwaitStatusFunction()792 inline bool JSTaggedValue::IsJSAsyncAwaitStatusFunction() const
793 {
794     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAsyncAwaitStatusFunction();
795 }
796 
IsJSPrimitiveRef()797 inline bool JSTaggedValue::IsJSPrimitiveRef() const
798 {
799     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJsPrimitiveRef();
800 }
801 
IsJSPrimitive()802 inline bool JSTaggedValue::IsJSPrimitive() const
803 {
804     return IsNumber() || IsStringOrSymbol() || IsBoolean();
805 }
806 
IsAccessorData()807 inline bool JSTaggedValue::IsAccessorData() const
808 {
809     return IsHeapObject() && GetTaggedObject()->GetClass()->IsAccessorData();
810 }
811 
IsInternalAccessor()812 inline bool JSTaggedValue::IsInternalAccessor() const
813 {
814     return IsHeapObject() && GetTaggedObject()->GetClass()->IsInternalAccessor();
815 }
816 
IsAccessor()817 inline bool JSTaggedValue::IsAccessor() const
818 {
819     if (IsHeapObject()) {
820         auto *jshcalss = GetTaggedObject()->GetClass();
821         return jshcalss->IsAccessorData() || jshcalss->IsInternalAccessor();
822     }
823 
824     return false;
825 }
826 
IsPrototypeHandler()827 inline bool JSTaggedValue::IsPrototypeHandler() const
828 {
829     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPrototypeHandler();
830 }
831 
IsTransitionHandler()832 inline bool JSTaggedValue::IsTransitionHandler() const
833 {
834     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTransitionHandler();
835 }
836 
IsPropertyBox()837 inline bool JSTaggedValue::IsPropertyBox() const
838 {
839     return IsHeapObject() && GetTaggedObject()->GetClass()->IsPropertyBox();
840 }
841 
IsProtoChangeDetails()842 inline bool JSTaggedValue::IsProtoChangeDetails() const
843 {
844     return IsHeapObject() && GetTaggedObject()->GetClass()->IsProtoChangeDetails();
845 }
IsProtoChangeMarker()846 inline bool JSTaggedValue::IsProtoChangeMarker() const
847 {
848     return IsHeapObject() && GetTaggedObject()->GetClass()->IsProtoChangeMarker();
849 }
850 
IsJSGlobalEnv()851 inline bool JSTaggedValue::IsJSGlobalEnv() const
852 {
853     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJsGlobalEnv();
854 }
855 
IsForinIterator()856 inline bool JSTaggedValue::IsForinIterator() const
857 {
858     return IsHeapObject() && GetTaggedObject()->GetClass()->IsForinIterator();
859 }
860 
IsJSSetIterator()861 inline bool JSTaggedValue::IsJSSetIterator() const
862 {
863     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSSetIterator();
864 }
865 
IsJSMapIterator()866 inline bool JSTaggedValue::IsJSMapIterator() const
867 {
868     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSMapIterator();
869 }
870 
IsJSAPITreeMapIterator()871 inline bool JSTaggedValue::IsJSAPITreeMapIterator() const
872 {
873     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPITreeMapIterator();
874 }
875 
IsJSAPITreeSetIterator()876 inline bool JSTaggedValue::IsJSAPITreeSetIterator() const
877 {
878     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPITreeSetIterator();
879 }
880 
IsJSArrayIterator()881 inline bool JSTaggedValue::IsJSArrayIterator() const
882 {
883     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSArrayIterator();
884 }
885 
IsJSAPIArrayListIterator()886 inline bool JSTaggedValue::IsJSAPIArrayListIterator() const
887 {
888     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIArrayListIterator();
889 }
890 
IsIterator()891 inline bool JSTaggedValue::IsIterator() const
892 {
893     return IsHeapObject() && GetTaggedObject()->GetClass()->IsIterator();
894 }
895 
IsGeneratorFunction()896 inline bool JSTaggedValue::IsGeneratorFunction() const
897 {
898     return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorFunction();
899 }
900 
IsGeneratorObject()901 inline bool JSTaggedValue::IsGeneratorObject() const
902 {
903     return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorObject();
904 }
905 
IsGeneratorContext()906 inline bool JSTaggedValue::IsGeneratorContext() const
907 {
908     return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorContext();
909 }
910 
IsAsyncFuncObject()911 inline bool JSTaggedValue::IsAsyncFuncObject() const
912 {
913     return IsHeapObject() && GetTaggedObject()->GetClass()->IsAsyncFuncObject();
914 }
915 
IsDynClass()916 inline bool JSTaggedValue::IsDynClass() const
917 {
918     return IsJSHClass();
919 }
920 
IsJSHClass()921 inline bool JSTaggedValue::IsJSHClass() const
922 {
923     return IsHeapObject() && GetTaggedObject()->GetClass()->IsHClass();
924 }
925 
IsStringIterator()926 inline bool JSTaggedValue::IsStringIterator() const
927 {
928     return IsHeapObject() && GetTaggedObject()->GetClass()->IsStringIterator();
929 }
930 
IsArrayBuffer()931 inline bool JSTaggedValue::IsArrayBuffer() const
932 {
933     return IsHeapObject() && GetTaggedObject()->GetClass()->IsArrayBuffer();
934 }
935 
IsDataView()936 inline bool JSTaggedValue::IsDataView() const
937 {
938     return IsHeapObject() && GetTaggedObject()->GetClass()->IsDataView();
939 }
940 
IsTemplateMap()941 inline bool JSTaggedValue::IsTemplateMap() const
942 {
943     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTemplateMap();
944 }
945 
IsJSGlobalObject()946 inline bool JSTaggedValue::IsJSGlobalObject() const
947 {
948     return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSGlobalObject();
949 }
950 
IsMachineCodeObject()951 inline bool JSTaggedValue::IsMachineCodeObject() const
952 {
953     return IsHeapObject() && GetTaggedObject()->GetClass()->IsMachineCodeObject();
954 }
955 
IsClassInfoExtractor()956 inline bool JSTaggedValue::IsClassInfoExtractor() const
957 {
958     return IsHeapObject() && GetTaggedObject()->GetClass()->IsClassInfoExtractor();
959 }
960 
IsTSObjectType()961 inline bool JSTaggedValue::IsTSObjectType() const
962 {
963     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSObjectType();
964 }
965 
IsTSClassType()966 inline bool JSTaggedValue::IsTSClassType() const
967 {
968     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSClassType();
969 }
970 
IsTSInterfaceType()971 inline bool JSTaggedValue::IsTSInterfaceType() const
972 {
973     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSInterfaceType();
974 }
975 
IsTSUnionType()976 inline bool JSTaggedValue::IsTSUnionType() const
977 {
978     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSUnionType();
979 }
980 
IsTSImportType()981 inline bool JSTaggedValue::IsTSImportType() const
982 {
983     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSImportType();
984 }
985 
IsTSClassInstanceType()986 inline bool JSTaggedValue::IsTSClassInstanceType() const
987 {
988     return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSClassInstanceType();
989 }
990 
ExtractNumber()991 inline double JSTaggedValue::ExtractNumber() const
992 {
993     ASSERT(IsNumber());
994     return GetNumber();
995 }
996 
997 // 9.4.2.4 ArraySetLength 3 to 7
ToArrayLength(JSThread * thread,const JSHandle<JSTaggedValue> & tagged,uint32_t * output)998 inline bool JSTaggedValue::ToArrayLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged, uint32_t *output)
999 {
1000     // 3. Let newLen be ToUint32(Desc.[[Value]]).
1001     uint32_t newLen = ToUint32(thread, tagged);
1002     // 4. ReturnIfAbrupt(newLen).
1003     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1004 
1005     // 5. Let numberLen be ToNumber(Desc.[[Value]]).
1006     JSTaggedNumber numberLen = ToNumber(thread, tagged);
1007     // 6. ReturnIfAbrupt(newLen).
1008     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1009 
1010     // 7. If newLen != numberLen, throw a RangeError exception.
1011     if (JSTaggedNumber(newLen) != numberLen) {
1012         THROW_RANGE_ERROR_AND_RETURN(thread, "Not a valid array length", false);
1013     }
1014 
1015     *output = newLen;
1016     return true;
1017 }
1018 
GetArrayLength()1019 inline uint32_t JSTaggedValue::GetArrayLength() const
1020 {
1021     ASSERT(IsNumber());
1022     if (IsInt()) {
1023         return static_cast<uint32_t>(GetInt());
1024     }
1025     if (IsDouble()) {
1026         ASSERT(GetDouble() <= TaggedArray::MAX_ARRAY_INDEX);
1027         return static_cast<uint32_t>(GetDouble());
1028     }
1029     UNREACHABLE();
1030 }
1031 
ToElementIndex(JSTaggedValue key,uint32_t * output)1032 inline bool JSTaggedValue::ToElementIndex(JSTaggedValue key, uint32_t *output)
1033 {
1034     if (key.IsInt()) {
1035         int index = key.GetInt();
1036         if (index >= 0) {
1037             *output = index;
1038             return true;
1039         }
1040     } else if (key.IsDouble()) {
1041         double d = key.GetDouble();
1042         uint32_t index = base::NumberHelper::DoubleToInt(d, base::INT32_BITS);
1043         if (d - static_cast<double>(index) == 0.0) {
1044             *output = index;
1045             return true;
1046         }
1047     } else if (key.IsString()) {
1048         return StringToElementIndex(key, output);
1049     }
1050     return false;
1051 }
1052 
StringToElementIndex(JSTaggedValue key,uint32_t * output)1053 inline bool JSTaggedValue::StringToElementIndex(JSTaggedValue key, uint32_t *output)
1054 {
1055     ASSERT(key.IsString());
1056 
1057     auto strObj = static_cast<EcmaString *>(key.GetTaggedObject());
1058     uint32_t len = strObj->GetLength();
1059     if (len == 0 || len > MAX_INDEX_LEN) {  // NOLINTNEXTLINEreadability-magic-numbers)
1060         return false;
1061     }
1062     uint32_t c;
1063     if (strObj->IsUtf16()) {
1064         c = strObj->GetDataUtf16()[0];  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1065     } else {
1066         c = strObj->GetDataUtf8()[0];  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1067     }
1068     uint64_t n = 0;
1069     if (c >= '0' && c <= '9') {
1070         if (c == '0') {
1071             if (len != 1) {
1072                 return false;
1073             }
1074             *output = 0;
1075             return true;
1076         }
1077 
1078         n = c - '0';
1079         for (uint32_t i = 1; i < len; i++) {
1080             if (strObj->IsUtf16()) {
1081                 c = strObj->GetDataUtf16()[i];  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1082             } else {
1083                 c = strObj->GetDataUtf8()[i];  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1084             }
1085             if (c < '0' || c > '9') {
1086                 return false;
1087             }
1088             // NOLINTNEXTLINE(readability-magic-numbers)
1089             n = n * 10 + (c - '0');  // 10: decimal factor
1090         }
1091         if (n < JSObject::MAX_ELEMENT_INDEX) {
1092             *output = n;
1093             return true;
1094         }
1095     }
1096     return false;
1097 }
1098 
GetKeyHashCode()1099 inline uint32_t JSTaggedValue::GetKeyHashCode() const
1100 {
1101     ASSERT(IsStringOrSymbol());
1102     if (IsString()) {
1103         return EcmaString::Cast(GetTaggedObject())->GetHashcode();
1104     }
1105 
1106     return JSSymbol::Cast(GetTaggedObject())->GetHashField();
1107 }
1108 }  // namespace panda::ecmascript
1109 #endif  // ECMASCRIPT_TAGGED_VALUE__INL_H
1110