//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once class JsrtDebugManager; class JsrtDebuggerObjectsManager; // Type of objects we give to debugger enum class JsrtDebuggerObjectType { Function, Globals, Property, Scope }; // Base class representing a debugger object class JsrtDebuggerObjectBase { public: JsrtDebuggerObjectBase(JsrtDebuggerObjectType type, JsrtDebuggerObjectsManager* debuggerObjectsManager); virtual ~JsrtDebuggerObjectBase(); JsrtDebuggerObjectType GetType() { return type; } uint GetHandle() const { return handle; } JsrtDebuggerObjectsManager* GetDebuggerObjectsManager(); virtual Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp) = 0; virtual Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount); template static void CreateDebuggerObject(JsrtDebuggerObjectsManager* debuggerObjectsManager, Js::ResolvedObject resolvedObject, Js::ScriptContext* scriptContext, bool forceSetValueProp, PostFunction postFunction) { AutoPtr> objectDisplayWeakRef(resolvedObject.GetObjectDisplay()); Js::IDiagObjectModelDisplay* objectDisplay = objectDisplayWeakRef->GetStrongReference(); if (objectDisplay != nullptr) { JsrtDebuggerObjectBase* debuggerObject = JsrtDebuggerObjectType::Make(debuggerObjectsManager, objectDisplayWeakRef); Js::DynamicObject* object = debuggerObject->GetJSONObject(resolvedObject.scriptContext, forceSetValueProp); Assert(object != nullptr); Js::Var marshaledObj = Js::CrossSite::MarshalVar(scriptContext, object); postFunction(marshaledObj); objectDisplayWeakRef.Detach(); } } protected: Js::DynamicObject* GetChildren(WeakArenaReference* walkerRef, Js::ScriptContext * scriptContext, uint fromCount, uint totalCount); private: JsrtDebuggerObjectType type; uint handle; JsrtDebuggerObjectsManager* debuggerObjectsManager; }; class JsrtDebuggerObjectFunction : public JsrtDebuggerObjectBase { public: static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, Js::FunctionBody* functionBody); Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp); private: JsrtDebuggerObjectFunction(JsrtDebuggerObjectsManager* debuggerObjectsManager, Js::FunctionBody* functionBody); ~JsrtDebuggerObjectFunction(); Js::FunctionBody* functionBody; }; class JsrtDebuggerObjectProperty : public JsrtDebuggerObjectBase { public: static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay); Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp); Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount); private: JsrtDebuggerObjectProperty(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay); ~JsrtDebuggerObjectProperty(); WeakArenaReference* objectDisplay; WeakArenaReference* walkerRef; }; class JsrtDebuggerObjectGlobalsNode : public JsrtDebuggerObjectBase { public: static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay); Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp); Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount); private: JsrtDebuggerObjectGlobalsNode(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay); ~JsrtDebuggerObjectGlobalsNode(); WeakArenaReference* objectDisplay; WeakArenaReference* walkerRef; }; class JsrtDebuggerObjectScope : public JsrtDebuggerObjectBase { public: static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay, uint index); Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp); Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount); private: JsrtDebuggerObjectScope(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference* objectDisplay, uint index); ~JsrtDebuggerObjectScope(); WeakArenaReference* objectDisplay; WeakArenaReference* walkerRef; uint index; }; class JsrtDebuggerStackFrame { public: JsrtDebuggerStackFrame(JsrtDebuggerObjectsManager * debuggerObjectsManager, Js::DiagStackFrame* stackFrame, uint frameIndex); ~JsrtDebuggerStackFrame(); Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext); Js::DynamicObject* GetLocalsObject(Js::ScriptContext* scriptContext); bool Evaluate(Js::ScriptContext* scriptContext, const char16 *source, int sourceLength, bool isLibraryCode, bool forceSetValueProp, Js::DynamicObject** evalResult); uint GetIndex() const { return this->frameIndex; } private: uint frameIndex; Js::DiagStackFrame* stackFrame; JsrtDebuggerObjectsManager * debuggerObjectsManager; }; class JsrtDebugStackFrames { public: JsrtDebugStackFrames(JsrtDebugManager* jsrtDebugManager); ~JsrtDebugStackFrames(); Js::JavascriptArray* StackFrames(Js::ScriptContext* scriptContext); bool TryGetFrameObjectFromFrameIndex(uint frameIndex, JsrtDebuggerStackFrame ** debuggerStackFrame); private: Js::DynamicObject* GetStackFrame(Js::DiagStackFrame * stackFrame, uint frameIndex); JsrtDebugManager* jsrtDebugManager; typedef JsUtil::BaseDictionary FramesDictionary; FramesDictionary* framesDictionary; void ClearFrameDictionary(); }; // Class managing objects we give to debugger, it maintains various mappings class JsrtDebuggerObjectsManager { public: JsrtDebuggerObjectsManager(JsrtDebugManager* jsrtDebugManager); ~JsrtDebuggerObjectsManager(); void ClearAll(); JsrtDebugManager* GetJsrtDebugManager() { return this->jsrtDebugManager; }; ArenaAllocator* GetDebugObjectArena(); uint GetNextHandle() { return ++handleId; } void AddToDebuggerObjectsDictionary(JsrtDebuggerObjectBase* debuggerObject); bool TryGetDebuggerObjectFromHandle(uint handle, JsrtDebuggerObjectBase** debuggerObject); void AddToDataToDebuggerObjectsDictionary(void* data, JsrtDebuggerObjectBase* debuggerObject); bool TryGetDataFromDataToDebuggerObjectsDictionary(void* data, JsrtDebuggerObjectBase** debuggerObject); private: uint handleId; JsrtDebugManager* jsrtDebugManager; typedef JsUtil::BaseDictionary DebuggerObjectsDictionary; DebuggerObjectsDictionary* handleToDebuggerObjectsDictionary; typedef JsUtil::BaseDictionary DataToDebuggerObjectsDictionary; DataToDebuggerObjectsDictionary* dataToDebuggerObjectsDictionary; };