| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "JsrtPch.h"
- #ifdef ENABLE_SCRIPT_DEBUGGING
- #include "JsrtDebuggerObject.h"
- #include "JsrtDebugUtils.h"
- #include "JsrtDebugManager.h"
- JsrtDebuggerObjectBase::JsrtDebuggerObjectBase(JsrtDebuggerObjectType type, JsrtDebuggerObjectsManager* debuggerObjectsManager) :
- type(type),
- debuggerObjectsManager(debuggerObjectsManager)
- {
- Assert(debuggerObjectsManager != nullptr);
- this->handle = debuggerObjectsManager->GetNextHandle();
- }
- JsrtDebuggerObjectBase::~JsrtDebuggerObjectBase()
- {
- this->debuggerObjectsManager = nullptr;
- }
- JsrtDebuggerObjectsManager * JsrtDebuggerObjectBase::GetDebuggerObjectsManager()
- {
- return this->debuggerObjectsManager;
- }
- Js::DynamicObject * JsrtDebuggerObjectBase::GetChildren(Js::ScriptContext * scriptContext, uint fromCount, uint totalCount)
- {
- AssertMsg(false, "Wrong type for GetChildren");
- return nullptr;
- }
- Js::DynamicObject * JsrtDebuggerObjectBase::GetChildren(WeakArenaReference<Js::IDiagObjectModelWalkerBase>* walkerRef, Js::ScriptContext * scriptContext, uint fromCount, uint totalCount)
- {
- Js::DynamicObject* childrensObject = scriptContext->GetLibrary()->CreateObject();
- uint propertiesArrayCount = 0;
- Js::JavascriptArray* propertiesArray = scriptContext->GetLibrary()->CreateArray();
- uint debuggerOnlyPropertiesArrayCount = 0;
- Js::JavascriptArray* debuggerOnlyPropertiesArray = scriptContext->GetLibrary()->CreateArray();
- Js::IDiagObjectModelWalkerBase* walker = walkerRef->GetStrongReference();
- uint32 childrensCount = 0;
- if (walker != nullptr)
- {
- try
- {
- childrensCount = walker->GetChildrenCount();
- }
- catch (const Js::JavascriptException& err)
- {
- err.GetAndClear(); // discard exception object
- }
- if (fromCount < childrensCount)
- {
- for (uint32 i = fromCount; i < childrensCount && (propertiesArrayCount + debuggerOnlyPropertiesArrayCount) < totalCount; ++i)
- {
- Js::ResolvedObject resolvedObject;
- try
- {
- walker->Get(i, &resolvedObject);
- }
- catch (const Js::JavascriptException& err)
- {
- Js::JavascriptExceptionObject* exception = err.GetAndClear();
- Js::Var error = exception->GetThrownObject(scriptContext);
- resolvedObject.obj = error;
- resolvedObject.address = nullptr;
- resolvedObject.scriptContext = exception->GetScriptContext();
- resolvedObject.typeId = Js::JavascriptOperators::GetTypeId(error);
- resolvedObject.name = _u("{error}");
- resolvedObject.propId = Js::Constants::NoProperty;
- }
- AutoPtr<WeakArenaReference<Js::IDiagObjectModelDisplay>> objectDisplayWeakRef(resolvedObject.GetObjectDisplay());
- Js::IDiagObjectModelDisplay* resolvedObjectDisplay = objectDisplayWeakRef->GetStrongReference();
- if (resolvedObjectDisplay != nullptr)
- {
- JsrtDebuggerObjectBase* debuggerObject = JsrtDebuggerObjectProperty::Make(this->GetDebuggerObjectsManager(), objectDisplayWeakRef);
- Js::DynamicObject* object = debuggerObject->GetJSONObject(resolvedObject.scriptContext, /* forceSetValueProp */ false);
- Js::Var marshaledObj = Js::CrossSite::MarshalVar(scriptContext, object);
- if (resolvedObjectDisplay->IsFake())
- {
- Js::JavascriptOperators::OP_SetElementI((Js::Var)debuggerOnlyPropertiesArray, Js::JavascriptNumber::ToVar(debuggerOnlyPropertiesArrayCount++, scriptContext), marshaledObj, scriptContext);
- }
- else
- {
- Js::JavascriptOperators::OP_SetElementI((Js::Var)propertiesArray, Js::JavascriptNumber::ToVar(propertiesArrayCount++, scriptContext), marshaledObj, scriptContext);
- }
- objectDisplayWeakRef->ReleaseStrongReference();
- objectDisplayWeakRef.Detach();
- }
- }
- }
- walkerRef->ReleaseStrongReference();
- }
- JsrtDebugUtils::AddPropertyToObject(childrensObject, JsrtDebugPropertyId::totalPropertiesOfObject, childrensCount, scriptContext);
- JsrtDebugUtils::AddPropertyToObject(childrensObject, JsrtDebugPropertyId::properties, propertiesArray, scriptContext);
- JsrtDebugUtils::AddPropertyToObject(childrensObject, JsrtDebugPropertyId::debuggerOnlyProperties, debuggerOnlyPropertiesArray, scriptContext);
- return childrensObject;
- }
- JsrtDebuggerObjectsManager::JsrtDebuggerObjectsManager(JsrtDebugManager* jsrtDebugManager) :
- handleId(0),
- jsrtDebugManager(jsrtDebugManager),
- handleToDebuggerObjectsDictionary(nullptr),
- dataToDebuggerObjectsDictionary(nullptr)
- {
- Assert(jsrtDebugManager != nullptr);
- }
- JsrtDebuggerObjectsManager::~JsrtDebuggerObjectsManager()
- {
- if (this->dataToDebuggerObjectsDictionary != nullptr)
- {
- AssertMsg(this->dataToDebuggerObjectsDictionary->Count() == 0, "Should have cleared all debugger objects by now?");
- Adelete(this->GetDebugObjectArena(), this->dataToDebuggerObjectsDictionary);
- this->dataToDebuggerObjectsDictionary = nullptr;
- }
- if (this->handleToDebuggerObjectsDictionary != nullptr)
- {
- AssertMsg(this->handleToDebuggerObjectsDictionary->Count() == 0, "Should have cleared all handle by now?");
- Adelete(this->GetDebugObjectArena(), this->handleToDebuggerObjectsDictionary);
- this->handleToDebuggerObjectsDictionary = nullptr;
- }
- }
- void JsrtDebuggerObjectsManager::ClearAll()
- {
- if (this->dataToDebuggerObjectsDictionary != nullptr)
- {
- this->dataToDebuggerObjectsDictionary->Clear();
- }
- if (this->handleToDebuggerObjectsDictionary != nullptr)
- {
- this->handleToDebuggerObjectsDictionary->Map([this](uint handle, JsrtDebuggerObjectBase* debuggerObject) {
- Adelete(this->GetDebugObjectArena(), debuggerObject);
- });
- this->handleToDebuggerObjectsDictionary->Clear();
- }
- this->handleId = 0;
- }
- ArenaAllocator * JsrtDebuggerObjectsManager::GetDebugObjectArena()
- {
- return this->GetJsrtDebugManager()->GetDebugObjectArena();
- }
- bool JsrtDebuggerObjectsManager::TryGetDebuggerObjectFromHandle(uint handle, JsrtDebuggerObjectBase ** debuggerObject)
- {
- if (this->handleToDebuggerObjectsDictionary == nullptr)
- {
- return false;
- }
- return this->handleToDebuggerObjectsDictionary->TryGetValue(handle, debuggerObject);
- }
- void JsrtDebuggerObjectsManager::AddToDebuggerObjectsDictionary(JsrtDebuggerObjectBase * debuggerObject)
- {
- Assert(debuggerObject != nullptr);
- uint handle = debuggerObject->GetHandle();
- Assert(handle > 0);
- if (this->handleToDebuggerObjectsDictionary == nullptr)
- {
- this->handleToDebuggerObjectsDictionary = Anew(this->GetDebugObjectArena(), DebuggerObjectsDictionary, this->GetDebugObjectArena(), 10);
- }
- Assert(!this->handleToDebuggerObjectsDictionary->ContainsKey(handle));
- int index = this->handleToDebuggerObjectsDictionary->Add(handle, debuggerObject);
- Assert(index != -1);
- }
- void JsrtDebuggerObjectsManager::AddToDataToDebuggerObjectsDictionary(void * data, JsrtDebuggerObjectBase * debuggerObject)
- {
- Assert(data != nullptr);
- Assert(debuggerObject != nullptr);
- if (this->dataToDebuggerObjectsDictionary == nullptr)
- {
- this->dataToDebuggerObjectsDictionary = Anew(this->GetDebugObjectArena(), DataToDebuggerObjectsDictionary, this->GetDebugObjectArena(), 10);
- }
- Assert(!this->dataToDebuggerObjectsDictionary->ContainsKey(data));
- int index = this->dataToDebuggerObjectsDictionary->Add(data, debuggerObject);
- Assert(index != -1);
- this->AddToDebuggerObjectsDictionary(debuggerObject);
- }
- bool JsrtDebuggerObjectsManager::TryGetDataFromDataToDebuggerObjectsDictionary(void * data, JsrtDebuggerObjectBase ** debuggerObject)
- {
- if (this->dataToDebuggerObjectsDictionary == nullptr)
- {
- return false;
- }
- return this->dataToDebuggerObjectsDictionary->TryGetValue(data, debuggerObject);
- }
- JsrtDebuggerStackFrame::JsrtDebuggerStackFrame(JsrtDebuggerObjectsManager * debuggerObjectsManager, Js::DiagStackFrame * stackFrame, uint frameIndex) :
- debuggerObjectsManager(debuggerObjectsManager),
- frameIndex(frameIndex),
- stackFrame(stackFrame)
- {
- Assert(this->stackFrame != nullptr);
- }
- JsrtDebuggerStackFrame::~JsrtDebuggerStackFrame()
- {
- this->debuggerObjectsManager = nullptr;
- this->stackFrame = nullptr;
- }
- Js::DynamicObject * JsrtDebuggerStackFrame::GetJSONObject(Js::ScriptContext* scriptContext)
- {
- Js::ScriptContext *frameScriptContext = stackFrame->GetScriptContext();
- Js::DynamicObject* stackTraceObject = frameScriptContext->GetLibrary()->CreateObject();
- Js::FunctionBody* functionBody = stackFrame->GetFunction();
- Js::Utf8SourceInfo* utf8SourceInfo = functionBody->GetUtf8SourceInfo();
- JsrtDebugUtils::AddPropertyToObject(stackTraceObject, JsrtDebugPropertyId::index, frameIndex, scriptContext);
- JsrtDebugUtils::AddScriptIdToObject(stackTraceObject, utf8SourceInfo);
- int currentByteCodeOffset = stackFrame->GetByteCodeOffset();
- if (stackFrame->IsInterpreterFrame() && frameIndex != 0)
- {
- // For non-leaf interpreter frames back up 1 instruction so we see the caller
- // rather than the statement after the caller
- currentByteCodeOffset--;
- }
- JsrtDebugUtils::AddLineColumnToObject(stackTraceObject, functionBody, currentByteCodeOffset);
- JsrtDebugUtils::AddSourceLengthAndTextToObject(stackTraceObject, functionBody, currentByteCodeOffset);
- Js::JavascriptFunction* javascriptFunction = stackFrame->GetJavascriptFunction();
- JsrtDebuggerObjectBase* functionObject = nullptr;
- if (!this->debuggerObjectsManager->TryGetDataFromDataToDebuggerObjectsDictionary(javascriptFunction, &functionObject))
- {
- functionObject = JsrtDebuggerObjectFunction::Make(this->debuggerObjectsManager, javascriptFunction);
- }
- JsrtDebugUtils::AddPropertyToObject(stackTraceObject, JsrtDebugPropertyId::functionHandle, functionObject->GetHandle(), frameScriptContext);
- return stackTraceObject;
- }
- Js::DynamicObject * JsrtDebuggerStackFrame::GetLocalsObject(Js::ScriptContext* scriptContext)
- {
- /*
- {
- "thisObject" : {},
- "exception" : {},
- "arguments" : {},
- "returnValue" : {},
- "functionCallsReturn" : [{}, {}],
- "locals" : [],
- "scopes" : [{}, {}],
- "globals" : {}
- }
- */
- Js::DynamicObject* propertiesObject = scriptContext->GetLibrary()->CreateObject();
- Js::Var returnValueObject = nullptr;
- uint functionCallsReturnCount = 0;
- Js::JavascriptArray* functionCallsReturn = scriptContext->GetLibrary()->CreateArray();
- uint totalLocalsCount = 0;
- Js::JavascriptArray* localsArray = scriptContext->GetLibrary()->CreateArray();
- uint scopesCount = 0;
- Js::JavascriptArray* scopesArray = scriptContext->GetLibrary()->CreateArray();
- Js::DynamicObject* globalsObject = nullptr;
- ReferencedArenaAdapter* pRefArena = scriptContext->GetThreadContext()->GetDebugManager()->GetDiagnosticArena();
- Js::IDiagObjectModelDisplay* pLocalsDisplay = Anew(pRefArena->Arena(), Js::LocalsDisplay, this->stackFrame);
- WeakArenaReference<Js::IDiagObjectModelWalkerBase>* objectModelWalker = pLocalsDisplay->CreateWalker();
- if (objectModelWalker != nullptr)
- {
- Js::LocalsWalker* localsWalker = (Js::LocalsWalker*)objectModelWalker->GetStrongReference();
- if (localsWalker != nullptr)
- {
- // If 'this' is available add 'thisObject'
- Js::ResolvedObject thisResolvedObject;
- {
- ENFORCE_ENTRYEXITRECORD_HASCALLER(scriptContext);
- thisResolvedObject.obj = this->stackFrame->GetThisFromFrame(&thisResolvedObject.address, localsWalker);
- }
- if (thisResolvedObject.obj != nullptr)
- {
- thisResolvedObject.scriptContext = scriptContext;
- thisResolvedObject.name = _u("this");
- thisResolvedObject.typeId = Js::JavascriptOperators::GetTypeId(thisResolvedObject.obj);
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(this->debuggerObjectsManager, thisResolvedObject, this->stackFrame->GetScriptContext(), false, [&](Js::Var marshaledObj)
- {
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::thisObject, marshaledObj, scriptContext);
- });
- }
- uint32 totalProperties = localsWalker->GetChildrenCount();
- if (totalProperties > 0)
- {
- int index = 0;
- Js::ResolvedObject resolvedObject;
- resolvedObject.scriptContext = this->stackFrame->GetScriptContext();
- // If we have a exception add 'exception'
- if (Js::VariableWalkerBase::GetExceptionObject(index, this->stackFrame, &resolvedObject))
- {
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(this->debuggerObjectsManager, resolvedObject, scriptContext, false, [&](Js::Var marshaledObj)
- {
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::exception, marshaledObj, scriptContext);
- });
- }
- // If user have not explicitly defined 'arguments' add 'arguments'
- if (localsWalker->HasUserNotDefinedArguments() && localsWalker->CreateArgumentsObject(&resolvedObject))
- {
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(this->debuggerObjectsManager, resolvedObject, scriptContext, false, [&](Js::Var marshaledObj)
- {
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::arguments, marshaledObj, scriptContext);
- });
- }
- Js::ReturnedValueList *returnedValueList = this->stackFrame->GetScriptContext()->GetDebugContext()->GetProbeContainer()->GetReturnedValueList();
- // If we have return value(s) add them to 'returnValue' or 'functionCallsReturn'
- if (returnedValueList != nullptr && returnedValueList->Count() > 0 && this->stackFrame->IsTopFrame())
- {
- for (int i = 0; i < returnedValueList->Count(); ++i)
- {
- Js::ReturnedValue * returnValue = returnedValueList->Item(i);
- Js::VariableWalkerBase::GetReturnedValueResolvedObject(returnValue, this->stackFrame, &resolvedObject);
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(debuggerObjectsManager, resolvedObject, scriptContext, false, [&](Js::Var marshaledObj)
- {
- if (returnValue->isValueOfReturnStatement)
- {
- returnValueObject = marshaledObj;
- }
- else
- {
- Js::JavascriptOperators::OP_SetElementI((Js::Var)functionCallsReturn, Js::JavascriptNumber::ToVar(functionCallsReturnCount, scriptContext), marshaledObj, scriptContext);
- functionCallsReturnCount++;
- }
- });
- }
- if (returnValueObject != nullptr)
- {
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::returnValue, returnValueObject, scriptContext);
- }
- if (functionCallsReturnCount > 0)
- {
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::functionCallsReturn, functionCallsReturn, scriptContext);
- }
- }
- // Add all locals variable(s) available under 'locals'
- uint32 localsCount = localsWalker->GetLocalVariablesCount();
- for (uint32 i = 0; i < localsCount; ++i)
- {
- if (!localsWalker->GetLocal(i, &resolvedObject))
- {
- break;
- }
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(debuggerObjectsManager, resolvedObject, scriptContext, false, [&](Js::Var marshaledObj)
- {
- Js::JavascriptOperators::OP_SetElementI((Js::Var)localsArray, Js::JavascriptNumber::ToVar(totalLocalsCount, scriptContext), marshaledObj, scriptContext);
- totalLocalsCount++;
- });
- }
- // Add all variable(s) captured under 'scopes'
- index = 0;
- BOOL foundGroup = TRUE;
- while (foundGroup)
- {
- foundGroup = localsWalker->GetScopeObject(index++, &resolvedObject);
- if (foundGroup == TRUE)
- {
- AutoPtr<WeakArenaReference<Js::IDiagObjectModelDisplay>> objectDisplayWeakRef(resolvedObject.GetObjectDisplay());
- JsrtDebuggerObjectBase* debuggerObject = JsrtDebuggerObjectScope::Make(debuggerObjectsManager, objectDisplayWeakRef, scopesCount);
- Js::DynamicObject* object = debuggerObject->GetJSONObject(resolvedObject.scriptContext, /* forceSetValueProp */ false);
- Assert(object != nullptr);
- Js::Var marshaledObj = Js::CrossSite::MarshalVar(scriptContext, object);
- Js::JavascriptOperators::OP_SetElementI((Js::Var)scopesArray, Js::JavascriptNumber::ToVar(scopesCount, scriptContext), marshaledObj, scriptContext);
- scopesCount++;
- objectDisplayWeakRef.Detach();
- }
- }
- // Add globals handle
- if (localsWalker->GetGlobalsObject(&resolvedObject))
- {
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectGlobalsNode>(this->debuggerObjectsManager, resolvedObject, scriptContext, false, [&](Js::Var marshaledObj)
- {
- globalsObject = (Js::DynamicObject*)marshaledObj;
- });
- }
- }
- objectModelWalker->ReleaseStrongReference();
- HeapDelete(objectModelWalker);
- }
- Adelete(pRefArena->Arena(), pLocalsDisplay);
- }
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::locals, localsArray, scriptContext);
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::scopes, scopesArray, scriptContext);
- if (globalsObject == nullptr)
- {
- globalsObject = scriptContext->GetLibrary()->CreateObject();
- }
- JsrtDebugUtils::AddPropertyToObject(propertiesObject, JsrtDebugPropertyId::globals, globalsObject, scriptContext);
- return propertiesObject;
- }
- bool JsrtDebuggerStackFrame::Evaluate(Js::ScriptContext* scriptContext, const char16 *source, int sourceLength, bool isLibraryCode, bool forceSetValueProp, Js::DynamicObject** evalResult)
- {
- *evalResult = nullptr;
- bool success = false;
- if (this->stackFrame != nullptr)
- {
- Js::ResolvedObject resolvedObject;
- HRESULT hr = S_OK;
- Js::ScriptContext* frameScriptContext = this->stackFrame->GetScriptContext();
- Js::JavascriptExceptionObject *exceptionObject = nullptr;
- {
- BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED(frameScriptContext, false)
- {
- ENFORCE_ENTRYEXITRECORD_HASCALLER(frameScriptContext);
- this->stackFrame->EvaluateImmediate(source, sourceLength, isLibraryCode, &resolvedObject);
- }
- END_JS_RUNTIME_CALL_AND_TRANSLATE_AND_GET_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr, frameScriptContext, exceptionObject);
- }
- if (resolvedObject.obj == nullptr)
- {
- resolvedObject.name = _u("{exception}");
- resolvedObject.typeId = Js::TypeIds_Error;
- resolvedObject.address = nullptr;
- if (exceptionObject != nullptr)
- {
- resolvedObject.obj = exceptionObject->GetThrownObject(scriptContext);
- }
- else
- {
- resolvedObject.obj = scriptContext->GetLibrary()->GetUndefined();
- }
- }
- else
- {
- success = true;
- }
- if (resolvedObject.obj != nullptr)
- {
- resolvedObject.scriptContext = frameScriptContext;
- charcount_t len = Js::JavascriptString::GetBufferLength(source);
- resolvedObject.name = AnewNoThrowArray(this->debuggerObjectsManager->GetDebugObjectArena(), WCHAR, len + 1);
- if (resolvedObject.name != nullptr)
- {
- wcscpy_s((WCHAR*)resolvedObject.name, len + 1, source);
- }
- else
- {
- // len can be big, if we failed just have empty string
- resolvedObject.name = _u("");
- }
- resolvedObject.typeId = Js::JavascriptOperators::GetTypeId(resolvedObject.obj);
- JsrtDebuggerObjectBase::CreateDebuggerObject<JsrtDebuggerObjectProperty>(this->debuggerObjectsManager, resolvedObject, scriptContext, forceSetValueProp, [&](Js::Var marshaledObj)
- {
- *evalResult = (Js::DynamicObject*)marshaledObj;
- });
- }
- }
- return success;
- }
- JsrtDebuggerObjectProperty::JsrtDebuggerObjectProperty(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay) :
- JsrtDebuggerObjectBase(JsrtDebuggerObjectType::Property, debuggerObjectsManager),
- objectDisplay(objectDisplay),
- walkerRef(nullptr)
- {
- Assert(objectDisplay != nullptr);
- }
- JsrtDebuggerObjectProperty::~JsrtDebuggerObjectProperty()
- {
- if (this->objectDisplay != nullptr)
- {
- HeapDelete(this->objectDisplay);
- this->objectDisplay = nullptr;
- }
- if (this->walkerRef != nullptr)
- {
- HeapDelete(this->walkerRef);
- this->walkerRef = nullptr;
- }
- }
- JsrtDebuggerObjectBase * JsrtDebuggerObjectProperty::Make(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay)
- {
- JsrtDebuggerObjectBase* debuggerObject = Anew(debuggerObjectsManager->GetDebugObjectArena(), JsrtDebuggerObjectProperty, debuggerObjectsManager, objectDisplay);
- debuggerObjectsManager->AddToDebuggerObjectsDictionary(debuggerObject);
- return debuggerObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectProperty::GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp)
- {
- Js::IDiagObjectModelDisplay* objectDisplayRef = this->objectDisplay->GetStrongReference();
- Js::DynamicObject* propertyObject = nullptr;
- if (objectDisplayRef != nullptr)
- {
- propertyObject = scriptContext->GetLibrary()->CreateObject();
- LPCWSTR name = objectDisplayRef->Name();
- JsrtDebugUtils::AddPropertyToObject(propertyObject, JsrtDebugPropertyId::name, name, wcslen(name), scriptContext);
- JsrtDebugUtils::AddPropertyType(propertyObject, objectDisplayRef, scriptContext, forceSetValueProp); // Will add type, value, display, className, propertyAttributes
- JsrtDebugUtils::AddPropertyToObject(propertyObject, JsrtDebugPropertyId::handle, this->GetHandle(), scriptContext);
- this->objectDisplay->ReleaseStrongReference();
- }
- return propertyObject;
- }
- Js::DynamicObject* JsrtDebuggerObjectProperty::GetChildren(Js::ScriptContext* scriptContext, uint fromCount, uint totalCount)
- {
- Js::IDiagObjectModelDisplay* objectDisplayRef = objectDisplay->GetStrongReference();
- if (objectDisplayRef == nullptr)
- {
- return nullptr;
- }
- if (this->walkerRef == nullptr)
- {
- this->walkerRef = objectDisplayRef->CreateWalker();
- }
- Js::DynamicObject* childrens = __super::GetChildren(this->walkerRef, scriptContext, fromCount, totalCount);
- objectDisplay->ReleaseStrongReference();
- return childrens;
- }
- JsrtDebuggerObjectScope::JsrtDebuggerObjectScope(JsrtDebuggerObjectsManager * debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay, uint index) :
- JsrtDebuggerObjectBase(JsrtDebuggerObjectType::Scope, debuggerObjectsManager),
- objectDisplay(objectDisplay),
- index(index),
- walkerRef(nullptr)
- {
- Assert(this->objectDisplay != nullptr);
- }
- JsrtDebuggerObjectScope::~JsrtDebuggerObjectScope()
- {
- if (this->objectDisplay != nullptr)
- {
- HeapDelete(this->objectDisplay);
- this->objectDisplay = nullptr;
- }
- if (this->walkerRef != nullptr)
- {
- HeapDelete(this->walkerRef);
- this->walkerRef = nullptr;
- }
- }
- JsrtDebuggerObjectBase * JsrtDebuggerObjectScope::Make(JsrtDebuggerObjectsManager * debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay, uint index)
- {
- JsrtDebuggerObjectBase* debuggerObject = Anew(debuggerObjectsManager->GetDebugObjectArena(), JsrtDebuggerObjectScope, debuggerObjectsManager, objectDisplay, index);
- debuggerObjectsManager->AddToDebuggerObjectsDictionary(debuggerObject);
- return debuggerObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectScope::GetJSONObject(Js::ScriptContext* scriptContext, bool forceSetValueProp)
- {
- Js::IDiagObjectModelDisplay* modelDisplay = this->objectDisplay->GetStrongReference();
- Js::DynamicObject* scopeObject = nullptr;
- if (modelDisplay != nullptr)
- {
- scopeObject = scriptContext->GetLibrary()->CreateObject();
- JsrtDebugUtils::AddPropertyToObject(scopeObject, JsrtDebugPropertyId::index, this->index, scriptContext);
- JsrtDebugUtils::AddPropertyToObject(scopeObject, JsrtDebugPropertyId::handle, this->GetHandle(), scriptContext);
- this->objectDisplay->ReleaseStrongReference();
- }
- return scopeObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectScope::GetChildren(Js::ScriptContext * scriptContext, uint fromCount, uint totalCount)
- {
- Js::IDiagObjectModelDisplay* objectDisplayRef = objectDisplay->GetStrongReference();
- if (objectDisplayRef == nullptr)
- {
- return nullptr;
- }
- if (this->walkerRef == nullptr)
- {
- this->walkerRef = objectDisplayRef->CreateWalker();
- }
- Js::DynamicObject* childrens = __super::GetChildren(this->walkerRef, scriptContext, fromCount, totalCount);
- objectDisplay->ReleaseStrongReference();
- return childrens;
- }
- JsrtDebuggerObjectFunction::JsrtDebuggerObjectFunction(JsrtDebuggerObjectsManager* debuggerObjectsManager, Js::JavascriptFunction* javascriptFunction) :
- JsrtDebuggerObjectBase(JsrtDebuggerObjectType::Function, debuggerObjectsManager),
- javascriptFunction(javascriptFunction),
- objectDisplay(nullptr),
- walkerRef(nullptr)
- {
- }
- JsrtDebuggerObjectFunction::~JsrtDebuggerObjectFunction()
- {
- if (this->objectDisplay != nullptr)
- {
- HeapDelete(this->objectDisplay);
- this->objectDisplay = nullptr;
- }
- if (this->walkerRef != nullptr)
- {
- HeapDelete(this->walkerRef);
- this->walkerRef = nullptr;
- }
- this->javascriptFunction = nullptr;
- }
- JsrtDebuggerObjectBase * JsrtDebuggerObjectFunction::Make(JsrtDebuggerObjectsManager * debuggerObjectsManager, Js::JavascriptFunction* javascriptFunction)
- {
- JsrtDebuggerObjectBase* debuggerObject = nullptr;
- Assert(!debuggerObjectsManager->TryGetDataFromDataToDebuggerObjectsDictionary(javascriptFunction, &debuggerObject));
-
- debuggerObject = Anew(debuggerObjectsManager->GetDebugObjectArena(), JsrtDebuggerObjectFunction, debuggerObjectsManager, javascriptFunction);
- debuggerObjectsManager->AddToDataToDebuggerObjectsDictionary(javascriptFunction, debuggerObject);
- return debuggerObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectFunction::GetJSONObject(Js::ScriptContext * scriptContext, bool forceSetValueProp)
- {
- Js::DynamicObject* functionObject = scriptContext->GetLibrary()->CreateObject();
- Js::FunctionBody* functionBody = this->javascriptFunction->GetFunctionBody();
- JsrtDebugUtils::AddScriptIdToObject(functionObject, functionBody->GetUtf8SourceInfo());
- JsrtDebugUtils::AddPropertyToObject(functionObject, JsrtDebugPropertyId::line, (uint32)functionBody->GetLineNumber(), scriptContext);
- JsrtDebugUtils::AddPropertyToObject(functionObject, JsrtDebugPropertyId::column, (uint32)functionBody->GetColumnNumber(), scriptContext);
- JsrtDebugUtils::AddPropertyToObject(functionObject, JsrtDebugPropertyId::name, functionBody->GetDisplayName(), functionBody->GetDisplayNameLength(), scriptContext);
- JsrtDebugUtils::AddPropertyToObject(functionObject, JsrtDebugPropertyId::type, scriptContext->GetLibrary()->GetFunctionTypeDisplayString(), scriptContext);
- JsrtDebugUtils::AddPropertyToObject(functionObject, JsrtDebugPropertyId::handle, this->GetHandle(), scriptContext);
- return functionObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectFunction::GetChildren(Js::ScriptContext * scriptContext, uint fromCount, uint totalCount)
- {
- if (this->objectDisplay == nullptr)
- {
- Js::ResolvedObject functionResolvedObject;
- functionResolvedObject.obj = this->javascriptFunction;
- functionResolvedObject.scriptContext = scriptContext;
- functionResolvedObject.name = _u("Function");
- functionResolvedObject.typeId = Js::JavascriptOperators::GetTypeId(functionResolvedObject.obj);
- this->objectDisplay = functionResolvedObject.GetObjectDisplay();
- }
- Js::IDiagObjectModelDisplay* objectDisplayRef = this->objectDisplay->GetStrongReference();
- if (objectDisplayRef == nullptr)
- {
- return nullptr;
- }
- if (this->walkerRef == nullptr)
- {
- this->walkerRef = objectDisplayRef->CreateWalker();
- }
- Js::DynamicObject* childrens = __super::GetChildren(this->walkerRef, scriptContext, fromCount, totalCount);
- this->objectDisplay->ReleaseStrongReference();
- return childrens;
- }
- JsrtDebuggerObjectGlobalsNode::JsrtDebuggerObjectGlobalsNode(JsrtDebuggerObjectsManager* debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay) :
- JsrtDebuggerObjectBase(JsrtDebuggerObjectType::Globals, debuggerObjectsManager),
- objectDisplay(objectDisplay),
- walkerRef(nullptr)
- {
- Assert(objectDisplay != nullptr);
- }
- JsrtDebuggerObjectGlobalsNode::~JsrtDebuggerObjectGlobalsNode()
- {
- if (this->objectDisplay != nullptr)
- {
- HeapDelete(this->objectDisplay);
- this->objectDisplay = nullptr;
- }
- if (this->walkerRef != nullptr)
- {
- HeapDelete(this->walkerRef);
- this->walkerRef = nullptr;
- }
- }
- JsrtDebuggerObjectBase * JsrtDebuggerObjectGlobalsNode::Make(JsrtDebuggerObjectsManager * debuggerObjectsManager, WeakArenaReference<Js::IDiagObjectModelDisplay>* objectDisplay)
- {
- JsrtDebuggerObjectBase* debuggerObject = Anew(debuggerObjectsManager->GetDebugObjectArena(), JsrtDebuggerObjectGlobalsNode, debuggerObjectsManager, objectDisplay);
- debuggerObjectsManager->AddToDebuggerObjectsDictionary(debuggerObject);
- return debuggerObject;
- }
- Js::DynamicObject * JsrtDebuggerObjectGlobalsNode::GetJSONObject(Js::ScriptContext * scriptContext, bool forceSetValueProp)
- {
- Js::IDiagObjectModelDisplay* objectDisplayRef = this->objectDisplay->GetStrongReference();
- Js::DynamicObject* globalsNode = nullptr;
- if (objectDisplayRef != nullptr)
- {
- globalsNode = scriptContext->GetLibrary()->CreateObject();
- JsrtDebugUtils::AddPropertyToObject(globalsNode, JsrtDebugPropertyId::handle, this->GetHandle(), scriptContext);
- this->objectDisplay->ReleaseStrongReference();
- }
- return globalsNode;
- }
- Js::DynamicObject * JsrtDebuggerObjectGlobalsNode::GetChildren(Js::ScriptContext * scriptContext, uint fromCount, uint totalCount)
- {
- Js::IDiagObjectModelDisplay* objectDisplayRef = objectDisplay->GetStrongReference();
- if (objectDisplayRef == nullptr)
- {
- return nullptr;
- }
- if (this->walkerRef == nullptr)
- {
- this->walkerRef = objectDisplayRef->CreateWalker();
- }
- Js::DynamicObject* childrens = __super::GetChildren(this->walkerRef, scriptContext, fromCount, totalCount);
- objectDisplay->ReleaseStrongReference();
- return childrens;
- }
- JsrtDebugStackFrames::JsrtDebugStackFrames(JsrtDebugManager* jsrtDebugManager):
- framesDictionary(nullptr)
- {
- Assert(jsrtDebugManager != nullptr);
- this->jsrtDebugManager = jsrtDebugManager;
- }
- JsrtDebugStackFrames::~JsrtDebugStackFrames()
- {
- if (this->framesDictionary != nullptr)
- {
- this->ClearFrameDictionary();
- Adelete(this->jsrtDebugManager->GetDebugObjectArena(), this->framesDictionary);
- this->framesDictionary = nullptr;
- }
- }
- static int __cdecl DiagStackFrameSorter(void * dispatchHaltFrameAddress, const void * diagStackFrame1, const void * diagStackFrame2)
- {
- const DWORD_PTR *p1 = reinterpret_cast<const DWORD_PTR*>(diagStackFrame1);
- const DWORD_PTR *p2 = reinterpret_cast<const DWORD_PTR*>(diagStackFrame2);
- Js::DiagStackFrame * pStackFrame1 = (Js::DiagStackFrame *)(*p1);
- Js::DiagStackFrame * pStackFrame2 = (Js::DiagStackFrame *)(*p2);
- DWORD_PTR stackAddress1 = pStackFrame1->GetStackAddress();
- DWORD_PTR stackAddress2 = pStackFrame2->GetStackAddress();
- return stackAddress1 > stackAddress2 ? 1 : -1;
- }
- Js::JavascriptArray * JsrtDebugStackFrames::StackFrames(Js::ScriptContext * scriptContext)
- {
- Js::JavascriptArray* stackTraceArray = nullptr;
- ThreadContext* threadContext = scriptContext->GetThreadContext();
- DWORD_PTR dispatchHaltFrameAddress = threadContext->GetDebugManager()->GetDispatchHaltFrameAddress();
- AssertMsg(dispatchHaltFrameAddress > 0, "Didn't set the dispatchHaltFrameAddress at time of break?");
- if (dispatchHaltFrameAddress != 0)
- {
- if (this->framesDictionary == nullptr)
- {
- this->framesDictionary = Anew(this->jsrtDebugManager->GetDebugObjectArena(), FramesDictionary, this->jsrtDebugManager->GetDebugObjectArena(), 10);
- }
- else
- {
- this->ClearFrameDictionary();
- }
- typedef JsUtil::List<Js::DiagStackFrame*, ArenaAllocator> DiagStackFrameList;
- DiagStackFrameList* stackList = Anew(this->jsrtDebugManager->GetDebugObjectArena(), DiagStackFrameList, this->jsrtDebugManager->GetDebugObjectArena(), 10);
- // Walk all the script contexts and collect the frames which are below the address when break was reported.
- for (Js::ScriptContext *tempScriptContext = threadContext->GetScriptContextList();
- tempScriptContext != nullptr && tempScriptContext->IsScriptContextInDebugMode();
- tempScriptContext = tempScriptContext->next)
- {
- Js::WeakDiagStack * framePointers = tempScriptContext->GetDebugContext()->GetProbeContainer()->GetFramePointers(dispatchHaltFrameAddress);
- if (framePointers != nullptr)
- {
- Js::DiagStack* stackFrames = framePointers->GetStrongReference();
- if (stackFrames != nullptr)
- {
- int count = stackFrames->Count();
- for (int frameIndex = 0; frameIndex < count; ++frameIndex)
- {
- Js::DiagStackFrame* stackFrame = stackFrames->Peek(frameIndex);
- stackList->Add(stackFrame);
- }
- }
- framePointers->ReleaseStrongReference();
- HeapDelete(framePointers);
- }
- }
- // Frames can be from multiple contexts, sort them based on stack address
- stackList->Sort(DiagStackFrameSorter, (void*)dispatchHaltFrameAddress);
- stackTraceArray = scriptContext->GetLibrary()->CreateArray(stackList->Count(), stackList->Count());
- stackList->Map([&](int index, Js::DiagStackFrame* stackFrame)
- {
- AssertMsg(index != 0 || stackFrame->IsTopFrame(), "Index 0 frame is not marked as top frame");
- Js::DynamicObject* stackTraceObject = this->GetStackFrame(stackFrame, index);
- Js::Var marshaledObj = Js::CrossSite::MarshalVar(scriptContext, stackTraceObject);
- stackTraceArray->DirectSetItemAt(index, marshaledObj);
- });
- Adelete(this->jsrtDebugManager->GetDebugObjectArena(), stackList);
- }
- else
- {
- // Empty array
- stackTraceArray = scriptContext->GetLibrary()->CreateArray(0, 0);
- }
- return stackTraceArray;
- }
- bool JsrtDebugStackFrames::TryGetFrameObjectFromFrameIndex(uint frameIndex, JsrtDebuggerStackFrame ** debuggerStackFrame)
- {
- if (this->framesDictionary != nullptr)
- {
- return this->framesDictionary->TryGetValue(frameIndex, debuggerStackFrame);
- }
- return false;
- }
- Js::DynamicObject * JsrtDebugStackFrames::GetStackFrame(Js::DiagStackFrame * stackFrame, uint frameIndex)
- {
- JsrtDebuggerStackFrame* debuggerStackFrame = Anew(this->jsrtDebugManager->GetDebugObjectArena(), JsrtDebuggerStackFrame, this->jsrtDebugManager->GetDebuggerObjectsManager(), stackFrame, frameIndex);
- Assert(this->framesDictionary != nullptr);
- this->framesDictionary->Add(frameIndex, debuggerStackFrame);
- return debuggerStackFrame->GetJSONObject(stackFrame->GetScriptContext());
- }
- void JsrtDebugStackFrames::ClearFrameDictionary()
- {
- if (this->framesDictionary != nullptr)
- {
- this->framesDictionary->Map([this](uint handle, JsrtDebuggerStackFrame* debuggerStackFrame) {
- Adelete(this->jsrtDebugManager->GetDebugObjectArena(), debuggerStackFrame);
- });
- this->framesDictionary->Clear();
- }
- }
- #endif
|