SCADeserialization.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. class SCAPropBag;
  9. //
  10. // DeserializationCloner helps clone a Var from a stream location.
  11. //
  12. template <class Reader>
  13. class DeserializationCloner:
  14. public ClonerBase<scaposition_t, Var, SCATypeId, DeserializationCloner<Reader> >
  15. {
  16. public:
  17. using typename ClonerBase<scaposition_t, Var, SCATypeId, DeserializationCloner<Reader> >::Dst;
  18. using typename ClonerBase<scaposition_t, Var, SCATypeId, DeserializationCloner<Reader> >::Src;
  19. using typename ClonerBase<scaposition_t, Var, SCATypeId, DeserializationCloner<Reader> >::SrcTypeId;
  20. private:
  21. //AutoCOMPtr<ISCAHost> m_pSCAHost;
  22. //AutoCOMPtr<ISCAContext> m_pSCAContext;
  23. Reader* m_reader;
  24. mutable char16* m_buffer;
  25. mutable charcount_t m_bufferLength;
  26. private:
  27. SCATypeId ReadTypeId() const
  28. {
  29. uint32 typeId;
  30. m_reader->Read(&typeId);
  31. return static_cast<SCATypeId>(typeId);
  32. }
  33. void Read(uint32* value) const
  34. {
  35. m_reader->Read(value);
  36. }
  37. const char16* TryReadString(charcount_t* len, bool reuseBuffer) const;
  38. const char16* ReadString(charcount_t* len) const;
  39. void Read(BYTE* buf, uint32 len) const;
  40. //
  41. // Read a TypedArray or DataView.
  42. //
  43. template <class T, bool clamped>
  44. void ReadTypedArray(Dst* dst) const
  45. {
  46. typedef TypedArrayTrace<T,clamped> trace_type;
  47. Dst arrayBuffer;
  48. this->GetEngine()->Clone(m_reader->GetPosition(), &arrayBuffer);
  49. if (!arrayBuffer || !VarIs<ArrayBufferBase>(arrayBuffer))
  50. {
  51. this->ThrowSCADataCorrupt();
  52. }
  53. uint32 byteOffset, length;
  54. Read(&byteOffset);
  55. Read(&length);
  56. *dst = trace_type::CreateTypedArray(
  57. VarTo<ArrayBufferBase>(arrayBuffer), byteOffset, length, this->GetScriptContext());
  58. }
  59. void ReadTypedArray(SrcTypeId typeId, Dst* dst) const;
  60. //
  61. // Read a SCAProperties section: {SCAPropertyName SCAValue} SCAPropertiesTerminator
  62. //
  63. void ReadObjectPropertiesIntoObject(RecyclableObject* m_obj)
  64. {
  65. ScriptContext* scriptContext = this->GetScriptContext();
  66. for(;;)
  67. {
  68. charcount_t len = 0;
  69. const char16* name = TryReadString(&len, /*reuseBuffer*/ true);
  70. if (!name)
  71. {
  72. break;
  73. }
  74. Js::PropertyRecord const * propertyRecord;
  75. scriptContext->GetOrAddPropertyRecord(name, len, &propertyRecord);
  76. // NOTE: 'Clone' may reenter here and use the buffer that backs the 'name'.
  77. // That is ok, since we do not need it past this point.
  78. // The propertyRecord keeps its own copy od the data.
  79. Var value;
  80. this->GetEngine()->Clone(m_reader->GetPosition(), &value);
  81. if (!value)
  82. {
  83. this->ThrowSCADataCorrupt();
  84. }
  85. m_obj->SetProperty(propertyRecord->GetPropertyId(), value, PropertyOperation_None, NULL); //Note: no prototype check
  86. }
  87. }
  88. void ReadObjectPropertiesIntoBag(SCAPropBag* m_propbag)
  89. {
  90. for (;;)
  91. {
  92. charcount_t len = 0;
  93. // NOTE: we will not reuse buffer here since the propbag may retain the string.
  94. const char16* name = TryReadString(&len, /*reuseBuffer*/ false);
  95. if (!name)
  96. {
  97. break;
  98. }
  99. Var value;
  100. this->GetEngine()->Clone(m_reader->GetPosition(), &value);
  101. if (!value)
  102. {
  103. this->ThrowSCADataCorrupt();
  104. }
  105. HRESULT hr = m_propbag->InternalAddNoCopy(name, len, value);
  106. m_propbag->ThrowIfFailed(hr);
  107. }
  108. }
  109. public:
  110. DeserializationCloner(ScriptContext* scriptContext, Reader* reader)
  111. : ClonerBase<scaposition_t, Var, SCATypeId, DeserializationCloner<Reader> >(scriptContext), m_reader(reader),
  112. m_buffer(nullptr), m_bufferLength(0)
  113. {
  114. }
  115. static bool ShouldLookupReference()
  116. {
  117. // Never lookup reference when cloning from stream location. DeserializationCloner
  118. // handles object reference lookup explictly when seeing a reference SCATypeId.
  119. return false;
  120. }
  121. SrcTypeId GetTypeId(Src src) const
  122. {
  123. Assert(m_reader->GetPosition() == src); // Only allow the current position
  124. return ReadTypeId();
  125. }
  126. void ThrowSCAUnsupported() const
  127. {
  128. // Unexpected SCATypeId indicates data corruption.
  129. this->ThrowSCADataCorrupt();
  130. }
  131. bool TryClonePrimitive(SrcTypeId typeId, Src src, Dst* dst);
  132. bool TryCloneObject(SrcTypeId typeId, Src src, Dst* dst, SCADeepCloneType* deepClone);
  133. void CloneProperties(SrcTypeId typeId, Src src, Dst dst);
  134. void CloneHostObjectProperties(SrcTypeId typeId, Src src, Dst dst);
  135. void CloneMap(Src src, Dst dst);
  136. void CloneSet(Src src, Dst dst);
  137. void CloneObjectReference(Src src, Dst dst);
  138. };
  139. class SCADeserializationEngine
  140. {
  141. typedef DeserializationCloner<StreamReader> StreamDeserializationCloner;
  142. public:
  143. static Var Deserialize(StreamReader* reader, Var* transferableVars, size_t cTransferableVars);
  144. };
  145. }