SCASerialization.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js
  7. {
  8. //
  9. // SerializationCloner helps clone a Var to a stream location.
  10. //
  11. template <class Writer>
  12. class SerializationCloner:
  13. public ClonerBase<Var, scaposition_t, TypeId, SerializationCloner<Writer> >
  14. {
  15. public:
  16. using typename ClonerBase<Var, scaposition_t, TypeId, SerializationCloner<Writer> >::Dst;
  17. using typename ClonerBase<Var, scaposition_t, TypeId, SerializationCloner<Writer> >::Src;
  18. using typename ClonerBase<Var, scaposition_t, TypeId, SerializationCloner<Writer> >::SrcTypeId;
  19. private:
  20. //AutoCOMPtr<ISCAContext> m_pSCAContext;
  21. Writer* m_writer;
  22. // AutoCOMPtr<ISCASerializable> m_pSCASerializable; // Temporary, QI from a host object
  23. JsUtil::List<SharedContents*, HeapAllocator>* m_sharedContentsrList;
  24. private:
  25. void WriteTypeId(SCATypeId typeId) const
  26. {
  27. Write(static_cast<uint32>(typeId));
  28. }
  29. void Write(uint32 data) const
  30. {
  31. m_writer->Write(data);
  32. }
  33. void Write(const char16* str, charcount_t len) const;
  34. void Write(const BYTE* bytes, uint32 len) const;
  35. //
  36. // Write a TypedArray or a DataView layout: [SCATypeId] [ArrayBuffer] [byteOffset] [length]
  37. //
  38. template <class T, bool clamped, bool isVirtual = false>
  39. void WriteTypedArray(Src src) const
  40. {
  41. typedef TypedArrayTrace<T, clamped, isVirtual> trace_type;
  42. typedef typename trace_type::TypedArrayType array_type;
  43. WriteTypeId(trace_type::GetSCATypeId());
  44. array_type* arr = VarTo<array_type>(src);
  45. this->GetEngine()->Clone(arr->GetArrayBuffer());
  46. Write(arr->GetByteOffset());
  47. Write(arr->GetLength());
  48. }
  49. static bool IsTypedArray(SrcTypeId typeId);
  50. void WriteTypedArray(SrcTypeId typeId, Src src) const;
  51. static bool IsSparseArray(JavascriptArray* arr);
  52. void WriteDenseArrayIndexProperties(JavascriptArray* arr);
  53. void WriteSparseArrayIndexProperties(JavascriptArray* arr);
  54. //
  55. // Write array index named properties.
  56. //
  57. template <class ArrayItemAccessor>
  58. void WriteArrayIndexProperties(JavascriptArray* arr)
  59. {
  60. ScriptContext* scriptContext = this->GetScriptContext();
  61. uint32 length = arr->GetLength();
  62. for (uint32 i = 0; i < length; i++)
  63. {
  64. Var value = nullptr;
  65. if (ArrayItemAccessor::GetItem(arr, i, &value, scriptContext))
  66. {
  67. this->GetEngine()->Clone(value);
  68. }
  69. else
  70. {
  71. WriteTypeId(SCA_None);
  72. }
  73. }
  74. }
  75. //
  76. // Write sparse array index named properties using an array index enumerator.
  77. //
  78. template <class IndexEnumerator, class ArrayItemAccessor>
  79. void WriteSparseArrayIndexProperties(typename IndexEnumerator::ArrayType* arr)
  80. {
  81. ScriptContext* scriptContext = this->GetScriptContext();
  82. IndexEnumerator e(arr);
  83. Var value = nullptr;
  84. while (e.MoveNext())
  85. {
  86. uint32 i = e.GetIndex();
  87. if (ArrayItemAccessor::GetItem(arr, i, &value, scriptContext))
  88. {
  89. Write(i);
  90. this->GetEngine()->Clone(value);
  91. }
  92. }
  93. Write(static_cast<uint32>(SCA_PROPERTY_TERMINATOR));
  94. }
  95. //
  96. // Write a SCAProperties section: {SCAPropertyName SCAValue} SCAPropertiesTerminator
  97. //
  98. template <class Enumerator>
  99. void WriteObjectProperties(Enumerator* enumerator)
  100. {
  101. while (enumerator->MoveNext())
  102. {
  103. // Write property name
  104. Write(enumerator->GetNameString(), enumerator->GetNameLength());
  105. // Write property value
  106. this->GetEngine()->Clone(enumerator->GetValue());
  107. }
  108. // Write property terminator
  109. m_writer->Write(static_cast<uint32>(SCA_PROPERTY_TERMINATOR));
  110. }
  111. // Direct item accessor used on non-crosssite JavascriptArray for WriteArrayIndexProperties.
  112. class JavascriptArrayDirectItemAccessor
  113. {
  114. public:
  115. static BOOL GetItem(JavascriptArray* arr, uint32 index, Var* value, ScriptContext* scriptContext)
  116. {
  117. return arr->GetItem(arr, index, value, scriptContext);
  118. }
  119. };
  120. // Item accessor used on cross-site JavascriptArray for WriteArrayIndexProperties.
  121. class JavascriptArrayItemAccessor
  122. {
  123. public:
  124. static BOOL GetItem(JavascriptArray* arr, uint32 index, Var* value, ScriptContext* scriptContext)
  125. {
  126. return JavascriptOperators::GetOwnItem(arr, index, value, scriptContext);
  127. }
  128. };
  129. // Item accessor used on ES5Array for WriteArrayIndexProperties.
  130. class JavascriptArrayEnumerableItemAccessor
  131. {
  132. public:
  133. static BOOL GetItem(JavascriptArray* arr, uint32 index, Var* value, ScriptContext* scriptContext)
  134. {
  135. return arr->IsItemEnumerable(index)
  136. && JavascriptOperators::GetOwnItem(arr, index, value, scriptContext);
  137. }
  138. };
  139. public:
  140. SerializationCloner(ScriptContext* scriptContext, Writer* writer, JsUtil::List<SharedContents*, HeapAllocator>* sharedContentsrList)
  141. : ClonerBase<Var, scaposition_t, TypeId, SerializationCloner<Writer> >(scriptContext), m_writer(writer), m_sharedContentsrList(sharedContentsrList)
  142. {
  143. }
  144. static bool ShouldLookupReference()
  145. {
  146. // Always lookup reference when cloning Vars
  147. return true;
  148. }
  149. SrcTypeId GetTypeId(Src src) const
  150. {
  151. return JavascriptOperators::GetTypeId(src);
  152. }
  153. bool TryClonePrimitive(SrcTypeId typeId, Src src, Dst* dst);
  154. bool TryCloneObject(SrcTypeId typeId, Src src, Dst* dst, SCADeepCloneType* deepClone);
  155. void CloneProperties(SrcTypeId typeId, Src src, Dst dst);
  156. void CloneHostObjectProperties(SrcTypeId typeId, Src src, Dst dst);
  157. void CloneMap(Src src, Dst dst);
  158. void CloneSet(Src src, Dst dst);
  159. void CloneObjectReference(Src src, Dst dst);
  160. bool CanBeTransferred(SrcTypeId typeId) { return typeId == TypeIds_ArrayBuffer; }
  161. };
  162. //
  163. // Object property enumerator for WriteObjectProperties.
  164. //
  165. class ObjectPropertyEnumerator: public ScriptContextHolder
  166. {
  167. private:
  168. RecyclableObject* m_obj;
  169. JavascriptStaticEnumerator* m_innerEnumerator;
  170. JavascriptString* m_name;
  171. Var m_value;
  172. public:
  173. ObjectPropertyEnumerator(ScriptContext* scriptContext, RecyclableObject* obj, JavascriptStaticEnumerator* enumerator)
  174. : ScriptContextHolder(scriptContext),
  175. m_obj(obj),
  176. m_innerEnumerator(enumerator),
  177. m_name(NULL),
  178. m_value(NULL)
  179. {
  180. }
  181. bool MoveNext();
  182. const char16* GetNameString() const
  183. {
  184. return m_name->GetString();
  185. }
  186. charcount_t GetNameLength() const
  187. {
  188. return m_name->GetLength();
  189. }
  190. Var GetValue() const
  191. {
  192. return m_value;
  193. }
  194. };
  195. //
  196. // Template and specializations for TypedArray/DataView SCA.
  197. //
  198. template <class T, bool clamped = false, bool isVirtual = false> struct TypedArrayTrace
  199. {
  200. // Generic TypedArrayTrace is empty. Specializations provide implementation.
  201. };
  202. // Base implementation shared by data type TypedArrays.
  203. template <class T, bool clamped = false, bool isVirtual = false> struct TypedArrayTraceBase
  204. {
  205. typedef TypedArray<T,clamped, isVirtual> TypedArrayType;
  206. static Var CreateTypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 length,
  207. ScriptContext* scriptContext)
  208. {
  209. JavascriptLibrary* lib = scriptContext->GetLibrary();
  210. return TypedArrayType::Create(arrayBuffer, byteOffset, length, lib);
  211. }
  212. };
  213. template<> struct TypedArrayTrace<int8>: TypedArrayTraceBase<int8>
  214. {
  215. static SCATypeId GetSCATypeId() { return SCA_Int8Array; }
  216. };
  217. template<> struct TypedArrayTrace<uint8, false>: TypedArrayTraceBase<uint8, false>
  218. {
  219. static SCATypeId GetSCATypeId() { return SCA_Uint8Array; }
  220. };
  221. template<> struct TypedArrayTrace<uint8, true>: TypedArrayTraceBase<uint8, true>
  222. {
  223. static SCATypeId GetSCATypeId() { return SCA_Uint8ClampedArray; }
  224. };
  225. template<> struct TypedArrayTrace<int16>: TypedArrayTraceBase<int16>
  226. {
  227. static SCATypeId GetSCATypeId() { return SCA_Int16Array; }
  228. };
  229. template<> struct TypedArrayTrace<uint16>: TypedArrayTraceBase<uint16>
  230. {
  231. static SCATypeId GetSCATypeId() { return SCA_Uint16Array; }
  232. };
  233. template<> struct TypedArrayTrace<int32>: TypedArrayTraceBase<int32>
  234. {
  235. static SCATypeId GetSCATypeId() { return SCA_Int32Array; }
  236. };
  237. template<> struct TypedArrayTrace<uint32>: TypedArrayTraceBase<uint32>
  238. {
  239. static SCATypeId GetSCATypeId() { return SCA_Uint32Array; }
  240. };
  241. template<> struct TypedArrayTrace<float>: TypedArrayTraceBase<float>
  242. {
  243. static SCATypeId GetSCATypeId() { return SCA_Float32Array; }
  244. };
  245. template<> struct TypedArrayTrace<double>: TypedArrayTraceBase<double>
  246. {
  247. static SCATypeId GetSCATypeId() { return SCA_Float64Array; }
  248. };
  249. template<> struct TypedArrayTrace<int8, false,true>: TypedArrayTraceBase<int8,false,true>
  250. {
  251. static SCATypeId GetSCATypeId() { return SCA_Int8Array; }
  252. };
  253. template<> struct TypedArrayTrace<uint8, false,true>: TypedArrayTraceBase<uint8, false,true>
  254. {
  255. static SCATypeId GetSCATypeId() { return SCA_Uint8Array; }
  256. };
  257. template<> struct TypedArrayTrace<uint8, true,true>: TypedArrayTraceBase<uint8, true,true>
  258. {
  259. static SCATypeId GetSCATypeId() { return SCA_Uint8ClampedArray; }
  260. };
  261. template<> struct TypedArrayTrace<int16,false,true>: TypedArrayTraceBase<int16,false,true>
  262. {
  263. static SCATypeId GetSCATypeId() { return SCA_Int16Array; }
  264. };
  265. template<> struct TypedArrayTrace<uint16,false,true>: TypedArrayTraceBase<uint16,false,true>
  266. {
  267. static SCATypeId GetSCATypeId() { return SCA_Uint16Array; }
  268. };
  269. template<> struct TypedArrayTrace<int32,false,true>: TypedArrayTraceBase<int32,false,true>
  270. {
  271. static SCATypeId GetSCATypeId() { return SCA_Int32Array; }
  272. };
  273. template<> struct TypedArrayTrace<uint32,false,true>: TypedArrayTraceBase<uint32,false,true>
  274. {
  275. static SCATypeId GetSCATypeId() { return SCA_Uint32Array; }
  276. };
  277. template<> struct TypedArrayTrace<float, false, true>: TypedArrayTraceBase<float, false, true>
  278. {
  279. static SCATypeId GetSCATypeId() { return SCA_Float32Array; }
  280. };
  281. template<> struct TypedArrayTrace<double, false, true>: TypedArrayTraceBase<double, false, true>
  282. {
  283. static SCATypeId GetSCATypeId() { return SCA_Float64Array; }
  284. };
  285. template<> struct TypedArrayTrace<DataView>
  286. {
  287. typedef DataView TypedArrayType;
  288. static Var CreateTypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 length,
  289. ScriptContext* scriptContext)
  290. {
  291. JavascriptLibrary* lib = scriptContext->GetLibrary();
  292. return lib->CreateDataView(arrayBuffer, byteOffset, length);
  293. }
  294. static SCATypeId GetSCATypeId() { return SCA_DataView; }
  295. };
  296. class SCASerializationEngine
  297. {
  298. typedef SerializationCloner<StreamWriter> StreamSerializationCloner;
  299. public:
  300. static void Serialize(Var root, StreamWriter* writer, Var* transferableVars, size_t cTransferableVars,
  301. JsUtil::List<Js::SharedContents*, HeapAllocator>* sharedContentsList);
  302. };
  303. }