• 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_SERIALIZER_H
17 #define ECMASCRIPT_JS_SERIALIZER_H
18 
19 #include <map>
20 
21 #include "ecmascript/ecma_vm.h"
22 #include "ecmascript/js_date.h"
23 #include "ecmascript/js_map.h"
24 #include "ecmascript/js_native_pointer.h"
25 #include "ecmascript/js_object.h"
26 #include "ecmascript/js_thread.h"
27 #include "ecmascript/js_typed_array.h"
28 #include "ecmascript/regexp/dyn_chunk.h"
29 
30 namespace panda::ecmascript {
31 enum class SerializationUID : uint8_t {
32     // JS special values
33     JS_NULL = 0x01,
34     JS_UNDEFINED,
35     JS_TRUE,
36     JS_FALSE,
37     HOLE,
38     // Number types
39     INT32,
40     DOUBLE,
41     // Not support yet, BigInt type has not been implemented in ark engine
42     BIGINT,
43     ECMASTRING,
44     // Boolean types
45     C_TRUE,
46     C_FALSE,
47     // Tagged object reference mark
48     TAGGED_OBJECT_REFERNCE,
49     // Support tagged objct id reference begin
50     JS_DATE,
51     JS_REG_EXP,
52     JS_PLAIN_OBJECT,
53     JS_SET,
54     JS_MAP,
55     JS_ARRAY,
56     JS_ARRAY_BUFFER,
57     // TypedArray begin
58     JS_UINT8_ARRAY,
59     JS_UINT8_CLAMPED_ARRAY,
60     JS_UINT16_ARRAY,
61     JS_UINT32_ARRAY,
62     JS_INT8_ARRAY,
63     JS_INT16_ARRAY,
64     JS_INT32_ARRAY,
65     JS_FLOAT32_ARRAY,
66     JS_FLOAT64_ARRAY,
67     // TypedArray end
68     // Support tagged objct id reference end
69     // Error UIDs
70     JS_ERROR,
71     EVAL_ERROR,
72     RANGE_ERROR,
73     REFERENCE_ERROR,
74     TYPE_ERROR,
75     URI_ERROR,
76     SYNTAX_ERROR,
77     ERROR_MESSAGE_BEGIN,
78     ERROR_MESSAGE_END,
79     // NativeFunctionPointer
80     NATIVE_FUNCTION_POINTER,
81     UNKNOWN
82 };
83 
84 class JSSerializer {
85 public:
JSSerializer(JSThread * thread)86     explicit JSSerializer(JSThread *thread) : thread_(thread) {}
87     ~JSSerializer() = default;
88     bool SerializeJSTaggedValue(const JSHandle<JSTaggedValue> &value);
89 
90     // Return pointer to the buffer and its length, should not use this Serializer anymore after Release
91     std::pair<uint8_t *, size_t> ReleaseBuffer();
92 
93 private:
94     bool WriteTaggedObject(const JSHandle<JSTaggedValue> &value);
95     bool WritePrimitiveValue(const JSHandle<JSTaggedValue> &value);
96     bool WriteInt(int32_t value);
97     bool WriteDouble(double value);
98     bool WriteRawData(const void *data, size_t length);
99     bool WriteType(SerializationUID uId);
100     bool AllocateBuffer(size_t bytes);
101     bool ExpandBuffer(size_t requestedSize);
102     bool WriteBoolean(bool value);
103     bool WriteJSError(const JSHandle<JSTaggedValue> &value);
104     bool WriteJSErrorHeader(JSType type);
105     bool WriteJSDate(const JSHandle<JSTaggedValue> &value);
106     bool WriteJSArray(const JSHandle<JSTaggedValue> &value);
107     bool WriteJSMap(const JSHandle<JSTaggedValue> &value);
108     bool WriteJSSet(const JSHandle<JSTaggedValue> &value);
109     bool WriteJSRegExp(const JSHandle<JSTaggedValue> &value);
110     bool WriteEcmaString(const JSHandle<JSTaggedValue> &value);
111     bool WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId);
112     bool WritePlainObject(const JSHandle<JSTaggedValue> &value);
113     bool WriteNativeFunctionPointer(const JSHandle<JSTaggedValue> &value);
114     bool WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value);
115     bool WriteDesc(const PropertyDescriptor &desc);
116     bool IsSerialized(uintptr_t addr) const;
117     bool WriteIfSerialized(uintptr_t addr);
118 
119     NO_MOVE_SEMANTIC(JSSerializer);
120     NO_COPY_SEMANTIC(JSSerializer);
121 
122     JSThread *thread_;
123     uint8_t *buffer_ = nullptr;
124     uint64_t sizeLimit_ = 0;
125     size_t bufferSize_ = 0;
126     size_t bufferCapacity_ = 0;
127     // The Reference map is used for check whether a tagged object has been serialized
128     // Reference map works only if no gc happens during serialization
129     std::map<uintptr_t, uint64_t> referenceMap_;
130     uint64_t objectId_ = 0;
131 };
132 
133 class JSDeserializer {
134 public:
135     // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
JSDeserializer(JSThread * thread,uint8_t * data,size_t size)136     JSDeserializer(JSThread *thread, uint8_t *data, size_t size)
137         : thread_(thread), begin_(data), position_(data), end_(data + size)
138     {
139     }
140     ~JSDeserializer();
141     JSHandle<JSTaggedValue> DeserializeJSTaggedValue();
142 
143 private:
144     bool ReadInt(int32_t *value);
145     bool ReadObjectId(uint64_t *objectId);
146     bool ReadDouble(double *value);
147     SerializationUID ReadType();
148     JSHandle<JSTaggedValue> ReadJSError(SerializationUID uid);
149     JSHandle<JSTaggedValue> ReadJSDate();
150     JSHandle<JSTaggedValue> ReadJSArray();
151     JSHandle<JSTaggedValue> ReadPlainObject();
152     JSHandle<JSTaggedValue> ReadEcmaString();
153     JSHandle<JSTaggedValue> ReadJSMap();
154     JSHandle<JSTaggedValue> ReadJSSet();
155     JSHandle<JSTaggedValue> ReadJSRegExp();
156     JSHandle<JSTaggedValue> ReadJSTypedArray(SerializationUID uid);
157     JSHandle<JSTaggedValue> ReadNativeFunctionPointer();
158     JSHandle<JSTaggedValue> ReadJSArrayBuffer();
159     JSHandle<JSTaggedValue> ReadReference();
160     bool JudgeType(SerializationUID targetUid);
161     void *GetBuffer(uint32_t bufferSize);
162     bool ReadJSTaggedValue(JSTaggedValue *originalFlags);
163     bool DefinePropertiesAndElements(const JSHandle<JSTaggedValue> &obj);
164     bool ReadDesc(PropertyDescriptor *desc);
165     bool ReadBoolean(bool *value);
166 
167     NO_MOVE_SEMANTIC(JSDeserializer);
168     NO_COPY_SEMANTIC(JSDeserializer);
169 
170     JSThread *thread_ = nullptr;
171     uint8_t *begin_ = nullptr;
172     const uint8_t *position_ = nullptr;
173     const uint8_t * const end_ = nullptr;
174     uint64_t objectId_ = 0;
175     std::map<uint64_t, JSHandle<JSTaggedValue>> referenceMap_;
176 };
177 
178 class SerializationData {
179 public:
SerializationData()180     SerializationData() : dataSize_(0), value_(nullptr) {}
181     ~SerializationData() = default;
182 
GetData()183     uint8_t* GetData() const
184     {
185         return value_.get();
186     }
GetSize()187     size_t GetSize() const
188     {
189         return dataSize_;
190     }
191 
192 private:
193     struct Deleter {
operatorDeleter194         void operator()(uint8_t* ptr) const
195         {
196             free(ptr);
197         }
198     };
199 
200     size_t dataSize_;
201     std::unique_ptr<uint8_t, Deleter> value_;
202 
203 private:
204     friend class Serializer;
205 
206     NO_COPY_SEMANTIC(SerializationData);
207 };
208 
209 class Serializer {
210 public:
Serializer(JSThread * thread)211     explicit Serializer(JSThread *thread) : valueSerializer_(thread) {}
212     ~Serializer() = default;
213 
214     bool WriteValue(JSThread *thread, const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &transfer);
215     std::unique_ptr<SerializationData> Release();
216 
217 private:
218     bool PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer);
219     bool FinalizeTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer);
220 
221 private:
222     ecmascript::JSSerializer valueSerializer_;
223     std::unique_ptr<SerializationData> data_;
224     CVector<int> arrayBufferIdxs_;
225 
226     NO_COPY_SEMANTIC(Serializer);
227 };
228 
229 class Deserializer {
230 public:
Deserializer(JSThread * thread,SerializationData * data)231     explicit Deserializer(JSThread *thread, SerializationData* data)
232         : valueDeserializer_(thread, data->GetData(), data->GetSize()) {}
233     ~Deserializer() = default;
234 
235     JSHandle<JSTaggedValue> ReadValue();
236 
237 private:
238     ecmascript::JSDeserializer valueDeserializer_;
239 
240     NO_COPY_SEMANTIC(Deserializer);
241 };
242 }  // namespace panda::ecmascript
243 
244 #endif // ECMASCRIPT_JS_SERIALIZER_H
245