blob: afde7c2d62ccf9ace834b16806ec5d6c94ffa70b [file]
//-------------------------------------------------------------------------------------------------------
// 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<class JsrtDebuggerObjectType, class PostFunction>
static void CreateDebuggerObject(JsrtDebuggerObjectsManager* debuggerObjectsManager, Js::ResolvedObject resolvedObject, Js::ScriptContext* scriptContext, bool forceSetValueProp, PostFunction postFunction)
{
AutoPtr<WeakArenaReference<Js::IDiagObjectModelDisplay>> 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<Js::IDiagObjectModelWalkerBase>* 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<Js::IDiagObjectModelDisplay>* objectDisplay);
Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp);
Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount);
private:
JsrtDebuggerObjectProperty(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay);
~JsrtDebuggerObjectProperty();
WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay;
WeakArenaReference<Js::IDiagObjectModelWalkerBase>* walkerRef;
};
class JsrtDebuggerObjectGlobalsNode : public JsrtDebuggerObjectBase
{
public:
static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay);
Js::DynamicObject* GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp);
Js::DynamicObject* GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount);
private:
JsrtDebuggerObjectGlobalsNode(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay);
~JsrtDebuggerObjectGlobalsNode();
WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay;
WeakArenaReference<Js::IDiagObjectModelWalkerBase>* walkerRef;
};
class JsrtDebuggerObjectScope : public JsrtDebuggerObjectBase
{
public:
static JsrtDebuggerObjectBase* Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* 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<Js::IDiagObjectModelDisplay>* objectDisplay, uint index);
~JsrtDebuggerObjectScope();
WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay;
WeakArenaReference<Js::IDiagObjectModelWalkerBase>* 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<uint, JsrtDebuggerStackFrame*, ArenaAllocator> 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<uint, JsrtDebuggerObjectBase*, ArenaAllocator> DebuggerObjectsDictionary;
DebuggerObjectsDictionary* handleToDebuggerObjectsDictionary;
typedef JsUtil::BaseDictionary<void*, JsrtDebuggerObjectBase*, ArenaAllocator> DataToDebuggerObjectsDictionary;
DataToDebuggerObjectsDictionary* dataToDebuggerObjectsDictionary;
};