JsrtDiag.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  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. #include "JsrtPch.h"
  6. #include "JsrtInternal.h"
  7. #include "RuntimeDebugPch.h"
  8. #include "ThreadContextTlsEntry.h"
  9. #include "JsrtDebugUtils.h"
  10. #include "Codex/Utf8Helper.h"
  11. #define VALIDATE_IS_DEBUGGING(jsrtDebugManager) \
  12. if (jsrtDebugManager == nullptr || !jsrtDebugManager->IsDebugEventCallbackSet()) \
  13. { \
  14. return JsErrorDiagNotInDebugMode; \
  15. }
  16. #define VALIDATE_RUNTIME_IS_AT_BREAK(runtime) \
  17. if (runtime->GetThreadContext()->GetDebugManager() == nullptr || !runtime->GetThreadContext()->GetDebugManager()->IsAtDispatchHalt()) \
  18. { \
  19. return JsErrorDiagNotAtBreak; \
  20. }
  21. #define VALIDATE_RUNTIME_STATE_FOR_START_STOP_DEBUGGING(threadContext) \
  22. if (threadContext->GetRecycler() && threadContext->GetRecycler()->IsHeapEnumInProgress()) \
  23. { \
  24. return JsErrorHeapEnumInProgress; \
  25. } \
  26. else if (threadContext->IsInThreadServiceCallback()) \
  27. { \
  28. return JsErrorInThreadServiceCallback; \
  29. } \
  30. else if (threadContext->IsInScript()) \
  31. { \
  32. return JsErrorRuntimeInUse; \
  33. } \
  34. ThreadContextScope scope(threadContext); \
  35. if (!scope.IsValid()) \
  36. { \
  37. return JsErrorWrongThread; \
  38. }
  39. CHAKRA_API JsDiagStartDebugging(
  40. _In_ JsRuntimeHandle runtimeHandle,
  41. _In_ JsDiagDebugEventCallback debugEventCallback,
  42. _In_opt_ void* callbackState)
  43. {
  44. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  45. VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
  46. PARAM_NOT_NULL(debugEventCallback);
  47. JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
  48. ThreadContext * threadContext = runtime->GetThreadContext();
  49. VALIDATE_RUNTIME_STATE_FOR_START_STOP_DEBUGGING(threadContext);
  50. if (runtime->GetJsrtDebugManager() != nullptr && runtime->GetJsrtDebugManager()->IsDebugEventCallbackSet())
  51. {
  52. return JsErrorDiagAlreadyInDebugMode;
  53. }
  54. // Create the debug object to save callback function and data
  55. runtime->EnsureJsrtDebugManager();
  56. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  57. jsrtDebugManager->SetDebugEventCallback(debugEventCallback, callbackState);
  58. if (threadContext->GetDebugManager() != nullptr)
  59. {
  60. threadContext->GetDebugManager()->SetLocalsDisplayFlags(Js::DebugManager::LocalsDisplayFlags::LocalsDisplayFlags_NoGroupMethods);
  61. }
  62. for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
  63. scriptContext != nullptr && !scriptContext->IsClosed();
  64. scriptContext = scriptContext->next)
  65. {
  66. Assert(!scriptContext->IsScriptContextInDebugMode());
  67. Js::DebugContext* debugContext = scriptContext->GetDebugContext();
  68. if (debugContext->GetHostDebugContext() == nullptr)
  69. {
  70. debugContext->SetHostDebugContext(jsrtDebugManager);
  71. }
  72. HRESULT hr;
  73. if (FAILED(hr = scriptContext->OnDebuggerAttached()))
  74. {
  75. Debugger_AttachDetach_fatal_error(hr); // Inconsistent state, we can't continue from here
  76. return JsErrorFatal;
  77. }
  78. Js::ProbeContainer* probeContainer = debugContext->GetProbeContainer();
  79. probeContainer->InitializeInlineBreakEngine(jsrtDebugManager);
  80. probeContainer->InitializeDebuggerScriptOptionCallback(jsrtDebugManager);
  81. }
  82. return JsNoError;
  83. });
  84. }
  85. CHAKRA_API JsDiagStopDebugging(
  86. _In_ JsRuntimeHandle runtimeHandle,
  87. _Out_ void** callbackState)
  88. {
  89. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  90. VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
  91. PARAM_NOT_NULL(callbackState);
  92. *callbackState = nullptr;
  93. JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
  94. ThreadContext * threadContext = runtime->GetThreadContext();
  95. VALIDATE_RUNTIME_STATE_FOR_START_STOP_DEBUGGING(threadContext);
  96. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  97. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  98. for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
  99. scriptContext != nullptr && !scriptContext->IsClosed();
  100. scriptContext = scriptContext->next)
  101. {
  102. Assert(scriptContext->IsScriptContextInDebugMode());
  103. HRESULT hr;
  104. if (FAILED(hr = scriptContext->OnDebuggerDetached()))
  105. {
  106. Debugger_AttachDetach_fatal_error(hr); // Inconsistent state, we can't continue from here
  107. return JsErrorFatal;
  108. }
  109. Js::DebugContext* debugContext = scriptContext->GetDebugContext();
  110. Js::ProbeContainer* probeContainer = debugContext->GetProbeContainer();
  111. probeContainer->UninstallInlineBreakpointProbe(nullptr);
  112. probeContainer->UninstallDebuggerScriptOptionCallback();
  113. jsrtDebugManager->ClearBreakpointDebugDocumentDictionary();
  114. }
  115. *callbackState = jsrtDebugManager->GetAndClearCallbackState();
  116. return JsNoError;
  117. });
  118. }
  119. CHAKRA_API JsDiagGetScripts(
  120. _Out_ JsValueRef *scriptsArray)
  121. {
  122. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  123. PARAM_NOT_NULL(scriptsArray);
  124. *scriptsArray = JS_INVALID_REFERENCE;
  125. JsrtContext *currentContext = JsrtContext::GetCurrent();
  126. JsrtDebugManager* jsrtDebugManager = currentContext->GetRuntime()->GetJsrtDebugManager();
  127. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  128. Js::JavascriptArray* scripts = jsrtDebugManager->GetScripts(scriptContext);
  129. if (scripts != nullptr)
  130. {
  131. *scriptsArray = scripts;
  132. return JsNoError;
  133. }
  134. return JsErrorDiagUnableToPerformAction;
  135. });
  136. }
  137. CHAKRA_API JsDiagGetSource(
  138. _In_ unsigned int scriptId,
  139. _Out_ JsValueRef *source)
  140. {
  141. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  142. PARAM_NOT_NULL(source);
  143. *source = JS_INVALID_REFERENCE;
  144. JsrtContext *currentContext = JsrtContext::GetCurrent();
  145. JsrtDebugManager* jsrtDebugManager = currentContext->GetRuntime()->GetJsrtDebugManager();
  146. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  147. Js::DynamicObject* sourceObject = jsrtDebugManager->GetSource(scriptContext, scriptId);
  148. if (sourceObject != nullptr)
  149. {
  150. *source = sourceObject;
  151. return JsNoError;
  152. }
  153. return JsErrorInvalidArgument;
  154. });
  155. }
  156. CHAKRA_API JsDiagRequestAsyncBreak(
  157. _In_ JsRuntimeHandle runtimeHandle)
  158. {
  159. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  160. VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
  161. JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
  162. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  163. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  164. for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
  165. scriptContext != nullptr && !scriptContext->IsClosed();
  166. scriptContext = scriptContext->next)
  167. {
  168. jsrtDebugManager->EnableAsyncBreak(scriptContext);
  169. }
  170. return JsNoError;
  171. });
  172. }
  173. CHAKRA_API JsDiagGetBreakpoints(
  174. _Out_ JsValueRef *breakpoints)
  175. {
  176. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  177. PARAM_NOT_NULL(breakpoints);
  178. *breakpoints = JS_INVALID_REFERENCE;
  179. JsrtContext *currentContext = JsrtContext::GetCurrent();
  180. Js::JavascriptArray* bpsArray = currentContext->GetScriptContext()->GetLibrary()->CreateArray();
  181. JsrtRuntime * runtime = currentContext->GetRuntime();
  182. ThreadContextScope scope(runtime->GetThreadContext());
  183. if (!scope.IsValid())
  184. {
  185. return JsErrorWrongThread;
  186. }
  187. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  188. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  189. for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
  190. scriptContext != nullptr && !scriptContext->IsClosed();
  191. scriptContext = scriptContext->next)
  192. {
  193. jsrtDebugManager->GetBreakpoints(&bpsArray, scriptContext);
  194. }
  195. *breakpoints = bpsArray;
  196. return JsNoError;
  197. });
  198. }
  199. CHAKRA_API JsDiagSetBreakpoint(
  200. _In_ unsigned int scriptId,
  201. _In_ unsigned int lineNumber,
  202. _In_ unsigned int columnNumber,
  203. _Out_ JsValueRef *breakpoint)
  204. {
  205. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  206. PARAM_NOT_NULL(breakpoint);
  207. *breakpoint = JS_INVALID_REFERENCE;
  208. JsrtContext *currentContext = JsrtContext::GetCurrent();
  209. JsrtRuntime * runtime = currentContext->GetRuntime();
  210. ThreadContextScope scope(runtime->GetThreadContext());
  211. if (!scope.IsValid())
  212. {
  213. return JsErrorWrongThread;
  214. }
  215. VALIDATE_IS_DEBUGGING(runtime->GetJsrtDebugManager());
  216. Js::Utf8SourceInfo* utf8SourceInfo = nullptr;
  217. for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
  218. scriptContext != nullptr && utf8SourceInfo == nullptr && !scriptContext->IsClosed();
  219. scriptContext = scriptContext->next)
  220. {
  221. scriptContext->MapScript([&](Js::Utf8SourceInfo* sourceInfo) -> bool
  222. {
  223. if (sourceInfo->GetSourceInfoId() == scriptId)
  224. {
  225. utf8SourceInfo = sourceInfo;
  226. return true;
  227. }
  228. return false;
  229. });
  230. }
  231. if (utf8SourceInfo != nullptr && utf8SourceInfo->HasDebugDocument())
  232. {
  233. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  234. Js::DynamicObject* bpObject = jsrtDebugManager->SetBreakPoint(currentContext->GetScriptContext(), utf8SourceInfo, lineNumber, columnNumber);
  235. if(bpObject != nullptr)
  236. {
  237. *breakpoint = bpObject;
  238. return JsNoError;
  239. }
  240. return JsErrorDiagUnableToPerformAction;
  241. }
  242. return JsErrorDiagObjectNotFound;
  243. });
  244. }
  245. CHAKRA_API JsDiagRemoveBreakpoint(
  246. _In_ unsigned int breakpointId)
  247. {
  248. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  249. JsrtContext *currentContext = JsrtContext::GetCurrent();
  250. JsrtRuntime* runtime = currentContext->GetRuntime();
  251. ThreadContextScope scope(runtime->GetThreadContext());
  252. if (!scope.IsValid())
  253. {
  254. return JsErrorWrongThread;
  255. }
  256. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  257. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  258. if (!jsrtDebugManager->RemoveBreakpoint(breakpointId))
  259. {
  260. return JsErrorInvalidArgument;
  261. }
  262. return JsNoError;
  263. });
  264. }
  265. CHAKRA_API JsDiagSetBreakOnException(
  266. _In_ JsRuntimeHandle runtimeHandle,
  267. _In_ JsDiagBreakOnExceptionAttributes exceptionAttributes)
  268. {
  269. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  270. VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
  271. JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
  272. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  273. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  274. jsrtDebugManager->SetBreakOnException(exceptionAttributes);
  275. return JsNoError;
  276. });
  277. }
  278. CHAKRA_API JsDiagGetBreakOnException(
  279. _In_ JsRuntimeHandle runtimeHandle,
  280. _Out_ JsDiagBreakOnExceptionAttributes* exceptionAttributes)
  281. {
  282. return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
  283. VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
  284. PARAM_NOT_NULL(exceptionAttributes);
  285. *exceptionAttributes = JsDiagBreakOnExceptionAttributeNone;
  286. JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
  287. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  288. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  289. *exceptionAttributes = jsrtDebugManager->GetBreakOnException();
  290. return JsNoError;
  291. });
  292. }
  293. CHAKRA_API JsDiagSetStepType(
  294. _In_ JsDiagStepType stepType)
  295. {
  296. return ContextAPIWrapper_NoRecord<true>([&](Js::ScriptContext * scriptContext) -> JsErrorCode {
  297. JsrtContext *currentContext = JsrtContext::GetCurrent();
  298. JsrtRuntime* runtime = currentContext->GetRuntime();
  299. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  300. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  301. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  302. if (stepType == JsDiagStepTypeStepIn)
  303. {
  304. jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_INTO);
  305. }
  306. else if (stepType == JsDiagStepTypeStepOut)
  307. {
  308. jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OUT);
  309. }
  310. else if (stepType == JsDiagStepTypeStepOver)
  311. {
  312. jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OVER);
  313. }
  314. else if (stepType == JsDiagStepTypeStepBack)
  315. {
  316. #if ENABLE_TTD
  317. ThreadContext* threadContext = runtime->GetThreadContext();
  318. if(!threadContext->IsRuntimeInTTDMode())
  319. {
  320. return JsErrorInvalidArgument;
  321. }
  322. TTD::TTDebuggerSourceLocation bpLocation;
  323. threadContext->TTDLog->GetPreviousTimeAndPositionForDebugger(bpLocation);
  324. threadContext->TTDLog->SetPendingTTDBPInfo(bpLocation);
  325. threadContext->TTDLog->SetPendingTTDMoveMode(JsTTDMoveMode::JsTTDMoveNone);
  326. //don't worry about BP suppression because we are just going to throw after we return
  327. jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
  328. #else
  329. return JsErrorInvalidArgument;
  330. #endif
  331. }
  332. else if(stepType == JsDiagStepTypeStepReverseContinue)
  333. {
  334. #if ENABLE_TTD
  335. ThreadContext* threadContext = runtime->GetThreadContext();
  336. if(!threadContext->IsRuntimeInTTDMode())
  337. {
  338. return JsErrorInvalidArgument;
  339. }
  340. TTD::TTDebuggerSourceLocation bpLocation;
  341. threadContext->TTDLog->GetTimeAndPositionForDebugger(bpLocation);
  342. threadContext->TTDLog->SetPendingTTDBPInfo(bpLocation);
  343. threadContext->TTDLog->SetPendingTTDMoveMode(JsTTDMoveMode::JsTTDMoveScanIntervalForContinue);
  344. //don't worry about BP suppression because we are just going to throw after we return
  345. jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
  346. #else
  347. return JsErrorInvalidArgument;
  348. #endif
  349. }
  350. return JsNoError;
  351. });
  352. }
  353. CHAKRA_API JsDiagGetFunctionPosition(
  354. _In_ JsValueRef function,
  355. _Out_ JsValueRef *functionPosition)
  356. {
  357. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  358. VALIDATE_INCOMING_REFERENCE(function, scriptContext);
  359. PARAM_NOT_NULL(functionPosition);
  360. *functionPosition = JS_INVALID_REFERENCE;
  361. if (!Js::RecyclableObject::Is(function) || !Js::ScriptFunction::Is(function))
  362. {
  363. return JsErrorInvalidArgument;
  364. }
  365. Js::ScriptFunction* jsFunction = Js::ScriptFunction::FromVar(function);
  366. Js::FunctionBody* functionBody = jsFunction->GetFunctionBody();
  367. if (functionBody != nullptr)
  368. {
  369. Js::Utf8SourceInfo* utf8SourceInfo = functionBody->GetUtf8SourceInfo();
  370. if (utf8SourceInfo != nullptr && !utf8SourceInfo->GetIsLibraryCode())
  371. {
  372. ULONG lineNumber = functionBody->GetLineNumber();
  373. ULONG columnNumber = functionBody->GetColumnNumber();
  374. uint startOffset = functionBody->GetStatementStartOffset(0);
  375. ULONG firstStatementLine;
  376. LONG firstStatementColumn;
  377. if (functionBody->GetLineCharOffsetFromStartChar(startOffset, &firstStatementLine, &firstStatementColumn))
  378. {
  379. Js::DynamicObject* funcPositionObject = (Js::DynamicObject*)Js::CrossSite::MarshalVar(utf8SourceInfo->GetScriptContext(), scriptContext->GetLibrary()->CreateObject());
  380. if (funcPositionObject != nullptr)
  381. {
  382. JsrtDebugUtils::AddScriptIdToObject(funcPositionObject, utf8SourceInfo);
  383. JsrtDebugUtils::AddFileNameOrScriptTypeToObject(funcPositionObject, utf8SourceInfo);
  384. JsrtDebugUtils::AddPropertyToObject(funcPositionObject, JsrtDebugPropertyId::line, (uint32) lineNumber, scriptContext);
  385. JsrtDebugUtils::AddPropertyToObject(funcPositionObject, JsrtDebugPropertyId::column, (uint32) columnNumber, scriptContext);
  386. JsrtDebugUtils::AddPropertyToObject(funcPositionObject, JsrtDebugPropertyId::firstStatementLine, (uint32) firstStatementLine, scriptContext);
  387. JsrtDebugUtils::AddPropertyToObject(funcPositionObject, JsrtDebugPropertyId::firstStatementColumn, (int32) firstStatementColumn, scriptContext);
  388. *functionPosition = funcPositionObject;
  389. return JsNoError;
  390. }
  391. }
  392. }
  393. }
  394. return JsErrorDiagObjectNotFound;
  395. });
  396. }
  397. CHAKRA_API JsDiagGetStackTrace(
  398. _Out_ JsValueRef *stackTrace)
  399. {
  400. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  401. PARAM_NOT_NULL(stackTrace);
  402. *stackTrace = JS_INVALID_REFERENCE;
  403. JsrtContext* context = JsrtContext::GetCurrent();
  404. JsrtRuntime* runtime = context->GetRuntime();
  405. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  406. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  407. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  408. *stackTrace = jsrtDebugManager->GetStackFrames(scriptContext);
  409. return JsNoError;
  410. });
  411. }
  412. CHAKRA_API JsDiagGetStackProperties(
  413. _In_ unsigned int stackFrameIndex,
  414. _Out_ JsValueRef *properties)
  415. {
  416. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  417. PARAM_NOT_NULL(properties);
  418. *properties = JS_INVALID_REFERENCE;
  419. JsrtContext* context = JsrtContext::GetCurrent();
  420. JsrtRuntime* runtime = context->GetRuntime();
  421. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  422. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  423. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  424. JsrtDebuggerStackFrame* debuggerStackFrame = nullptr;
  425. if (!jsrtDebugManager->TryGetFrameObjectFromFrameIndex(scriptContext, stackFrameIndex, &debuggerStackFrame))
  426. {
  427. return JsErrorDiagObjectNotFound;
  428. }
  429. Js::DynamicObject* localsObject = debuggerStackFrame->GetLocalsObject(scriptContext);
  430. if (localsObject != nullptr)
  431. {
  432. *properties = localsObject;
  433. return JsNoError;
  434. }
  435. return JsErrorDiagUnableToPerformAction;
  436. });
  437. }
  438. CHAKRA_API JsDiagGetProperties(
  439. _In_ unsigned int objectHandle,
  440. _In_ unsigned int fromCount,
  441. _In_ unsigned int totalCount,
  442. _Out_ JsValueRef *propertiesObject)
  443. {
  444. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  445. PARAM_NOT_NULL(propertiesObject);
  446. *propertiesObject = JS_INVALID_REFERENCE;
  447. JsrtContext* context = JsrtContext::GetCurrent();
  448. JsrtRuntime* runtime = context->GetRuntime();
  449. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  450. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  451. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  452. JsrtDebuggerObjectBase* debuggerObject = nullptr;
  453. if (!jsrtDebugManager->GetDebuggerObjectsManager()->TryGetDebuggerObjectFromHandle(objectHandle, &debuggerObject) || debuggerObject == nullptr)
  454. {
  455. return JsErrorDiagInvalidHandle;
  456. }
  457. Js::DynamicObject* properties = debuggerObject->GetChildren(scriptContext, fromCount, totalCount);
  458. if (properties != nullptr)
  459. {
  460. *propertiesObject = properties;
  461. return JsNoError;
  462. }
  463. return JsErrorDiagUnableToPerformAction;
  464. });
  465. }
  466. CHAKRA_API JsDiagGetObjectFromHandle(
  467. _In_ unsigned int objectHandle,
  468. _Out_ JsValueRef *handleObject)
  469. {
  470. return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  471. PARAM_NOT_NULL(handleObject);
  472. *handleObject = JS_INVALID_REFERENCE;
  473. JsrtContext* context = JsrtContext::GetCurrent();
  474. JsrtRuntime* runtime = context->GetRuntime();
  475. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  476. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  477. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  478. JsrtDebuggerObjectBase* debuggerObject = nullptr;
  479. if (!jsrtDebugManager->GetDebuggerObjectsManager()->TryGetDebuggerObjectFromHandle(objectHandle, &debuggerObject) || debuggerObject == nullptr)
  480. {
  481. return JsErrorDiagInvalidHandle;
  482. }
  483. Js::DynamicObject* object = debuggerObject->GetJSONObject(scriptContext);
  484. if (object != nullptr)
  485. {
  486. *handleObject = object;
  487. return JsNoError;
  488. }
  489. return JsErrorDiagUnableToPerformAction;
  490. });
  491. }
  492. CHAKRA_API JsDiagEvaluate(
  493. _In_z_ const WCHAR *expression,
  494. _In_ unsigned int stackFrameIndex,
  495. _Out_ JsValueRef *evalResult)
  496. {
  497. return ContextAPINoScriptWrapper_NoRecord([&](Js::ScriptContext *scriptContext) -> JsErrorCode {
  498. PARAM_NOT_NULL(expression);
  499. PARAM_NOT_NULL(evalResult);
  500. *evalResult = JS_INVALID_REFERENCE;
  501. JsrtContext* context = JsrtContext::GetCurrent();
  502. JsrtRuntime* runtime = context->GetRuntime();
  503. VALIDATE_RUNTIME_IS_AT_BREAK(runtime);
  504. JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();
  505. VALIDATE_IS_DEBUGGING(jsrtDebugManager);
  506. JsrtDebuggerStackFrame* debuggerStackFrame = nullptr;
  507. if (!jsrtDebugManager->TryGetFrameObjectFromFrameIndex(scriptContext, stackFrameIndex, &debuggerStackFrame))
  508. {
  509. return JsErrorDiagObjectNotFound;
  510. }
  511. size_t len = wcslen(expression);
  512. if (len != static_cast<int>(len))
  513. {
  514. return JsErrorInvalidArgument;
  515. }
  516. Js::DynamicObject* result = nullptr;
  517. bool success = debuggerStackFrame->Evaluate(scriptContext, expression, static_cast<int>(len), false, &result);
  518. if (result != nullptr)
  519. {
  520. *evalResult = result;
  521. }
  522. return success ? JsNoError : JsErrorScriptException;
  523. }, false /*allowInObjectBeforeCollectCallback*/, true /*scriptExceptionAllowed*/);
  524. }
  525. #ifdef CHAKRACOREBUILD_
  526. CHAKRA_API JsDiagEvaluateUtf8(
  527. _In_z_ const char *expression,
  528. _In_ unsigned int stackFrameIndex,
  529. _Out_ JsValueRef *evalResult)
  530. {
  531. PARAM_NOT_NULL(expression);
  532. utf8::NarrowToWide wstr(expression, strlen(expression));
  533. if (!wstr)
  534. {
  535. return JsErrorOutOfMemory;
  536. }
  537. return JsDiagEvaluate(wstr, stackFrameIndex, evalResult);
  538. }
  539. #endif