2
0

DiagObjectModel.h 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  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 IDiagObjectAddress;
  9. class IDiagObjectModelDisplay;
  10. class RecyclableMethodsGroupWalker;
  11. class RecyclableObjectWalker;
  12. class RecyclableArrayWalker;
  13. // Concrete type for manipulating JS Vars
  14. struct ResolvedObject
  15. {
  16. ResolvedObject() : propId(Js::Constants::NoProperty), scriptContext(nullptr), address(nullptr),
  17. objectDisplay(nullptr), obj(nullptr), originalObj(nullptr), isConst(false), name(nullptr)
  18. {}
  19. PropertyId propId;
  20. ScriptContext *scriptContext;
  21. IDiagObjectAddress *address;
  22. IDiagObjectModelDisplay *objectDisplay;
  23. Var obj;
  24. Var originalObj;
  25. LPCWSTR name;
  26. TypeId typeId;
  27. bool isConst;
  28. WeakArenaReference<IDiagObjectModelDisplay>* GetObjectDisplay();
  29. IDiagObjectModelDisplay * CreateDisplay();
  30. bool IsInDeadZone() const;
  31. };
  32. // interfaces for manipulating DataTypes
  33. // Allow setting the value across different parent data types
  34. class IDiagObjectAddress
  35. {
  36. public:
  37. virtual BOOL Set(Var updateObject) = 0;
  38. virtual BOOL IsWritable() { return !IsInDeadZone(); }
  39. virtual Var GetValue(BOOL fUpdated) { return nullptr; }
  40. virtual BOOL IsInDeadZone() const { return FALSE; };
  41. };
  42. class IDiagObjectModelWalkerBase
  43. {
  44. public:
  45. // Get the child at i'th position.
  46. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) = 0;
  47. // Returns number of children for the current diag object.
  48. virtual ulong GetChildrenCount() = 0;
  49. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) = 0;
  50. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propId, bool& isConst) { return nullptr;}
  51. };
  52. enum DiagObjectModelDisplayType
  53. {
  54. DiagObjectModelDisplayType_LocalsDisplay,
  55. DiagObjectModelDisplayType_RecyclableObjectDisplay,
  56. DiagObjectModelDisplayType_RecyclableCollectionObjectDisplay,
  57. DiagObjectModelDisplayType_RecyclableKeyValueDisplay,
  58. };
  59. // Allow getting information across different data types
  60. class IDiagObjectModelDisplay
  61. {
  62. public:
  63. virtual LPCWSTR Name() = 0;
  64. virtual LPCWSTR Type() = 0;
  65. virtual LPCWSTR Value(int radix) = 0;
  66. virtual BOOL HasChildren() = 0;
  67. virtual BOOL Set(Var updateObject) = 0;
  68. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() = 0;
  69. virtual BOOL SetDefaultTypeAttribute(DBGPROP_ATTRIB_FLAGS attributes) { return FALSE; };
  70. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() = 0;
  71. virtual BOOL IsLocalsAsRoot() { return FALSE; }
  72. virtual Var GetVarValue(BOOL fUpdated) { return nullptr; }
  73. virtual IDiagObjectAddress * GetDiagAddress() { return nullptr; }
  74. virtual DiagObjectModelDisplayType GetType() = 0;
  75. virtual bool IsFake() { return (this->GetTypeAttribute() & DBGPROP_ATTRIB_VALUE_IS_FAKE) == DBGPROP_ATTRIB_VALUE_IS_FAKE; }
  76. virtual bool IsLiteralProperty() const = 0;
  77. virtual bool IsSymbolProperty() { return false; }
  78. };
  79. //
  80. // There are three distinct types of classes defined in order to inspect a variable on watch/locals window.
  81. // If someone has to change or provide the support for custom types/objects (such as PixelArray etc) be displayed on the debugger, they need to aware
  82. // of few things which are mentioned below.
  83. // <...>Display (eg RecyclableArrayDisplay), mentions how current variable is given to debugger, and tells what walker (enumerator) to be chosen
  84. // in order to walk to children of the current variable.
  85. // <...>Walker (eg RecyclableArrayWalker), mentions logic of walk thru content of the current variable (the object generally acts like an enumerator). Let say for an array, it has logic to go thru each
  86. // indices and populate values.
  87. // <...>Address (eg RecyclableArrayAddress), associated with each child and will be used to updating that item. The object if this will be consumed by "<...>Walker"
  88. // object when it walks thru each children of the current variable.
  89. // In order to support the custom objects, above classes should be used (or derived) to get started.
  90. //
  91. enum DebuggerPropertyDisplayInfoFlags
  92. {
  93. DebuggerPropertyDisplayInfoFlags_None = 0x0,
  94. DebuggerPropertyDisplayInfoFlags_Const = 0x1,
  95. DebuggerPropertyDisplayInfoFlags_InDeadZone = 0x2,
  96. DebuggerPropertyDisplayInfoFlags_Unscope = 0x4,
  97. };
  98. struct DebuggerPropertyDisplayInfo
  99. {
  100. PropertyId propId;
  101. Var aVar;
  102. DWORD flags; // DebuggerPropertyDisplayInfoFlags.
  103. DebuggerPropertyDisplayInfo(PropertyId _propId, Var _aVar, DWORD _flags) : propId(_propId), aVar(_aVar), flags(_flags)
  104. {}
  105. bool IsUnscoped() const { return (flags & DebuggerPropertyDisplayInfoFlags_Unscope) != 0; }
  106. bool IsConst() const { return (flags & DebuggerPropertyDisplayInfoFlags_Const) != 0; }
  107. bool IsInDeadZone() const { return (flags & DebuggerPropertyDisplayInfoFlags_InDeadZone) != 0; }
  108. };
  109. enum UIGroupType
  110. {
  111. UIGroupType_None,
  112. UIGroupType_InnerScope, // variables under the innerscope (such as Block/Catch)
  113. UIGroupType_Scope,
  114. UIGroupType_Globals
  115. };
  116. enum FramesLocalType
  117. {
  118. LocalType_None = 0x0,
  119. LocalType_Reg = 0x1,
  120. LocalType_InSlot = 0x2,
  121. LocalType_InObject = 0x4,
  122. };
  123. enum FrameWalkerFlags
  124. {
  125. FW_None = 0x0,
  126. FW_MakeGroups = 0x1, // Make groups such as [Scope], [Globals] etc.
  127. FW_EnumWithScopeAlso = 0x2, // While walking include the with scope as well.
  128. FW_AllowLexicalThis = 0x4, // Do not filter out Js::PropertyIds::_lexicalThisSlotSymbol
  129. FW_AllowSuperReference = 0x8, // Allow walking of Js::PropertyIds::_superReferenceSymbol and Js::PropertyIds::_superCtorReferenceSymbol
  130. };
  131. class VariableWalkerBase : public IDiagObjectModelWalkerBase
  132. {
  133. public:
  134. DiagStackFrame* pFrame;
  135. Var instance;
  136. JsUtil::List<DebuggerPropertyDisplayInfo*, ArenaAllocator> *pMembersList;
  137. UIGroupType groupType;
  138. private:
  139. bool allowLexicalThis;
  140. bool allowSuperReference;
  141. public :
  142. VariableWalkerBase(DiagStackFrame* _pFrame, Var _instance, UIGroupType _groupType, bool allowLexicalThis, bool allowSuperReference = false)
  143. : pFrame(_pFrame), instance(_instance), pMembersList(nullptr), groupType(_groupType), allowLexicalThis(allowLexicalThis), allowSuperReference(allowSuperReference)
  144. {
  145. }
  146. // Defined virtual function, should be extended by type of variable scope.
  147. virtual void PopulateMembers() { };
  148. virtual IDiagObjectAddress * GetObjectAddress(int index) { return nullptr; }
  149. virtual Var GetVarObjectAt(int index);
  150. virtual bool IsConstAt(int index);
  151. /// IDiagObjectModelWalkerBase
  152. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  153. virtual ulong GetChildrenCount() override;
  154. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override sealed;
  155. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propId, bool& isConst) override;
  156. static BOOL GetExceptionObject(int &index, DiagStackFrame* frame, ResolvedObject* pResolvedObject);
  157. static bool HasExceptionObject(DiagStackFrame* frame);
  158. static BOOL GetReturnedValue(int &index, DiagStackFrame* frame, ResolvedObject* pResolvedObject);
  159. static int GetReturnedValueCount(DiagStackFrame* frame);
  160. #ifdef ENABLE_MUTATION_BREAKPOINT
  161. static BOOL GetBreakMutationBreakpointValue(int &index, DiagStackFrame* frame, ResolvedObject* pResolvedObject);
  162. static uint GetBreakMutationBreakpointsCount(DiagStackFrame* frame);
  163. #endif
  164. bool IsInGroup() const { return (groupType != UIGroupType::UIGroupType_None && groupType != UIGroupType::UIGroupType_InnerScope); }
  165. bool IsWalkerForCurrentFrame() const { return groupType == UIGroupType::UIGroupType_None; }
  166. int GetAdjustedByteCodeOffset() const;
  167. DebuggerPropertyDisplayInfo* AllocateNewPropertyDisplayInfo(PropertyId propertyId, Var value, bool isConst, bool isInDeadZone);
  168. protected:
  169. int GetMemberCount() { return pMembersList ? pMembersList->Count() : 0; }
  170. bool IsPropertyValid(PropertyId propertyId, RegSlot location, bool *isPropertyInDebuggerScope, bool* isConst, bool* isInDeadZone) const;
  171. };
  172. class RegSlotVariablesWalker : public VariableWalkerBase
  173. {
  174. // This will be pointing to the inner debugger scope (block/catch)
  175. DebuggerScope* debuggerScope;
  176. public:
  177. RegSlotVariablesWalker(DiagStackFrame* _pFrame, DebuggerScope *_debuggerScope, UIGroupType _groupType, bool allowSuperReference = false)
  178. : VariableWalkerBase(_pFrame, nullptr, _groupType, /* allowLexicalThis */ false, allowSuperReference), debuggerScope(_debuggerScope)
  179. {
  180. }
  181. virtual void PopulateMembers() override;
  182. virtual IDiagObjectAddress * GetObjectAddress(int index) override;
  183. virtual Var GetVarObjectAt(int index) override;
  184. private:
  185. bool IsRegisterValid(PropertyId propertyId, RegSlot registerSlot) const;
  186. bool IsRegisterInScope(PropertyId propertyId, RegSlot registerSlot) const;
  187. Var GetVarObjectAndRegAt(int index, RegSlot* reg = nullptr);
  188. };
  189. class SlotArrayVariablesWalker : public VariableWalkerBase
  190. {
  191. public:
  192. SlotArrayVariablesWalker(DiagStackFrame* _pFrame, Var _instance, UIGroupType _groupType, bool allowLexicalThis, bool allowSuperReference = false) : VariableWalkerBase(_pFrame, _instance, _groupType, allowLexicalThis, allowSuperReference) {}
  193. virtual void PopulateMembers() override;
  194. virtual IDiagObjectAddress * GetObjectAddress(int index) override;
  195. ScopeSlots GetSlotArray() {
  196. Var *slotArray = (Var *) instance;
  197. Assert(slotArray != nullptr);
  198. return ScopeSlots(slotArray);
  199. }
  200. };
  201. class ObjectVariablesWalker : public VariableWalkerBase
  202. {
  203. public:
  204. ObjectVariablesWalker(DiagStackFrame* _pFrame, Var _instance, UIGroupType _groupType, bool allowLexicalThis, bool allowSuperReference = false) : VariableWalkerBase(_pFrame, _instance, _groupType, allowLexicalThis, allowSuperReference) {}
  205. virtual void PopulateMembers() override;
  206. virtual IDiagObjectAddress * GetObjectAddress(int index) override;
  207. protected:
  208. void AddObjectProperties(int count, Js::RecyclableObject* object);
  209. };
  210. class RootObjectVariablesWalker : public ObjectVariablesWalker
  211. {
  212. public:
  213. RootObjectVariablesWalker(DiagStackFrame* _pFrame, Var _instance, UIGroupType _groupType) : ObjectVariablesWalker(_pFrame, _instance, _groupType, /* allowLexicalThis */ false) {}
  214. virtual void PopulateMembers() override;
  215. };
  216. class DiagScopeVariablesWalker sealed : public VariableWalkerBase
  217. {
  218. public:
  219. // Represent catch/with scope objects, (ie. the representation for the diagnostics purposes.)
  220. JsUtil::List<IDiagObjectModelWalkerBase*, ArenaAllocator> *pDiagScopeObjects;
  221. ulong diagScopeVarCount;
  222. bool scopeIsInitialized;
  223. bool enumWithScopeAlso;
  224. public:
  225. DiagScopeVariablesWalker(DiagStackFrame* _pFrame, Var _instance, bool _enumWithScopeAlso)
  226. : VariableWalkerBase(_pFrame, _instance, UIGroupType_InnerScope, /* allowLexicalThis */ false), pDiagScopeObjects(nullptr), diagScopeVarCount(0), scopeIsInitialized(false), enumWithScopeAlso(_enumWithScopeAlso)
  227. {}
  228. DiagScopeVariablesWalker(DiagStackFrame* _pFrame, Var _instance, IDiagObjectModelWalkerBase* innerWalker);
  229. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  230. virtual ulong GetChildrenCount() override;
  231. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propId, bool& isConst) override;
  232. };
  233. // Display of variable on the locals window
  234. // Also responsible for walking on the current frame and build up chain of scopes.
  235. class LocalsWalker sealed : public IDiagObjectModelWalkerBase
  236. {
  237. friend class RecyclableArgumentsArrayWalker;
  238. DiagStackFrame* pFrame;
  239. JsUtil::List<VariableWalkerBase *, ArenaAllocator> * pVarWalkers; // This includes, current frame, all scopes and globals for a current frame
  240. uint totalLocalsCount;
  241. DWORD frameWalkerFlags;
  242. // true, if user has not defined the 'arguments' in the script, this is used for displaying a fake arguments object and display in the locals window.
  243. bool hasUserNotDefinedArguments;
  244. public:
  245. LocalsWalker(DiagStackFrame* _frame, DWORD _frameWalkerFlags);
  246. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  247. virtual ulong GetChildrenCount() override;
  248. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) {return FALSE; }
  249. static DWORD GetCurrentFramesLocalsType(DiagStackFrame* frame);
  250. IDiagObjectAddress * FindPropertyAddress(PropertyId propId, bool& isConst) override;
  251. // enumerateGroups will be true for the when fetching from a variable from the expression evaluation.
  252. IDiagObjectAddress * FindPropertyAddress(PropertyId propId, bool enumerateGroups, bool& isConst);
  253. template <typename FnProcessResolvedObject>
  254. DynamicObject* CreateAndPopulateActivationObject(ScriptContext* scriptContext, FnProcessResolvedObject processResolvedObjectFn)
  255. {
  256. Assert(scriptContext);
  257. Js::DynamicObject* activeScopeObject = nullptr;
  258. ulong count = this->GetChildrenCount();
  259. if (count > 0)
  260. {
  261. activeScopeObject = scriptContext->GetLibrary()->CreateActivationObject();
  262. for (ulong i = 0; i < count; i++)
  263. {
  264. Js::ResolvedObject resolveObject;
  265. if (this->Get(i, &resolveObject) && resolveObject.propId != Js::Constants::NoProperty)
  266. {
  267. if (!activeScopeObject->HasOwnProperty(resolveObject.propId))
  268. {
  269. OUTPUT_TRACE(Js::ConsoleScopePhase, L"Adding '%s' property to activeScopeObject\n", resolveObject.scriptContext->GetPropertyName(resolveObject.propId)->GetBuffer());
  270. if (resolveObject.IsInDeadZone())
  271. {
  272. PropertyOperationFlags flags = static_cast<PropertyOperationFlags>(PropertyOperation_SpecialValue | PropertyOperation_AllowUndecl);
  273. PropertyAttributes attributes = resolveObject.isConst ? PropertyConstDefaults : PropertyLetDefaults;
  274. resolveObject.obj = scriptContext->GetLibrary()->GetUndeclBlockVar();
  275. activeScopeObject->SetPropertyWithAttributes(
  276. resolveObject.propId,
  277. resolveObject.obj,
  278. attributes, nullptr, flags);
  279. }
  280. else
  281. {
  282. activeScopeObject->SetPropertyWithAttributes(
  283. resolveObject.propId,
  284. JavascriptOperators::BoxStackInstance(resolveObject.obj, scriptContext), //The value escapes, box if necessary.
  285. resolveObject.isConst ? PropertyConstDefaults : PropertyDynamicTypeDefaults,
  286. nullptr);
  287. }
  288. processResolvedObjectFn(resolveObject);
  289. }
  290. }
  291. }
  292. }
  293. return activeScopeObject;
  294. }
  295. private:
  296. BOOL CreateArgumentsObject(ResolvedObject* pResolvedObject);
  297. bool ShouldMakeGroups() const { return frameWalkerFlags & FW_MakeGroups; }
  298. bool ShouldInsertFakeArguments();
  299. void ExpandArgumentsObject(IDiagObjectModelDisplay * argumentsDisplay);
  300. };
  301. class LocalsDisplay : public IDiagObjectModelDisplay
  302. {
  303. DiagStackFrame* pFrame;
  304. public:
  305. LocalsDisplay(DiagStackFrame* _frame);
  306. virtual LPCWSTR Name() override;
  307. virtual LPCWSTR Type() override;
  308. virtual LPCWSTR Value(int radix) override;
  309. virtual BOOL HasChildren() override;
  310. virtual BOOL Set(Var updateObject) override;
  311. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override;
  312. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  313. virtual BOOL IsLocalsAsRoot() { return TRUE; }
  314. virtual DiagObjectModelDisplayType GetType() { return DiagObjectModelDisplayType_LocalsDisplay; }
  315. virtual bool IsLiteralProperty() const { return false; }
  316. };
  317. //
  318. // The locals var's addresses.
  319. // A representation of an address when this Var is taken from the slot array.
  320. class LocalObjectAddressForSlot : public IDiagObjectAddress
  321. {
  322. ScopeSlots slotArray;
  323. int slotIndex;
  324. Var value;
  325. public:
  326. LocalObjectAddressForSlot(ScopeSlots _pSlotArray, int _slotIndex, Js::Var _value);
  327. virtual BOOL Set(Var updateObject) override;
  328. virtual Var GetValue(BOOL fUpdated);
  329. virtual BOOL IsInDeadZone() const;
  330. };
  331. // A representation of an address when this Var is taken from the direct regslot.
  332. class LocalObjectAddressForRegSlot : public IDiagObjectAddress
  333. {
  334. DiagStackFrame* pFrame;
  335. RegSlot regSlot;
  336. Var value;
  337. public:
  338. LocalObjectAddressForRegSlot(DiagStackFrame* _pFrame, RegSlot _regSlot, Js::Var _value);
  339. virtual BOOL Set(Var updateObject) override;
  340. virtual Var GetValue(BOOL fUpdated);
  341. BOOL IsInDeadZone() const;
  342. };
  343. class CatchScopeWalker sealed : public IDiagObjectModelWalkerBase
  344. {
  345. DiagStackFrame* pFrame;
  346. DebuggerScope * debuggerScope;
  347. public :
  348. CatchScopeWalker(DiagStackFrame* _pFrame, DebuggerScope* _debuggerScope)
  349. : pFrame(_pFrame), debuggerScope(_debuggerScope)
  350. {
  351. }
  352. /// IDiagObjectModelWalkerBase
  353. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  354. virtual ulong GetChildrenCount() override;
  355. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override { return FALSE; }
  356. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propId, bool& isConst) override;
  357. private:
  358. void FetchValueAndAddress(DebuggerScopeProperty &scopeProperty, _Out_opt_ Var *pValue, _Out_opt_ IDiagObjectAddress ** ppAddress);
  359. };
  360. // Concrete Classes for Objects
  361. class RecyclableObjectWalker : public IDiagObjectModelWalkerBase
  362. {
  363. protected:
  364. ScriptContext* scriptContext;
  365. Var instance;
  366. Var originalInstance; // Remember original instance for prototype walk, because evaluating getters in CallGetter() if __proto__ instance is passed does not work
  367. JsUtil::List<DebuggerPropertyDisplayInfo *, ArenaAllocator> * pMembersList;
  368. RecyclableArrayWalker * innerArrayObjectWalker; // Will be used for array indices on the object
  369. JsUtil::List<IDiagObjectModelWalkerBase *, ArenaAllocator> * fakeGroupObjectWalkerList; // such as [prototype], [Methods] etc.
  370. void InsertItem(Js::RecyclableObject *pOriginalObject, Js::RecyclableObject *pObject, PropertyId propertyId, bool isConst, bool isUnscoped, Js::RecyclableMethodsGroupWalker **ppMethodsGrouptWalker, bool shouldPinProperty = false);
  371. void InsertItem(PropertyId propertyId, bool isConst, bool isUnscoped, Var itemObj, Js::RecyclableMethodsGroupWalker **ppMethodsGrouptWalker, bool shouldPinProperty = false);
  372. void EnsureFakeGroupObjectWalkerList();
  373. public:
  374. RecyclableObjectWalker(ScriptContext* pContext, Var slot);
  375. RecyclableObjectWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  376. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  377. virtual ulong GetChildrenCount() override;
  378. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) { return FALSE; };
  379. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propertyId, bool& isConst) override;
  380. static Var GetObject(RecyclableObject* originalInstance, RecyclableObject* instance, PropertyId propertyId, ScriptContext* scriptContext);
  381. };
  382. class RecyclableObjectAddress : public IDiagObjectAddress
  383. {
  384. Var parentObj;
  385. Js::PropertyId propId;
  386. Js::Var value;
  387. BOOL isInDeadZone;
  388. public:
  389. RecyclableObjectAddress(Var parentObj, Js::PropertyId _propId, Js::Var _value, BOOL _isInDeadZone);
  390. virtual BOOL Set(Var updateObject) override;
  391. virtual BOOL IsWritable() override;
  392. virtual Var GetValue(BOOL fUpdated);
  393. BOOL IsInDeadZone() const;
  394. };
  395. class RecyclableObjectDisplay : public IDiagObjectModelDisplay
  396. {
  397. protected:
  398. ScriptContext* scriptContext;
  399. Var instance;
  400. Var originalInstance;
  401. LPCWSTR name;
  402. IDiagObjectAddress* pObjAddress;
  403. DBGPROP_ATTRIB_FLAGS defaultAttributes;
  404. PropertyId propertyId;
  405. public:
  406. RecyclableObjectDisplay(ResolvedObject* resolvedObject, DBGPROP_ATTRIB_FLAGS defaultAttributes = DBGPROP_ATTRIB_NO_ATTRIB);
  407. virtual LPCWSTR Name() override;
  408. virtual LPCWSTR Type() override;
  409. virtual LPCWSTR Value(int radix) override;
  410. virtual BOOL HasChildren() override;
  411. virtual BOOL Set(Var updateObject) override;
  412. virtual BOOL SetDefaultTypeAttribute(DBGPROP_ATTRIB_FLAGS attributes) override { defaultAttributes = attributes; return TRUE; };
  413. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override;
  414. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  415. virtual Var GetVarValue(BOOL fUpdated) override;
  416. virtual IDiagObjectAddress * GetDiagAddress() override { return pObjAddress; }
  417. virtual DiagObjectModelDisplayType GetType() { return DiagObjectModelDisplayType_RecyclableObjectDisplay; }
  418. virtual bool IsLiteralProperty() const;
  419. virtual bool IsSymbolProperty() override;
  420. static BOOL GetPropertyWithScriptEnter(RecyclableObject* originalInstance, RecyclableObject* instance, PropertyId propertyId, Var* value, ScriptContext* scriptContext);
  421. StringBuilder<ArenaAllocator>* GetStringBuilder();
  422. PropertyId GetPropertyId() const;
  423. };
  424. // Concrete classes for Arrays
  425. class RecyclableArrayAddress : public IDiagObjectAddress
  426. {
  427. protected:
  428. Var parentArray;
  429. unsigned int index;
  430. public:
  431. RecyclableArrayAddress(Var parentArray, unsigned int index);
  432. virtual BOOL Set(Var updateObject) override;
  433. };
  434. class RecyclableArrayDisplay : public RecyclableObjectDisplay
  435. {
  436. protected:
  437. BOOL HasChildrenInternal(Js::JavascriptArray* arrayObj);
  438. public:
  439. RecyclableArrayDisplay(ResolvedObject* resolvedObject);
  440. virtual BOOL HasChildren() override;
  441. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  442. };
  443. class RecyclableArrayWalker : public RecyclableObjectWalker
  444. {
  445. protected:
  446. uint32 indexedItemCount;
  447. JsUtil::List<uint32, ArenaAllocator> * pAbsoluteIndexList;
  448. // Just populate the indexes only.
  449. bool fOnlyOwnProperties;
  450. uint32 RecyclableArrayWalker::GetItemCount(Js::JavascriptArray* arrayObj);
  451. // ES5Array will extend this.
  452. virtual uint32 GetNextDescriptor(uint32 currentDescriptor) { return Js::JavascriptArray::InvalidIndex; }
  453. LPCWSTR RecyclableArrayWalker::GetIndexName(uint32 index, StringBuilder<ArenaAllocator>* stringBuilder);
  454. Js::JavascriptArray* GetArrayObject();
  455. public:
  456. RecyclableArrayWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  457. void SetOnlyWalkOwnProperties(bool set) { fOnlyOwnProperties = set; }
  458. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  459. virtual ulong GetChildrenCount() override;
  460. virtual BOOL FetchItemAtIndex(Js::JavascriptArray* arrayObj, uint32 index, Var *value);
  461. virtual Var FetchItemAt(Js::JavascriptArray* arrayObj, uint32 index);
  462. virtual BOOL GetResolvedObject(Js::JavascriptArray* arrayObj, int index, ResolvedObject* pResolvedObject, uint32 * pabsIndex) sealed;
  463. StringBuilder<ArenaAllocator>* GetBuilder();
  464. };
  465. // Concrete classes for Arguments object
  466. //
  467. class RecyclableArgumentsObjectDisplay : public RecyclableObjectDisplay
  468. {
  469. LocalsWalker *pLocalsWalker;
  470. public:
  471. RecyclableArgumentsObjectDisplay(ResolvedObject* resolvedObject, LocalsWalker *localsWalker);
  472. virtual BOOL HasChildren() override;
  473. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  474. };
  475. class RecyclableArgumentsObjectWalker : public RecyclableObjectWalker
  476. {
  477. LocalsWalker *pLocalsWalker;
  478. public:
  479. RecyclableArgumentsObjectWalker(ScriptContext* pContext, Var instance, LocalsWalker * localsWalker);
  480. virtual ulong GetChildrenCount() override;
  481. };
  482. class RecyclableArgumentsArrayAddress : public IDiagObjectAddress
  483. {
  484. Var parentArray;
  485. unsigned int index;
  486. public:
  487. RecyclableArgumentsArrayAddress(Var parentArray, unsigned int index);
  488. virtual BOOL Set(Var updateObject) override;
  489. };
  490. class RecyclableArgumentsArrayWalker : public RecyclableArrayWalker
  491. {
  492. JsUtil::List<IDiagObjectAddress *, ArenaAllocator> * pFormalsList;
  493. public:
  494. RecyclableArgumentsArrayWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  495. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  496. virtual ulong GetChildrenCount() override;
  497. void FetchFormalsAddress (LocalsWalker * localsWalker);
  498. };
  499. // Concrete classes for Typed array objects
  500. //
  501. class RecyclableTypedArrayAddress : public RecyclableArrayAddress
  502. {
  503. public:
  504. RecyclableTypedArrayAddress(Var parentArray, unsigned int index);
  505. virtual BOOL Set(Var updateObject) override;
  506. };
  507. class RecyclableTypedArrayDisplay : public RecyclableObjectDisplay
  508. {
  509. public:
  510. RecyclableTypedArrayDisplay(ResolvedObject* resolvedObject);
  511. virtual BOOL HasChildren() override;
  512. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  513. };
  514. class RecyclableTypedArrayWalker : public RecyclableArrayWalker
  515. {
  516. public:
  517. RecyclableTypedArrayWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  518. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  519. virtual ulong GetChildrenCount() override;
  520. };
  521. // Concrete classes for Pixel array objects
  522. //
  523. class RecyclablePixelArrayAddress : public RecyclableArrayAddress
  524. {
  525. public:
  526. RecyclablePixelArrayAddress(Var parentArray, unsigned int index);
  527. virtual BOOL Set(Var updateObject) override;
  528. };
  529. class RecyclablePixelArrayDisplay : public RecyclableObjectDisplay
  530. {
  531. public:
  532. RecyclablePixelArrayDisplay(ResolvedObject* resolvedObject);
  533. virtual BOOL HasChildren() override;
  534. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  535. };
  536. class RecyclablePixelArrayWalker : public RecyclableArrayWalker
  537. {
  538. public:
  539. RecyclablePixelArrayWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  540. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  541. virtual ulong GetChildrenCount() override;
  542. };
  543. // Concrete classes for ES5 array objects
  544. //
  545. class RecyclableES5ArrayAddress : public RecyclableArrayAddress
  546. {
  547. public:
  548. RecyclableES5ArrayAddress(Var parentArray, unsigned int index);
  549. virtual BOOL Set(Var updateObject) override;
  550. };
  551. class RecyclableES5ArrayDisplay : public RecyclableArrayDisplay
  552. {
  553. public:
  554. RecyclableES5ArrayDisplay(ResolvedObject* resolvedObject);
  555. virtual BOOL HasChildren() override;
  556. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  557. };
  558. class RecyclableES5ArrayWalker sealed : public RecyclableArrayWalker
  559. {
  560. public:
  561. RecyclableES5ArrayWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  562. virtual uint32 GetNextDescriptor(uint32 currentDescriptor) override;
  563. virtual BOOL FetchItemAtIndex(Js::JavascriptArray* arrayObj, uint32 index, Var *value) override;
  564. virtual Var FetchItemAt(Js::JavascriptArray* arrayObj, uint32 index) override;
  565. };
  566. // Concrete classes for Proto group object
  567. //
  568. class RecyclableProtoObjectWalker : public RecyclableObjectWalker
  569. {
  570. public:
  571. RecyclableProtoObjectWalker(ScriptContext* pContext, Var slot, Var originalInstance);
  572. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override;
  573. virtual IDiagObjectAddress *FindPropertyAddress(PropertyId propId, bool& isConst) override;
  574. };
  575. class RecyclableProtoObjectAddress : public RecyclableObjectAddress
  576. {
  577. public:
  578. RecyclableProtoObjectAddress(Var _parentObj, Js::PropertyId _propId, Js::Var _value);
  579. };
  580. // Concrete classes for Map, Set, and WeakMap group objects
  581. //
  582. template <typename TData>
  583. struct RecyclableCollectionObjectWalkerPropertyData
  584. {
  585. RecyclableCollectionObjectWalkerPropertyData():key(nullptr), value(nullptr) { }
  586. RecyclableCollectionObjectWalkerPropertyData(Var key, Var value):key(key), value(value) { }
  587. Var key;
  588. Var value;
  589. };
  590. template<>
  591. struct RecyclableCollectionObjectWalkerPropertyData<JavascriptSet>
  592. {
  593. RecyclableCollectionObjectWalkerPropertyData():value(nullptr) { }
  594. RecyclableCollectionObjectWalkerPropertyData(Var value):value(value) { }
  595. Var value;
  596. };
  597. template<>
  598. struct RecyclableCollectionObjectWalkerPropertyData<JavascriptWeakSet>
  599. {
  600. RecyclableCollectionObjectWalkerPropertyData():value(nullptr) { }
  601. RecyclableCollectionObjectWalkerPropertyData(Var value):value(value) { }
  602. Var value;
  603. };
  604. template <typename TData>
  605. class RecyclableCollectionObjectWalker : public IDiagObjectModelWalkerBase
  606. {
  607. ScriptContext* scriptContext;
  608. Var instance;
  609. JsUtil::List<RecyclableCollectionObjectWalkerPropertyData<TData>, ArenaAllocator>* propertyList;
  610. const wchar_t* Name();
  611. IDiagObjectModelDisplay* CreateTDataDisplay(ResolvedObject* resolvedObject, int i);
  612. void GetChildren();
  613. public:
  614. RecyclableCollectionObjectWalker(ScriptContext* scriptContext, Var instance):scriptContext(scriptContext), instance(instance), propertyList(nullptr) { }
  615. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override;
  616. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  617. virtual ulong GetChildrenCount() override;
  618. };
  619. typedef RecyclableCollectionObjectWalker<JavascriptMap> RecyclableMapObjectWalker;
  620. typedef RecyclableCollectionObjectWalker<JavascriptSet> RecyclableSetObjectWalker;
  621. typedef RecyclableCollectionObjectWalker<JavascriptWeakMap> RecyclableWeakMapObjectWalker;
  622. typedef RecyclableCollectionObjectWalker<JavascriptWeakSet> RecyclableWeakSetObjectWalker;
  623. template <typename TData>
  624. class RecyclableCollectionObjectDisplay : public IDiagObjectModelDisplay
  625. {
  626. ScriptContext* scriptContext;
  627. const wchar_t* name;
  628. RecyclableCollectionObjectWalker<TData>* walker;
  629. public:
  630. RecyclableCollectionObjectDisplay(ScriptContext* scriptContext, const wchar_t* name, RecyclableCollectionObjectWalker<TData>* walker) : scriptContext(scriptContext), name(name), walker(walker) { }
  631. virtual LPCWSTR Name() override { return name; }
  632. virtual LPCWSTR Type() override { return L""; }
  633. virtual LPCWSTR Value(int radix) override;
  634. virtual BOOL HasChildren() override { return walker->GetChildrenCount() > 0; }
  635. virtual BOOL Set(Var updateObject) override { return FALSE; }
  636. virtual BOOL SetDefaultTypeAttribute(DBGPROP_ATTRIB_FLAGS attributes) override { return FALSE; }
  637. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override { return DBGPROP_ATTRIB_VALUE_READONLY | DBGPROP_ATTRIB_VALUE_IS_FAKE | (HasChildren() ? DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE : 0); }
  638. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  639. virtual Var GetVarValue(BOOL fUpdated) override { return nullptr; }
  640. virtual IDiagObjectAddress * GetDiagAddress() override { return nullptr; }
  641. virtual DiagObjectModelDisplayType GetType() { return DiagObjectModelDisplayType_RecyclableCollectionObjectDisplay; }
  642. virtual bool IsLiteralProperty() const { return false; }
  643. };
  644. class RecyclableKeyValueDisplay : public IDiagObjectModelDisplay
  645. {
  646. ScriptContext* scriptContext;
  647. Var key;
  648. Var value;
  649. const wchar_t* name;
  650. public:
  651. RecyclableKeyValueDisplay(ScriptContext* scriptContext, Var key, Var value, const wchar_t* name) : scriptContext(scriptContext), key(key), value(value), name(name) { }
  652. virtual LPCWSTR Name() override { return name; }
  653. virtual LPCWSTR Type() override { return L""; }
  654. virtual LPCWSTR Value(int radix) override;
  655. virtual BOOL HasChildren() override { return TRUE; }
  656. virtual BOOL Set(Var updateObject) override { return FALSE; }
  657. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override { return DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE | DBGPROP_ATTRIB_VALUE_IS_FAKE | DBGPROP_ATTRIB_VALUE_READONLY; }
  658. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  659. virtual DiagObjectModelDisplayType GetType() { return DiagObjectModelDisplayType_RecyclableKeyValueDisplay; }
  660. virtual bool IsLiteralProperty() const { return false; }
  661. };
  662. class RecyclableKeyValueWalker : public IDiagObjectModelWalkerBase
  663. {
  664. ScriptContext* scriptContext;
  665. Var key;
  666. Var value;
  667. public:
  668. RecyclableKeyValueWalker(ScriptContext* scriptContext, Var key, Var value):scriptContext(scriptContext), key(key), value(value) { }
  669. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  670. virtual ulong GetChildrenCount() override { return 2; }
  671. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override { return FALSE; }
  672. };
  673. class RecyclableProxyObjectDisplay : public RecyclableObjectDisplay
  674. {
  675. public:
  676. RecyclableProxyObjectDisplay(ResolvedObject* resolvedObject);
  677. virtual BOOL HasChildren() override { return TRUE; }
  678. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  679. };
  680. class RecyclableProxyObjectWalker : public RecyclableObjectWalker
  681. {
  682. public:
  683. RecyclableProxyObjectWalker(ScriptContext* pContext, Var instance);
  684. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  685. virtual ulong GetChildrenCount() override { return 2; }
  686. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override;
  687. };
  688. // Concrete classes for Methods group object
  689. //
  690. class RecyclableMethodsGroupWalker : public RecyclableObjectWalker
  691. {
  692. public:
  693. RecyclableMethodsGroupWalker(ScriptContext* pContext, Var slot);
  694. void AddItem(Js::PropertyId propertyId, Var obj);
  695. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  696. virtual ulong GetChildrenCount() override;
  697. virtual BOOL GetGroupObject(ResolvedObject* pResolvedObject) override;
  698. void Sort();
  699. };
  700. class RecyclableMethodsGroupDisplay : public RecyclableObjectDisplay
  701. {
  702. public:
  703. RecyclableMethodsGroupWalker *methodGroupWalker;
  704. RecyclableMethodsGroupDisplay(RecyclableMethodsGroupWalker *_methodGroupWalker, ResolvedObject* resolvedObject);
  705. virtual LPCWSTR Type() override;
  706. virtual LPCWSTR Value(int radix) override;
  707. virtual BOOL HasChildren() override;
  708. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override;
  709. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  710. };
  711. // Concrete classes for Scope group object
  712. //
  713. class ScopeVariablesGroupDisplay : public RecyclableObjectDisplay
  714. {
  715. public:
  716. VariableWalkerBase *scopeGroupWalker;
  717. ScopeVariablesGroupDisplay(VariableWalkerBase *walker, ResolvedObject* resolvedObject);
  718. virtual LPCWSTR Type() override;
  719. virtual LPCWSTR Value(int radix) override;
  720. virtual BOOL HasChildren() override;
  721. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override;
  722. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  723. };
  724. // Concrete classes for Globals group object
  725. //
  726. class GlobalsScopeVariablesGroupDisplay sealed : public RecyclableObjectDisplay
  727. {
  728. public:
  729. VariableWalkerBase *globalsGroupWalker;
  730. GlobalsScopeVariablesGroupDisplay(VariableWalkerBase *walker, ResolvedObject* resolvedObject);
  731. virtual LPCWSTR Type() override;
  732. virtual LPCWSTR Value(int radix) override;
  733. virtual BOOL HasChildren() override;
  734. virtual DBGPROP_ATTRIB_FLAGS GetTypeAttribute() override;
  735. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  736. };
  737. #ifdef ENABLE_MUTATION_BREAKPOINT
  738. // For Pending Mutation breakpoint
  739. class PendingMutationBreakpointDisplay : public RecyclableObjectDisplay
  740. {
  741. MutationType mutationType;
  742. public:
  743. PendingMutationBreakpointDisplay(ResolvedObject* resolvedObject, MutationType mutationType);
  744. virtual LPCWSTR Value(int radix) override { return L""; }
  745. virtual BOOL HasChildren() override { return TRUE; }
  746. virtual WeakArenaReference<IDiagObjectModelWalkerBase>* CreateWalker() override;
  747. };
  748. class PendingMutationBreakpointWalker : public RecyclableObjectWalker
  749. {
  750. MutationType mutationType;
  751. public:
  752. PendingMutationBreakpointWalker(ScriptContext* pContext, Var instance, MutationType mutationType);
  753. virtual BOOL Get(int i, ResolvedObject* pResolvedObject) override;
  754. virtual ulong GetChildrenCount() override;
  755. };
  756. #endif
  757. }