• 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_JS_TAGGED_VALUE_H
17 #define ECMASCRIPT_JS_TAGGED_VALUE_H
18 
19 #include "ecmascript/mem/c_string.h"
20 #include "include/coretypes/tagged_value.h"
21 
22 namespace panda::ecmascript {
23 class JSObject;
24 class JSTaggedNumber;
25 template<typename T>
26 class JSHandle;
27 class TaggedArray;
28 class LinkedHashMap;
29 class LinkedHashSet;
30 class PropertyDescriptor;
31 class OperationResult;
32 class EcmaString;
33 class JSThread;
34 
35 // Don't switch the order!
36 enum PreferredPrimitiveType : uint8_t { PREFER_NUMBER = 0, PREFER_STRING, NO_PREFERENCE };
37 
38 // Result of an abstract relational comparison of x and y, implemented according
39 // to ES6 section 7.2.11 Abstract Relational Comparison.
40 enum class ComparisonResult {
41     LESS,      // x < y
42     EQUAL,     // x = y
43     GREAT,     // x > y
44     UNDEFINED  // at least one of x or y was undefined or NaN
45 };
46 
47 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
48 #define RETURN_TAGGED_VALUE_IF_ABRUPT(thread) RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Undefined());
49 
50 using JSTaggedType = coretypes::TaggedType;
51 
ReinterpretDoubleToTaggedType(double value)52 static inline JSTaggedType ReinterpretDoubleToTaggedType(double value)
53 {
54     return bit_cast<JSTaggedType>(value);
55 }
ReinterpretTaggedTypeToDouble(JSTaggedType value)56 static inline double ReinterpretTaggedTypeToDouble(JSTaggedType value)
57 {
58     return bit_cast<double>(value);
59 }
60 
61 class JSTaggedValue : public coretypes::TaggedValue {
62 public:
Cast(ObjectHeader * object)63     static JSTaggedValue Cast(ObjectHeader *object)
64     {
65         return JSTaggedValue(object);
66     }
67 
68     JSTaggedValue(void *) = delete;
69 
70     constexpr JSTaggedValue() = default;
JSTaggedValue(coretypes::TaggedType v)71     constexpr explicit JSTaggedValue(coretypes::TaggedType v) : coretypes::TaggedValue(v) {}
JSTaggedValue(int v)72     constexpr explicit JSTaggedValue(int v) : coretypes::TaggedValue(v) {}
JSTaggedValue(unsigned int v)73     explicit JSTaggedValue(unsigned int v) : coretypes::TaggedValue(v) {}
JSTaggedValue(bool v)74     constexpr explicit JSTaggedValue(bool v) : coretypes::TaggedValue(v) {}
JSTaggedValue(double v)75     explicit JSTaggedValue(double v) : coretypes::TaggedValue(v) {}
JSTaggedValue(const ObjectHeader * v)76     explicit JSTaggedValue(const ObjectHeader *v) : coretypes::TaggedValue(v) {}
JSTaggedValue(const TaggedObject * v)77     explicit JSTaggedValue(const TaggedObject *v) : coretypes::TaggedValue(v) {}
JSTaggedValue(const coretypes::TaggedValue & other)78     explicit JSTaggedValue(const coretypes::TaggedValue &other) : coretypes::TaggedValue(other.GetRawData()) {}
JSTaggedValue(int64_t v)79     explicit JSTaggedValue(int64_t v) : coretypes::TaggedValue(v){};
80 
81     ~JSTaggedValue() = default;
82     DEFAULT_COPY_SEMANTIC(JSTaggedValue);
83     DEFAULT_MOVE_SEMANTIC(JSTaggedValue);
84 
GetWeakReferentUnChecked()85     inline TaggedObject *GetWeakReferentUnChecked() const
86     {
87         return reinterpret_cast<TaggedObject *>(GetRawData() & (~TAG_WEAK_MASK));
88     }
89 
IsWeakForHeapObject()90     inline bool IsWeakForHeapObject() const
91     {
92         return (GetRawData() & TAG_WEAK_MASK) == 1U;
93     }
94 
False()95     static inline constexpr JSTaggedValue False()
96     {
97         return JSTaggedValue(VALUE_FALSE);
98     }
99 
True()100     static inline constexpr JSTaggedValue True()
101     {
102         return JSTaggedValue(VALUE_TRUE);
103     }
104 
Undefined()105     static inline constexpr JSTaggedValue Undefined()
106     {
107         return JSTaggedValue(VALUE_UNDEFINED);
108     }
109 
Null()110     static inline constexpr JSTaggedValue Null()
111     {
112         return JSTaggedValue(VALUE_NULL);
113     }
114 
Hole()115     static inline constexpr JSTaggedValue Hole()
116     {
117         return JSTaggedValue(VALUE_HOLE);
118     }
119 
Exception()120     static inline constexpr JSTaggedValue Exception()
121     {
122         return JSTaggedValue(VALUE_EXCEPTION);
123     }
124 
GetNumber()125     inline double GetNumber() const
126     {
127         return IsInt() ? GetInt() : GetDouble();
128     }
129 
GetTaggedObject()130     inline TaggedObject *GetTaggedObject() const
131     {
132         return reinterpret_cast<TaggedObject *>(GetHeapObject());
133     }
134 
GetRawTaggedObject()135     inline TaggedObject *GetRawTaggedObject() const
136     {
137         return reinterpret_cast<TaggedObject *>(GetRawHeapObject());
138     }
139 
GetTaggedWeakRef()140     inline TaggedObject *GetTaggedWeakRef() const
141     {
142         return reinterpret_cast<TaggedObject *>(GetWeakReferent());
143     }
144 
145     static JSTaggedValue OrdinaryToPrimitive(JSThread *thread, const JSHandle<JSTaggedValue> &tagged,
146                                              PreferredPrimitiveType type = PREFER_NUMBER);
147 
148     // ecma6 7.1 Type Conversion
149     static JSTaggedValue ToPrimitive(JSThread *thread, const JSHandle<JSTaggedValue> &tagged,
150                                      PreferredPrimitiveType type = NO_PREFERENCE);
151     bool ToBoolean() const;
152     static JSTaggedNumber ToNumber(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
153     static JSTaggedValue ToBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
154     static JSTaggedValue ToBigInt64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
155     static JSTaggedValue ToBigUint64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
156     static JSTaggedNumber ToInteger(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
157     static JSTaggedValue ToNumeric(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
158     static int32_t ToInt32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
159     static uint32_t ToUint32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
160     static int16_t ToInt16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
161     static uint16_t ToUint16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
162     static int8_t ToInt8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
163     static uint8_t ToUint8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
164     static uint8_t ToUint8Clamp(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
165     static JSHandle<EcmaString> ToString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
166     static JSHandle<JSObject> ToObject(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
167     static JSHandle<JSTaggedValue> ToPropertyKey(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
168     static JSTaggedNumber ToLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
169     static JSTaggedValue CanonicalNumericIndexString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
170     static JSTaggedNumber ToIndex(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
171 
172     static bool ToArrayLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged, uint32_t *output);
173     static bool ToElementIndex(JSTaggedValue key, uint32_t *output);
174     static bool StringToElementIndex(JSTaggedValue key, uint32_t *output);
175     uint32_t GetArrayLength() const;
176 
177     // ecma6 7.2 Testing and Comparison Operations
178     bool IsCallable() const;
179     bool IsConstructor() const;
180     bool IsExtensible(JSThread *thread) const;
181     bool IsInteger() const;
182     bool WithinInt32() const;
183     bool IsZero() const;
184     static bool IsPropertyKey(const JSHandle<JSTaggedValue> &key);
185     static JSHandle<JSTaggedValue> RequireObjectCoercible(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
186     static bool SameValue(const JSTaggedValue &x, const JSTaggedValue &y);
187     static bool SameValue(const JSHandle<JSTaggedValue> &xHandle, const JSHandle<JSTaggedValue> &yHandle);
188     static bool SameValueZero(const JSTaggedValue &x, const JSTaggedValue &y);
189     static bool Less(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
190     static bool Equal(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
191     static bool StrictEqual(const JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
192     static bool SameValueNumberic(const JSTaggedValue &x, const JSTaggedValue &y);
193 
194     // ES6 7.4 Operations on Iterator Objects
195     static JSObject *CreateIterResultObject(JSThread *thread, const JSHandle<JSTaggedValue> &value, bool done);
196 
197     // ecma6 7.3
198     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
199                                        const JSHandle<JSTaggedValue> &key);
200 
201     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key);
202     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
203                                        const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver);
204     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key,
205                             const JSHandle<JSTaggedValue> &value, bool mayThrow = false);
206 
207     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
208                             const JSHandle<JSTaggedValue> &value, bool mayThrow = false);
209 
210     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
211                             const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver,
212                             bool mayThrow = false);
213     static bool DeleteProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
214                                const JSHandle<JSTaggedValue> &key);
215     static bool DeletePropertyOrThrow(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
216                                       const JSHandle<JSTaggedValue> &key);
217     static bool DefinePropertyOrThrow(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
218                                       const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc);
219     static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
220                                   const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc);
221     static bool GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
222                                PropertyDescriptor &desc);
223     static bool SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
224                              const JSHandle<JSTaggedValue> &proto);
225     static bool PreventExtensions(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
226     static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
227     static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key);
228     static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key);
229     static bool HasOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
230                                const JSHandle<JSTaggedValue> &key);
231     static bool GlobalHasOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key);
232 
233     // Type
234     bool IsJSMap() const;
235     bool IsJSSet() const;
236     bool IsJSWeakMap() const;
237     bool IsJSWeakSet() const;
238     bool IsJSRegExp() const;
239     bool IsNumber() const;
240     bool IsBigInt() const;
241     bool IsString() const;
242     bool IsStringOrSymbol() const;
243     bool IsTaggedArray() const;
244     bool IsNativePointer() const;
245     bool IsJSNativePointer() const;
246     bool IsBoolean() const;
247     bool IsSymbol() const;
248     bool IsJSObject() const;
249     bool IsJSGlobalObject() const;
250     bool IsJSError() const;
251     bool IsArray(JSThread *thread) const;
252     bool IsJSArray() const;
253     bool IsStableJSArray(JSThread *thread) const;
254     bool IsStableJSArguments(JSThread *thread) const;
255     bool HasStableElements(JSThread *thread) const;
256     bool IsTypedArray() const;
257     bool IsJSTypedArray() const;
258     bool IsJSInt8Array() const;
259     bool IsJSUint8Array() const;
260     bool IsJSUint8ClampedArray() const;
261     bool IsJSInt16Array() const;
262     bool IsJSUint16Array() const;
263     bool IsJSInt32Array() const;
264     bool IsJSUint32Array() const;
265     bool IsJSFloat32Array() const;
266     bool IsJSFloat64Array() const;
267     bool IsArguments() const;
268     bool IsDate() const;
269     bool IsBoundFunction() const;
270     bool IsJSIntlBoundFunction() const;
271     bool IsProxyRevocFunction() const;
272     bool IsJSAsyncFunction() const;
273     bool IsJSAsyncAwaitStatusFunction() const;
274     bool IsClassConstructor() const;
275     bool IsClassPrototype() const;
276     bool IsJSFunction() const;
277     bool IsJSFunctionBase() const;
278     bool IsECMAObject() const;
279     bool IsJSPrimitiveRef() const;
280     bool IsJSPrimitive() const;
281     bool IsAccessorData() const;
282     bool IsInternalAccessor() const;
283     bool IsAccessor() const;
284     bool IsJSGlobalEnv() const;
285     bool IsJSProxy() const;
286     bool IsDynClass() const;
287     bool IsJSHClass() const;
288     bool IsForinIterator() const;
289     bool IsStringIterator() const;
290     bool IsArrayBuffer() const;
291 
292     bool IsJSSetIterator() const;
293     bool IsJSMapIterator() const;
294     bool IsJSArrayIterator() const;
295     bool IsIterator() const;
296     bool IsGeneratorFunction() const;
297     bool IsGeneratorObject() const;
298     bool IsGeneratorContext() const;
299     bool IsAsyncFuncObject() const;
300     bool IsJSPromise() const;
301     bool IsRecord() const;
302     bool IsPromiseReaction() const;
303     bool IsProgram() const;
304     bool IsJSPromiseReactionFunction() const;
305     bool IsJSPromiseExecutorFunction() const;
306     bool IsJSPromiseAllResolveElementFunction() const;
307     bool IsPromiseCapability() const;
308     bool IsPromiseIteratorRecord() const;
309     bool IsPromiseRecord() const;
310     bool IsResolvingFunctionsRecord() const;
311     bool IsCompletionRecord() const;
312     bool IsDataView() const;
313     bool IsTemplateMap() const;
314     bool IsMicroJobQueue() const;
315     bool IsPendingJob() const;
316     bool IsJSLocale() const;
317     bool IsJSDateTimeFormat() const;
318     bool IsJSRelativeTimeFormat() const;
319     bool IsJSIntl() const;
320     bool IsJSNumberFormat() const;
321     bool IsJSCollator() const;
322     bool IsJSPluralRules() const;
323 
324     // non ECMA standard jsapis
325     bool IsJSAPIArrayList() const;
326     bool IsJSAPIArrayListIterator() const;
327     bool IsJSAPITreeMap() const;
328     bool IsJSAPITreeSet() const;
329     bool IsJSAPITreeMapIterator() const;
330     bool IsJSAPITreeSetIterator() const;
331     bool IsSpecialContainer() const;
332 
333     bool IsPrototypeHandler() const;
334     bool IsTransitionHandler() const;
335     bool IsPropertyBox() const;
336     bool IsProtoChangeMarker() const;
337     bool IsProtoChangeDetails() const;
338     bool IsMachineCodeObject() const;
339     bool IsClassInfoExtractor() const;
340     bool IsTSObjectType() const;
341     bool IsTSClassType() const;
342     bool IsTSUnionType() const;
343     bool IsTSInterfaceType() const;
344     bool IsTSClassInstanceType() const;
345     bool IsTSImportType() const;
346     static bool IsSameTypeOrHClass(JSTaggedValue x, JSTaggedValue y);
347 
348     static ComparisonResult Compare(JSThread *thread, const JSHandle<JSTaggedValue> &x,
349                                     const JSHandle<JSTaggedValue> &y);
350     static ComparisonResult StrictNumberCompare(double x, double y);
351     static bool StrictNumberEquals(double x, double y);
352 
353     static JSHandle<JSTaggedValue> ToPrototypeOrObj(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
354     inline uint32_t GetKeyHashCode() const;
355     static JSTaggedValue GetSuperBase(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
356 
357     void DumpTaggedValue(JSThread *thread, std::ostream &os) const DUMP_API_ATTR;
358     void Dump(JSThread *thread, std::ostream &os) const DUMP_API_ATTR;
359     void D() const DUMP_API_ATTR;
360     void DumpForSnapshot(JSThread *thread, std::vector<std::pair<CString, JSTaggedValue>> &vec,
361                          bool isVmMode = true) const;
362     static void DV(JSTaggedType val) DUMP_API_ATTR;
363 
364 private:
365     inline double ExtractNumber() const;
366 
367     void DumpSpecialValue([[maybe_unused]] JSThread *thread, std::ostream &os) const;
368     void DumpHeapObjectType([[maybe_unused]] JSThread *thread, std::ostream &os) const;
369 
370     // non ECMA standard jsapis
371     static bool HasContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
372                                      const JSHandle<JSTaggedValue> &key);
373     static JSHandle<TaggedArray> GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
374     static bool GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
375                                      const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
376 };
377 }  // namespace panda::ecmascript
378 #endif  // ECMASCRIPT_JS_TAGGED_VALUE_H
379