• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "ecmascript/ecma_vm.h"
20 #include "ecmascript/js_date.h"
21 #include "ecmascript/js_map.h"
22 #include "ecmascript/js_native_pointer.h"
23 #include "ecmascript/js_object.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/js_typed_array.h"
26 #include "ecmascript/jspandafile/js_pandafile.h"
27 #include "ecmascript/jspandafile/program_object.h"
28 #include "ecmascript/mem/dyn_chunk.h"
29 #include "ecmascript/napi/jsnapi_helper.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 
32 using panda::JSValueRef;
33 namespace panda::ecmascript {
34 class JSPandaFile;
35 class ConstantPool;
36 
37 typedef void* (*DetachFunc)(void *enginePointer, void *objPointer, void *hint, void *detachData);
38 typedef Local<JSValueRef> (*AttachFunc)(void *enginePointer, void *buffer, void *hint, void *attachData);
39 
40 enum class SerializationUID : uint8_t {
41     UID_BEGIN = 0x01,
42     // JS special values
43     JS_NULL,
44     JS_UNDEFINED,
45     JS_TRUE,
46     JS_FALSE,
47     HOLE,
48     // Number types
49     INT32,
50     DOUBLE,
51     BIGINT,
52     ECMASTRING,
53     C_STRING,
54     // Boolean types
55     C_TRUE,
56     C_FALSE,
57     // Tagged object reference mark
58     TAGGED_OBJECT_REFERNCE,
59     // Support tagged object id reference begin
60     JS_DATE,
61     JS_REG_EXP,
62     JS_PLAIN_OBJECT,
63     NATIVE_BINDING_OBJECT,
64     JS_SET,
65     JS_MAP,
66     JS_ARRAY,
67     JS_ARRAY_BUFFER,
68     JS_SHARED_ARRAY_BUFFER,
69     JS_TRANSFER_ARRAY_BUFFER,
70     // TypedArray begin
71     JS_UINT8_ARRAY,
72     JS_UINT8_CLAMPED_ARRAY,
73     JS_UINT16_ARRAY,
74     JS_UINT32_ARRAY,
75     JS_INT8_ARRAY,
76     JS_INT16_ARRAY,
77     JS_INT32_ARRAY,
78     JS_FLOAT32_ARRAY,
79     JS_FLOAT64_ARRAY,
80     JS_BIGINT64_ARRAY,
81     JS_BIGUINT64_ARRAY,
82     // TypedArray end
83     // Support tagged object id reference end
84     // Error UIDs
85     JS_ERROR,
86     EVAL_ERROR,
87     RANGE_ERROR,
88     REFERENCE_ERROR,
89     TYPE_ERROR,
90     AGGREGATE_ERROR,
91     URI_ERROR,
92     SYNTAX_ERROR,
93     OOM_ERROR,
94     ERROR_MESSAGE_BEGIN,
95     ERROR_MESSAGE_END,
96     // Function begin
97     CONCURRENT_FUNCTION,
98     METHOD,
99     NATIVE_METHOD,
100     TAGGED_ARRAY,
101     // Function end
102     BYTE_ARRAY,
103     UID_END,
104     UNKNOWN
105 };
106 
107 class JSSerializer {
108 public:
JSSerializer(JSThread * thread)109     explicit JSSerializer(JSThread *thread) : thread_(thread) {}
110     ~JSSerializer() = default;
111     bool SerializeJSTaggedValue(const JSHandle<JSTaggedValue> &value);
112     void InitTransferSet(CUnorderedSet<uintptr_t> transferDataSet);
113     void ClearTransferSet();
114 
115     // Return pointer to the buffer and its length, should not use this Serializer anymore after Release
116     std::pair<uint8_t *, size_t> ReleaseBuffer();
117 
118 private:
119     bool WriteJSFunction(const JSHandle<JSTaggedValue> &value);
120     bool WriteMethod(const JSHandle<JSTaggedValue> &value);
121     bool WriteConstantPool(const JSHandle<JSTaggedValue> &value);
122     bool WriteTaggedArray(const JSHandle<JSTaggedValue> &value);
123     bool WriteByteArray(const JSHandle<JSTaggedValue> &value, DataViewType viewType);
124     bool WriteTaggedObject(const JSHandle<JSTaggedValue> &value);
125     bool WritePrimitiveValue(const JSHandle<JSTaggedValue> &value);
126     bool WriteInt(int32_t value);
127     bool WriteDouble(double value);
128     bool WriteRawData(const void *data, size_t length);
129     bool WriteType(SerializationUID uId);
130     bool AllocateBuffer(size_t bytes);
131     bool ExpandBuffer(size_t requestedSize);
132     bool WriteBoolean(bool value);
133     bool WriteJSError(const JSHandle<JSTaggedValue> &value);
134     bool WriteJSErrorHeader(JSType type);
135     bool WriteJSDate(const JSHandle<JSTaggedValue> &value);
136     bool WriteJSArray(const JSHandle<JSTaggedValue> &value);
137     bool WriteJSMap(const JSHandle<JSTaggedValue> &value);
138     bool WriteJSSet(const JSHandle<JSTaggedValue> &value);
139     bool WriteJSRegExp(const JSHandle<JSTaggedValue> &value);
140     bool WriteEcmaString(const JSHandle<JSTaggedValue> &value);
141     bool WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId);
142     bool WritePlainObject(const JSHandle<JSTaggedValue> &value);
143     bool WriteNativeBindingObject(const JSHandle<JSTaggedValue> &value);
144     bool WriteJSNativePointer(const JSHandle<JSNativePointer> &value);
145     bool WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value);
146     bool WriteBigInt(const JSHandle<JSTaggedValue> &value);
147     bool WriteDesc(const PropertyDescriptor &desc);
148     bool IsNativeBindingObject(std::vector<JSTaggedValue> keyVector);
149     bool IsTargetSymbol(JSTaggedValue symbolVal);
150     bool IsSerialized(uintptr_t addr) const;
151     bool WriteIfSerialized(uintptr_t addr);
152     uint32_t GetDataViewTypeIndex(const DataViewType dataViewType);
153     bool WriteString(const CString &str);
154 
155     NO_MOVE_SEMANTIC(JSSerializer);
156     NO_COPY_SEMANTIC(JSSerializer);
157 
158     JSThread *thread_;
159     uint8_t *buffer_ = nullptr;
160     uint64_t sizeLimit_ = 0;
161     size_t bufferSize_ = 0;
162     size_t bufferCapacity_ = 0;
163     // The Reference map is used for check whether a tagged object has been serialized
164     // Reference map works only if no gc happens during serialization
165     CUnorderedMap<uintptr_t, uint64_t> referenceMap_;
166     CUnorderedSet<uintptr_t> transferDataSet_;
167     uint64_t objectId_ = 0;
168 };
169 
170 class JSDeserializer {
171 public:
172     // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
173     JSDeserializer(JSThread *thread, uint8_t *data, size_t size, void *hint = nullptr)
thread_(thread)174         : thread_(thread), factory_(thread->GetEcmaVM()->GetFactory()),
175         begin_(data), position_(data), end_(data + size), engine_(hint)
176     {
177     }
178     ~JSDeserializer();
179     JSHandle<JSTaggedValue> Deserialize();
180 
181 private:
182     bool ReadInt(int32_t *value);
183     bool ReadObjectId(uint64_t *objectId);
184     bool ReadDouble(double *value);
185     SerializationUID ReadType();
186     JSHandle<JSTaggedValue> ReadJSFunctionBase();
187     JSHandle<JSTaggedValue> ReadJSFunction();
188     JSHandle<JSTaggedValue> ReadTaggedArray();
189     JSHandle<JSTaggedValue> ReadByteArray();
190     JSHandle<JSTaggedValue> ReadMethod();
191     JSHandle<JSTaggedValue> ReadNativeMethod();
192     JSHandle<JSTaggedValue> ReadJSError(SerializationUID uid);
193     JSHandle<JSTaggedValue> ReadJSDate();
194     JSHandle<JSTaggedValue> ReadJSArray();
195     JSHandle<JSTaggedValue> ReadPlainObject();
196     JSHandle<JSTaggedValue> ReadEcmaString();
197     JSHandle<JSTaggedValue> ReadJSMap();
198     JSHandle<JSTaggedValue> ReadJSSet();
199     JSHandle<JSTaggedValue> ReadJSRegExp();
200     JSHandle<JSTaggedValue> ReadJSTypedArray(SerializationUID uid);
201     JSHandle<JSTaggedValue> ReadJSNativePointer();
202     JSHandle<JSTaggedValue> ReadJSArrayBuffer(SerializationUID uid);
203     JSHandle<JSTaggedValue> ReadReference();
204     JSHandle<JSTaggedValue> ReadNativeBindingObject();
205     JSHandle<JSTaggedValue> ReadBigInt();
206     JSHandle<JSTaggedValue> DeserializeJSTaggedValue();
207     bool JudgeType(SerializationUID targetUid);
208     void *GetBuffer(uint32_t bufferSize);
209     bool ReadJSTaggedValue(JSTaggedValue *originalFlags);
210     bool ReadNativePointer(uintptr_t *pointer);
211     bool DefinePropertiesAndElements(const JSHandle<JSTaggedValue> &obj);
212     bool ReadDesc(PropertyDescriptor *desc);
213     bool ReadBoolean(bool *value);
214     bool ReadString(CString *value);
215     DataViewType GetDataViewTypeByIndex(uint32_t viewTypeIndex);
216 
217     NO_MOVE_SEMANTIC(JSDeserializer);
218     NO_COPY_SEMANTIC(JSDeserializer);
219 
220     JSThread *thread_ = nullptr;
221     ObjectFactory *factory_ = nullptr;
222     uint8_t *begin_ = nullptr;
223     const uint8_t *position_ = nullptr;
224     const uint8_t *end_ = nullptr;
225     uint64_t objectId_ = 0;
226     CUnorderedMap<uint64_t, JSHandle<JSTaggedValue>> referenceMap_;
227     void *engine_ = nullptr;
228 };
229 
230 class SerializationData {
231 public:
SerializationData()232     SerializationData() : dataSize_(0), value_(nullptr) {}
233     ~SerializationData() = default;
234 
GetData()235     uint8_t* GetData() const
236     {
237         return value_.get();
238     }
GetSize()239     size_t GetSize() const
240     {
241         return dataSize_;
242     }
243 
244 private:
245     struct Deleter {
operatorDeleter246         void operator()(uint8_t* ptr) const
247         {
248             free(ptr);
249         }
250     };
251 
252     size_t dataSize_;
253     std::unique_ptr<uint8_t, Deleter> value_;
254 
255 private:
256     friend class Serializer;
257 
258     NO_COPY_SEMANTIC(SerializationData);
259 };
260 
261 class Serializer {
262 public:
Serializer(JSThread * thread)263     explicit Serializer(JSThread *thread) : valueSerializer_(thread) {}
264     ~Serializer() = default;
265 
266     bool WriteValue(JSThread *thread, const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &transfer);
267     std::unique_ptr<SerializationData> Release();
268 
269 private:
270     bool PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer);
271 
272 private:
273     ecmascript::JSSerializer valueSerializer_;
274     std::unique_ptr<SerializationData> data_;
275 
276     NO_COPY_SEMANTIC(Serializer);
277 };
278 
279 class Deserializer {
280 public:
Deserializer(JSThread * thread,SerializationData * data,void * hint)281     Deserializer(JSThread *thread, SerializationData *data, void *hint)
282         : valueDeserializer_(thread, data->GetData(), data->GetSize(), hint), data_(data) {}
~Deserializer()283     ~Deserializer()
284     {
285         data_.reset(nullptr);
286     }
287 
288     JSHandle<JSTaggedValue> ReadValue();
289 
290 private:
291     ecmascript::JSDeserializer valueDeserializer_;
292     std::unique_ptr<SerializationData> data_;
293 
294     NO_COPY_SEMANTIC(Deserializer);
295 };
296 }  // namespace panda::ecmascript
297 
298 #endif // ECMASCRIPT_JS_SERIALIZER_H
299