• 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 <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/jspandafile/js_pandafile.h"
29 #include "ecmascript/jspandafile/program_object.h"
30 #include "ecmascript/mem/dyn_chunk.h"
31 #include "ecmascript/napi/jsnapi_helper.h"
32 #include "ecmascript/napi/include/jsnapi.h"
33 
34 using panda::JSValueRef;
35 namespace panda::ecmascript {
36 class JSPandaFile;
37 class ConstantPool;
38 
39 typedef void* (*DetachFunc)(void *enginePointer, void *objPointer, void *hint, void *detachData);
40 typedef Local<JSValueRef> (*AttachFunc)(void *enginePointer, void *buffer, void *hint, void *attachData);
41 
42 enum class SerializationUID : uint8_t {
43     // JS special values
44     JS_NULL = 0x01,
45     JS_UNDEFINED,
46     JS_TRUE,
47     JS_FALSE,
48     HOLE,
49     // Number types
50     INT32,
51     DOUBLE,
52     // Not support yet, BigInt type has not been implemented in ark engine
53     BIGINT,
54     ECMASTRING,
55     // Boolean types
56     C_TRUE,
57     C_FALSE,
58     // Tagged object reference mark
59     TAGGED_OBJECT_REFERNCE,
60     // Support tagged object id reference begin
61     JS_DATE,
62     JS_REG_EXP,
63     JS_PLAIN_OBJECT,
64     NATIVE_BINDING_OBJECT,
65     JS_SET,
66     JS_MAP,
67     JS_ARRAY,
68     JS_ARRAY_BUFFER,
69     JS_SHARED_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     JS_METHOD,
99     NATIVE_METHOD,
100     CONSTANT_POOL,
101     TAGGED_ARRAY,
102     // Function end
103     BYTE_ARRAY,
104     NATIVE_POINTER,
105     UNKNOWN
106 };
107 
108 class JSSerializer {
109 public:
JSSerializer(JSThread * thread)110     explicit JSSerializer(JSThread *thread) : thread_(thread) {}
111     ~JSSerializer() = default;
112     bool SerializeJSTaggedValue(const JSHandle<JSTaggedValue> &value);
113 
114     // Return pointer to the buffer and its length, should not use this Serializer anymore after Release
115     std::pair<uint8_t *, size_t> ReleaseBuffer();
116 
117 private:
118     bool WriteJSFunction(const JSHandle<JSTaggedValue> &value);
119     bool WriteMethod(const JSHandle<JSTaggedValue> &value);
120     bool WriteConstantPool(const JSHandle<JSTaggedValue> &value);
121     bool WriteTaggedArray(const JSHandle<JSTaggedValue> &value);
122     bool WriteByteArray(const JSHandle<JSTaggedValue> &value, DataViewType viewType);
123     bool WriteTaggedObject(const JSHandle<JSTaggedValue> &value);
124     bool WritePrimitiveValue(const JSHandle<JSTaggedValue> &value);
125     bool WriteInt(int32_t value);
126     bool WriteDouble(double value);
127     bool WriteRawData(const void *data, size_t length);
128     bool WriteType(SerializationUID uId);
129     bool AllocateBuffer(size_t bytes);
130     bool ExpandBuffer(size_t requestedSize);
131     bool WriteBoolean(bool value);
132     bool WriteJSError(const JSHandle<JSTaggedValue> &value);
133     bool WriteJSErrorHeader(JSType type);
134     bool WriteJSDate(const JSHandle<JSTaggedValue> &value);
135     bool WriteJSArray(const JSHandle<JSTaggedValue> &value);
136     bool WriteJSMap(const JSHandle<JSTaggedValue> &value);
137     bool WriteJSSet(const JSHandle<JSTaggedValue> &value);
138     bool WriteJSRegExp(const JSHandle<JSTaggedValue> &value);
139     bool WriteEcmaString(const JSHandle<JSTaggedValue> &value);
140     bool WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId);
141     bool WritePlainObject(const JSHandle<JSTaggedValue> &value);
142     bool WriteNativeBindingObject(const JSHandle<JSTaggedValue> &value);
143     bool WriteNativePointer(const JSHandle<JSTaggedValue> &value);
144     bool WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value);
145     bool WriteDesc(const PropertyDescriptor &desc);
146     bool IsNativeBindingObject(std::vector<JSTaggedValue> keyVector);
147     bool IsTargetSymbol(JSTaggedValue symbolVal);
148     bool IsSerialized(uintptr_t addr) const;
149     bool WriteIfSerialized(uintptr_t addr);
150     uint32_t GetDataViewTypeIndex(const DataViewType dataViewType);
151 
152     NO_MOVE_SEMANTIC(JSSerializer);
153     NO_COPY_SEMANTIC(JSSerializer);
154 
155     JSThread *thread_;
156     uint8_t *buffer_ = nullptr;
157     uint64_t sizeLimit_ = 0;
158     size_t bufferSize_ = 0;
159     size_t bufferCapacity_ = 0;
160     // The Reference map is used for check whether a tagged object has been serialized
161     // Reference map works only if no gc happens during serialization
162     std::map<uintptr_t, uint64_t> referenceMap_;
163     uint64_t objectId_ = 0;
164 };
165 
166 class JSDeserializer {
167 public:
168     // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
169     JSDeserializer(JSThread *thread, uint8_t *data, size_t size, void *hint = nullptr)
thread_(thread)170         : thread_(thread), factory_(thread->GetEcmaVM()->GetFactory()),
171         begin_(data), position_(data), end_(data + size), engine_(hint)
172     {
173     }
174     ~JSDeserializer();
175     JSHandle<JSTaggedValue> DeserializeJSTaggedValue();
176 
177 private:
178     bool ReadInt(int32_t *value);
179     bool ReadObjectId(uint64_t *objectId);
180     bool ReadDouble(double *value);
181     SerializationUID ReadType();
182     JSHandle<JSTaggedValue> ReadJSFunctionBase();
183     JSHandle<JSTaggedValue> ReadJSFunction();
184     JSHandle<JSTaggedValue> ReadTaggedArray();
185     JSHandle<JSTaggedValue> ReadByteArray();
186     JSHandle<JSTaggedValue> ReadJSMethod();
187     JSHandle<JSTaggedValue> ReadNativeMethod();
188     JSHandle<JSTaggedValue> ReadConstantPool();
189     JSHandle<JSTaggedValue> ReadJSError(SerializationUID uid);
190     JSHandle<JSTaggedValue> ReadJSDate();
191     JSHandle<JSTaggedValue> ReadJSArray();
192     JSHandle<JSTaggedValue> ReadPlainObject();
193     JSHandle<JSTaggedValue> ReadEcmaString();
194     JSHandle<JSTaggedValue> ReadJSMap();
195     JSHandle<JSTaggedValue> ReadJSSet();
196     JSHandle<JSTaggedValue> ReadJSRegExp();
197     JSHandle<JSTaggedValue> ReadJSTypedArray(SerializationUID uid);
198     JSHandle<JSTaggedValue> ReadNativePointer();
199     JSHandle<JSTaggedValue> ReadJSArrayBuffer();
200     JSHandle<JSTaggedValue> ReadReference();
201     JSHandle<JSTaggedValue> ReadNativeBindingObject();
202     bool JudgeType(SerializationUID targetUid);
203     void *GetBuffer(uint32_t bufferSize);
204     bool ReadJSTaggedValue(JSTaggedValue *originalFlags);
205     bool ReadNativePointer(uintptr_t *pointer);
206     bool DefinePropertiesAndElements(const JSHandle<JSTaggedValue> &obj);
207     bool ReadDesc(PropertyDescriptor *desc);
208     bool ReadBoolean(bool *value);
209     DataViewType GetDataViewTypeByIndex(uint32_t viewTypeIndex);
210 
211     NO_MOVE_SEMANTIC(JSDeserializer);
212     NO_COPY_SEMANTIC(JSDeserializer);
213 
214     JSThread *thread_ = nullptr;
215     ObjectFactory *factory_ = nullptr;
216     uint8_t *begin_ = nullptr;
217     const uint8_t *position_ = nullptr;
218     const uint8_t * const end_ = nullptr;
219     uint64_t objectId_ = 0;
220     std::map<uint64_t, JSHandle<JSTaggedValue>> referenceMap_;
221     void *engine_ = nullptr;
222 };
223 
224 class SerializationData {
225 public:
SerializationData()226     SerializationData() : dataSize_(0), value_(nullptr) {}
227     ~SerializationData() = default;
228 
GetData()229     uint8_t* GetData() const
230     {
231         return value_.get();
232     }
GetSize()233     size_t GetSize() const
234     {
235         return dataSize_;
236     }
237 
238 private:
239     struct Deleter {
operatorDeleter240         void operator()(uint8_t* ptr) const
241         {
242             free(ptr);
243         }
244     };
245 
246     size_t dataSize_;
247     std::unique_ptr<uint8_t, Deleter> value_;
248 
249 private:
250     friend class Serializer;
251 
252     NO_COPY_SEMANTIC(SerializationData);
253 };
254 
255 class Serializer {
256 public:
Serializer(JSThread * thread)257     explicit Serializer(JSThread *thread) : valueSerializer_(thread) {}
258     ~Serializer() = default;
259 
260     bool WriteValue(JSThread *thread, const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &transfer);
261     std::unique_ptr<SerializationData> Release();
262 
263 private:
264     bool PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer);
265     bool FinalizeTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer);
266 
267 private:
268     ecmascript::JSSerializer valueSerializer_;
269     std::unique_ptr<SerializationData> data_;
270     CVector<int> arrayBufferIdxs_;
271 
272     NO_COPY_SEMANTIC(Serializer);
273 };
274 
275 class Deserializer {
276 public:
Deserializer(JSThread * thread,SerializationData * data,void * hint)277     explicit Deserializer(JSThread *thread, SerializationData *data, void *hint)
278         : valueDeserializer_(thread, data->GetData(), data->GetSize(), hint) {}
279     ~Deserializer() = default;
280 
281     JSHandle<JSTaggedValue> ReadValue();
282 
283 private:
284     ecmascript::JSDeserializer valueDeserializer_;
285 
286     NO_COPY_SEMANTIC(Deserializer);
287 };
288 }  // namespace panda::ecmascript
289 
290 #endif // ECMASCRIPT_JS_SERIALIZER_H