JavascriptProxy.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. // Implements JavascriptProxy.
  6. //----------------------------------------------------------------------------
  7. #pragma once
  8. namespace Js
  9. {
  10. // Host should keep the same object in cross-site scenario.
  11. class JavascriptProxy : public DynamicObject
  12. {
  13. friend class JavascriptOperators;
  14. protected:
  15. DEFINE_VTABLE_CTOR(JavascriptProxy, DynamicObject);
  16. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptProxy);
  17. private:
  18. Field(RecyclableObject*) handler;
  19. Field(RecyclableObject*) target;
  20. void RevokeObject();
  21. public:
  22. static const uint32 MAX_STACK_CALL_ARGUMENT_COUNT = 20;
  23. class EntryInfo
  24. {
  25. public:
  26. static FunctionInfo NewInstance;
  27. static FunctionInfo Revocable;
  28. static FunctionInfo Revoke;
  29. };
  30. typedef enum SetPropertyTrapKind {
  31. SetItemOnTaggedNumberKind,
  32. SetPropertyOnTaggedNumberKind,
  33. SetPropertyKind,
  34. SetItemKind,
  35. SetPropertyWPCacheKind,
  36. } SetPropertyTrapKind;
  37. enum KeysTrapKind {
  38. GetOwnPropertyNamesKind,
  39. GetOwnPropertySymbolKind,
  40. KeysKind
  41. };
  42. enum IntegrityLevel {
  43. IntegrityLevel_sealed,
  44. IntegrityLevel_frozen
  45. };
  46. JavascriptProxy(DynamicType * type);
  47. JavascriptProxy(DynamicType * type, ScriptContext * scriptContext, RecyclableObject* target, RecyclableObject* handler);
  48. // before recursively calling something on 'target' use this helper in case there is nesting of proxies.
  49. // the proxies could be deep nested and cause SO when processed recursively.
  50. static const JavascriptProxy* UnwrapNestedProxies(const JavascriptProxy* proxy);
  51. #ifndef IsJsDiag
  52. RecyclableObject* GetTarget();
  53. RecyclableObject* GetHandler();
  54. #else
  55. RecyclableObject* GetTarget() { return target; }
  56. RecyclableObject* GetHandler() { return handler; }
  57. #endif
  58. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  59. static Var EntryRevocable(RecyclableObject* function, CallInfo callInfo, ...);
  60. static Var EntryRevoke(RecyclableObject* function, CallInfo callInfo, ...);
  61. static Var FunctionCallTrap(RecyclableObject* function, CallInfo callInfo, ...);
  62. static JavascriptProxy* Create(ScriptContext* scriptContext, Arguments args);
  63. static BOOL GetOwnPropertyDescriptor(RecyclableObject* obj, PropertyId propertyId, ScriptContext* requestContext, PropertyDescriptor* propertyDescriptor);
  64. static BOOL DefineOwnPropertyDescriptor(RecyclableObject* obj, PropertyId propId, const PropertyDescriptor& descriptor, bool throwOnError, ScriptContext* requestContext);
  65. static DWORD GetOffsetOfTarget() { return offsetof(JavascriptProxy, target); }
  66. virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId, _Inout_opt_ PropertyValueInfo* info) override;
  67. virtual BOOL HasOwnProperty(PropertyId propertyId) override;
  68. virtual BOOL HasOwnPropertyNoHostObject(PropertyId propertyId) override;
  69. virtual BOOL HasOwnPropertyCheckNoRedecl(PropertyId propertyId) override;
  70. virtual BOOL UseDynamicObjectForNoHostObjectAccess() override;
  71. virtual DescriptorFlags GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  72. virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  73. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  74. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  75. virtual BOOL GetInternalProperty(Var instance, PropertyId internalPropertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  76. _Check_return_ _Success_(return) virtual BOOL GetAccessors(PropertyId propertyId, _Outptr_result_maybenull_ Var* getter, _Outptr_result_maybenull_ Var* setter, ScriptContext* requestContext) override;
  77. virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  78. virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  79. virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  80. virtual BOOL SetInternalProperty(PropertyId internalPropertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  81. virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = NULL) override;
  82. virtual BOOL EnsureProperty(PropertyId propertyId) override;
  83. virtual BOOL EnsureNoRedeclProperty(PropertyId propertyId) override;
  84. virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
  85. virtual BOOL InitPropertyScoped(PropertyId propertyId, Var value) override;
  86. virtual BOOL InitFuncScoped(PropertyId propertyId, Var value) override;
  87. virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags) override;
  88. virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags) override;
  89. #if ENABLE_FIXED_FIELDS
  90. virtual BOOL IsFixedProperty(PropertyId propertyId) override;
  91. #endif
  92. virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
  93. virtual BOOL HasOwnItem(uint32 index) override;
  94. virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  95. virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  96. virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override;
  97. virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
  98. virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
  99. virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, EnumeratorCache * enumeratorCache = nullptr) override;
  100. virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None) override;
  101. virtual BOOL Equals(__in Var other, __out BOOL* value, ScriptContext* requestContext) override;
  102. virtual BOOL StrictEquals(__in Var other, __out BOOL* value, ScriptContext* requestContext) override;
  103. virtual BOOL IsWritable(PropertyId propertyId) override;
  104. virtual BOOL IsConfigurable(PropertyId propertyId) override;
  105. virtual BOOL IsEnumerable(PropertyId propertyId) override;
  106. virtual BOOL IsExtensible() override;
  107. virtual BOOL PreventExtensions() override;
  108. virtual void ThrowIfCannotDefineProperty(PropertyId propId, const PropertyDescriptor& descriptor) { }
  109. virtual BOOL Seal() override;
  110. virtual BOOL Freeze() override;
  111. virtual BOOL IsSealed() override;
  112. virtual BOOL IsFrozen() override;
  113. virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
  114. virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
  115. virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
  116. virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;
  117. virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) { return false; }
  118. virtual uint GetSpecialPropertyCount() const { return 0; }
  119. virtual PropertyId const * GetSpecialPropertyIds() const { return nullptr; }
  120. virtual BOOL HasInstance(Var instance, ScriptContext* scriptContext, IsInstInlineCache* inlineCache = NULL) override;
  121. // This is used for external object only; should not be called for proxy
  122. virtual RecyclableObject* GetConfigurablePrototype(ScriptContext * requestContext) override;
  123. virtual RecyclableObject* GetPrototypeSpecial() override;
  124. // for external object. don't need it here.
  125. virtual Js::JavascriptString* GetClassName(ScriptContext * requestContext) override;
  126. #if DBG
  127. virtual bool CanStorePropertyValueDirectly(PropertyId propertyId, bool allowLetConst) { Assert(false); return false; };
  128. #endif
  129. virtual void RemoveFromPrototype(ScriptContext * requestContext, bool * allProtoCachesInvalidated) override;
  130. virtual void AddToPrototype(ScriptContext * requestContext, bool * allProtoCachesInvalidated) override;
  131. virtual void SetPrototype(RecyclableObject* newPrototype) override;
  132. BOOL SetPrototypeTrap(RecyclableObject* newPrototype, bool showThrow, ScriptContext * requestContext);
  133. Var ToString(Js::ScriptContext* scriptContext);
  134. virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  135. virtual RecyclableObject* ToObject(ScriptContext * requestContext) override;
  136. virtual Var GetTypeOfString(ScriptContext* requestContext) override;
  137. bool IsRevoked() const;
  138. BOOL SetPropertyTrap(Var receiver, SetPropertyTrapKind setPropertyTrapKind, PropertyId propertyId, Var newValue, ScriptContext* requestContext, PropertyOperationFlags propertyOperationFlags, BOOL skipPrototypeCheck = FALSE);
  139. BOOL SetPropertyTrap(Var receiver, SetPropertyTrapKind setPropertyTrapKind, Js::JavascriptString * propertyString, Var newValue, ScriptContext* requestContext, PropertyOperationFlags propertyOperationFlags);
  140. void PropertyIdFromInt(uint32 index, PropertyRecord const** propertyRecord);
  141. JavascriptArray* PropertyKeysTrap(KeysTrapKind keysTrapKind, ScriptContext* requestContext);
  142. template <class Fn>
  143. void GetOwnPropertyKeysHelper(ScriptContext* scriptContext, RecyclableObject* trapResultArray, uint32 len, JavascriptArray* trapResult,
  144. JsUtil::BaseDictionary<Js::PropertyId, bool, ArenaAllocator>& targetToTrapResultMap, Fn fn)
  145. {
  146. Var element = nullptr;
  147. const PropertyRecord* propertyRecord;
  148. uint32 trapResultIndex = 0;
  149. PropertyId propertyId;
  150. for (uint32 i = 0; i < len; i++)
  151. {
  152. if (!JavascriptOperators::GetItem(trapResultArray, i, &element, scriptContext) || // missing
  153. !(VarIs<JavascriptString>(element) || VarIs<JavascriptSymbol>(element))) // neither String nor Symbol
  154. {
  155. JavascriptError::ThrowTypeError(scriptContext, JSERR_InconsistentTrapResult, _u("ownKeys"));
  156. }
  157. JavascriptConversion::ToPropertyKey(element, scriptContext, &propertyRecord, nullptr);
  158. propertyId = propertyRecord->GetPropertyId();
  159. if (propertyId != Constants::NoProperty)
  160. {
  161. if (targetToTrapResultMap.AddNew(propertyId, true) == -1)
  162. {
  163. JavascriptError::ThrowTypeError(scriptContext, JSERR_DuplicateKeysFromOwnPropertyKeys);
  164. }
  165. }
  166. if (fn(propertyRecord))
  167. {
  168. trapResult->DirectSetItemAt(trapResultIndex++, element);
  169. }
  170. }
  171. }
  172. Var ConstructorTrap(Arguments args, ScriptContext* scriptContext, const Js::AuxArray<uint32> *spreadIndices);
  173. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  174. static PropertyId EnsureHandlerPropertyId(ScriptContext* scriptContext);
  175. static RecyclableObject* AutoProxyWrapper(Var obj);
  176. #endif
  177. private:
  178. JavascriptFunction* GetMethodHelper(PropertyId methodId, ScriptContext* requestContext);
  179. Var GetValueFromDescriptor(Var instance, PropertyDescriptor propertyDescriptor, ScriptContext* requestContext);
  180. static Var GetName(ScriptContext* requestContext, PropertyId propertyId);
  181. RecyclableObject* MarshalHandler(ScriptContext* requestContext) const
  182. {
  183. return static_cast<RecyclableObject*>(
  184. CrossSite::MarshalVar(requestContext, handler));
  185. }
  186. RecyclableObject* MarshalTarget(ScriptContext* requestContext) const
  187. {
  188. return static_cast<RecyclableObject*>(
  189. CrossSite::MarshalVar(requestContext, target));
  190. }
  191. static BOOL TestIntegrityLevel(IntegrityLevel integrityLevel, RecyclableObject* obj, ScriptContext* scriptContext);
  192. static BOOL SetIntegrityLevel(IntegrityLevel integrityLevel, RecyclableObject* obj, ScriptContext* scriptContext);
  193. template <class Fn, class GetPropertyIdFunc>
  194. BOOL HasPropertyTrap(Fn fn, GetPropertyIdFunc getPropertyId);
  195. template <class Fn, class GetPropertyIdFunc>
  196. BOOL GetPropertyTrap(Var instance, PropertyDescriptor* propertyDescriptor, Fn fn, GetPropertyIdFunc getPropertyId, ScriptContext* requestContext);
  197. BOOL GetPropertyDescriptorTrap(PropertyId propertyId, PropertyDescriptor* resultDescriptor, ScriptContext* requestContext);
  198. #if ENABLE_TTD
  199. public:
  200. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
  201. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  202. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  203. #endif
  204. };
  205. template <> inline bool VarIsImpl<JavascriptProxy>(RecyclableObject* obj)
  206. {
  207. return JavascriptOperators::GetTypeId(obj) == TypeIds_Proxy;
  208. }
  209. }