TTActionEvents.cpp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  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 "RuntimeDebugPch.h"
  6. #include "Library/JavascriptExceptionMetadata.h"
  7. #include "Common/ByteSwap.h"
  8. #include "Library/DataView.h"
  9. #if ENABLE_TTD
  10. namespace TTD
  11. {
  12. namespace NSLogEvents
  13. {
  14. bool IsJsRTActionRootCall(const EventLogEntry* evt)
  15. {
  16. if(evt->EventKind != NSLogEvents::EventKind::CallExistingFunctionActionTag)
  17. {
  18. return false;
  19. }
  20. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  21. return cfAction->CallbackDepth == 0;
  22. }
  23. int64 AccessTimeInRootCallOrSnapshot(const EventLogEntry* evt, bool& isSnap, bool& isRoot, bool& hasRtrSnap)
  24. {
  25. isSnap = false;
  26. isRoot = false;
  27. hasRtrSnap = false;
  28. if(evt->EventKind == NSLogEvents::EventKind::SnapshotTag)
  29. {
  30. const NSLogEvents::SnapshotEventLogEntry* snapEvent = NSLogEvents::GetInlineEventDataAs<NSLogEvents::SnapshotEventLogEntry, NSLogEvents::EventKind::SnapshotTag>(evt);
  31. isSnap = true;
  32. return snapEvent->RestoreTimestamp;
  33. }
  34. else if(NSLogEvents::IsJsRTActionRootCall(evt))
  35. {
  36. const NSLogEvents::JsRTCallFunctionAction* rootEntry = NSLogEvents::GetInlineEventDataAs<NSLogEvents::JsRTCallFunctionAction, NSLogEvents::EventKind::CallExistingFunctionActionTag>(evt);
  37. isRoot = true;
  38. hasRtrSnap = (rootEntry->AdditionalReplayInfo != nullptr && rootEntry->AdditionalReplayInfo->RtRSnap != nullptr);
  39. return rootEntry->CallEventTime;
  40. }
  41. else
  42. {
  43. return -1;
  44. }
  45. }
  46. bool TryGetTimeFromRootCallOrSnapshot(const EventLogEntry* evt, int64& res)
  47. {
  48. bool isSnap = false;
  49. bool isRoot = false;
  50. bool hasRtrSnap = false;
  51. res = AccessTimeInRootCallOrSnapshot(evt, isSnap, isRoot, hasRtrSnap);
  52. return (isSnap | isRoot);
  53. }
  54. int64 GetTimeFromRootCallOrSnapshot(const EventLogEntry* evt)
  55. {
  56. int64 res = -1;
  57. bool success = TryGetTimeFromRootCallOrSnapshot(evt, res);
  58. TTDAssert(success, "Not a root or snapshot!!!");
  59. return res;
  60. }
  61. void CreateScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  62. {
  63. const JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  64. Js::ScriptContext* resCtx = nullptr;
  65. executeContext->TTDExternalObjectFunctions.pfCreateJsRTContextCallback(executeContext->GetRuntimeHandle(), &resCtx);
  66. TTDAssert(resCtx != nullptr, "Create failed");
  67. executeContext->AddRootRef_Replay(cAction->GlobalObject, resCtx->GetGlobalObject());
  68. resCtx->ScriptContextLogTag = cAction->GlobalObject;
  69. executeContext->AddRootRef_Replay(cAction->KnownObjects->UndefinedObject, resCtx->GetLibrary()->GetUndefined());
  70. executeContext->AddRootRef_Replay(cAction->KnownObjects->NullObject, resCtx->GetLibrary()->GetNull());
  71. executeContext->AddRootRef_Replay(cAction->KnownObjects->TrueObject, resCtx->GetLibrary()->GetTrue());
  72. executeContext->AddRootRef_Replay(cAction->KnownObjects->FalseObject, resCtx->GetLibrary()->GetFalse());
  73. }
  74. void CreateScriptContext_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  75. {
  76. JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  77. alloc.UnlinkAllocation(cAction->KnownObjects);
  78. }
  79. void CreateScriptContext_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  80. {
  81. const JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  82. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  83. writer->WriteLogTag(NSTokens::Key::logTag, cAction->GlobalObject, NSTokens::Separator::NoSeparator);
  84. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->UndefinedObject, NSTokens::Separator::CommaSeparator);
  85. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->NullObject, NSTokens::Separator::CommaSeparator);
  86. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->TrueObject, NSTokens::Separator::CommaSeparator);
  87. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->FalseObject, NSTokens::Separator::CommaSeparator);
  88. writer->WriteSequenceEnd();
  89. }
  90. void CreateScriptContext_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  91. {
  92. JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  93. cAction->KnownObjects = alloc.SlabAllocateStruct<JsRTCreateScriptContextAction_KnownObjects>();
  94. reader->ReadSequenceStart_WDefaultKey(true);
  95. cAction->GlobalObject = reader->ReadLogTag(NSTokens::Key::logTag, false);
  96. cAction->KnownObjects->UndefinedObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  97. cAction->KnownObjects->NullObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  98. cAction->KnownObjects->TrueObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  99. cAction->KnownObjects->FalseObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  100. reader->ReadSequenceEnd();
  101. }
  102. void SetActiveScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  103. {
  104. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::SetActiveScriptContextActionTag>(evt);
  105. Js::Var gvar = InflateVarInReplay(executeContext, GetVarItem_0(action));
  106. TTDAssert(gvar == nullptr || Js::GlobalObject::Is(gvar), "Something is not right here!");
  107. Js::GlobalObject* gobj = static_cast<Js::GlobalObject*>(gvar);
  108. Js::ScriptContext* newCtx = (gobj != nullptr) ? gobj->GetScriptContext() : nullptr;
  109. executeContext->TTDExternalObjectFunctions.pfSetActiveJsRTContext(executeContext->GetRuntimeHandle(), newCtx);
  110. }
  111. #if !INT32VAR
  112. void CreateInt_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  113. {
  114. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  115. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::CreateIntegerActionTag>(evt);
  116. Js::Var res = Js::JavascriptNumber::ToVar((int32)action->Scalar, ctx);
  117. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::CreateIntegerActionTag>(executeContext, evt, res);
  118. }
  119. #endif
  120. void CreateNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  121. {
  122. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  123. const JsRTDoubleArgumentAction* action = GetInlineEventDataAs<JsRTDoubleArgumentAction, EventKind::CreateNumberActionTag>(evt);
  124. Js::Var res = Js::JavascriptNumber::ToVarNoCheck(action->DoubleValue, ctx);
  125. JsRTActionHandleResultForReplay<JsRTDoubleArgumentAction, EventKind::CreateNumberActionTag>(executeContext, evt, res);
  126. }
  127. void CreateBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  128. {
  129. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  130. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::CreateBooleanActionTag>(evt);
  131. Js::Var res = action->Scalar ? ctx->GetLibrary()->GetTrue() : ctx->GetLibrary()->GetFalse();
  132. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::CreateBooleanActionTag>(executeContext, evt, res);
  133. }
  134. void CreateString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  135. {
  136. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  137. const JsRTStringArgumentAction* action = GetInlineEventDataAs<JsRTStringArgumentAction, EventKind::CreateStringActionTag>(evt);
  138. Js::Var res = Js::JavascriptString::NewCopyBuffer(action->StringValue.Contents, action->StringValue.Length, ctx);
  139. JsRTActionHandleResultForReplay<JsRTStringArgumentAction, EventKind::CreateStringActionTag>(executeContext, evt, res);
  140. }
  141. void CreateSymbol_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  142. {
  143. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  144. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::CreateSymbolActionTag>(evt);
  145. Js::Var description = InflateVarInReplay(executeContext, GetVarItem_0(action));
  146. Js::JavascriptString* descriptionString;
  147. if(description != nullptr)
  148. {
  149. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(description, ctx);
  150. descriptionString = Js::JavascriptConversion::ToString(description, ctx);
  151. }
  152. else
  153. {
  154. descriptionString = ctx->GetLibrary()->GetEmptyString();
  155. }
  156. Js::Var res = ctx->GetLibrary()->CreateSymbol(descriptionString);
  157. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::CreateSymbolActionTag>(executeContext, evt, res);
  158. }
  159. void Execute_CreateErrorHelper(const JsRTSingleVarArgumentAction* errorData, ThreadContextTTD* executeContext, Js::ScriptContext* ctx, EventKind eventKind, Js::Var* res)
  160. {
  161. Js::Var message = InflateVarInReplay(executeContext, GetVarItem_0(errorData));
  162. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(message, ctx);
  163. *res = nullptr;
  164. switch(eventKind)
  165. {
  166. case EventKind::CreateErrorActionTag:
  167. *res = ctx->GetLibrary()->CreateError();
  168. break;
  169. case EventKind::CreateRangeErrorActionTag:
  170. *res = ctx->GetLibrary()->CreateRangeError();
  171. break;
  172. case EventKind::CreateReferenceErrorActionTag:
  173. *res = ctx->GetLibrary()->CreateReferenceError();
  174. break;
  175. case EventKind::CreateSyntaxErrorActionTag:
  176. *res = ctx->GetLibrary()->CreateSyntaxError();
  177. break;
  178. case EventKind::CreateTypeErrorActionTag:
  179. *res = ctx->GetLibrary()->CreateTypeError();
  180. break;
  181. case EventKind::CreateURIErrorActionTag:
  182. *res = ctx->GetLibrary()->CreateURIError();
  183. break;
  184. default:
  185. TTDAssert(false, "Missing error kind!!!");
  186. }
  187. Js::JavascriptOperators::OP_SetProperty(*res, Js::PropertyIds::message, message, ctx);
  188. }
  189. void VarConvertToNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  190. {
  191. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  192. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToNumberActionTag>(evt);
  193. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  194. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  195. Js::Var res = Js::JavascriptOperators::ToNumber(var, ctx);
  196. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToNumberActionTag>(executeContext, evt, res);
  197. }
  198. void VarConvertToBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  199. {
  200. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  201. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToBooleanActionTag>(evt);
  202. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  203. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  204. Js::JavascriptConversion::ToBool(var, ctx) ? ctx->GetLibrary()->GetTrue() : ctx->GetLibrary()->GetFalse();
  205. //It is either true or false which we always track so no need to do result mapping
  206. }
  207. void VarConvertToString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  208. {
  209. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  210. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToStringActionTag>(evt);
  211. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  212. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  213. Js::Var res = Js::JavascriptConversion::ToString(var, ctx);
  214. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToStringActionTag>(executeContext, evt, res);
  215. }
  216. void VarConvertToObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  217. {
  218. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  219. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToObjectActionTag>(evt);
  220. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  221. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  222. Js::Var res = Js::JavascriptOperators::ToObject(var, ctx);
  223. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  224. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToObjectActionTag>(executeContext, evt, res);
  225. }
  226. void AddRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  227. {
  228. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AddRootRefActionTag>(evt);
  229. TTD_LOG_PTR_ID origId = reinterpret_cast<TTD_LOG_PTR_ID>(GetVarItem_0(action));
  230. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  231. Js::RecyclableObject* newObj = Js::RecyclableObject::FromVar(var);
  232. executeContext->AddRootRef_Replay(origId, newObj);
  233. }
  234. void AddWeakRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  235. {
  236. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AddWeakRootRefActionTag>(evt);
  237. TTD_LOG_PTR_ID origId = reinterpret_cast<TTD_LOG_PTR_ID>(GetVarItem_0(action));
  238. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  239. Js::RecyclableObject* newObj = Js::RecyclableObject::FromVar(var);
  240. executeContext->AddRootRef_Replay(origId, newObj);
  241. }
  242. void AllocateObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  243. {
  244. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  245. Js::RecyclableObject* res = ctx->GetLibrary()->CreateObject();
  246. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::AllocateObjectActionTag>(executeContext, evt, res);
  247. }
  248. void AllocateExternalObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  249. {
  250. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  251. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AllocateExternalObjectActionTag>(evt);
  252. Js::Var prototype = InflateVarInReplay(executeContext, GetVarItem_0(action));
  253. Js::Var res = nullptr;
  254. executeContext->TTDExternalObjectFunctions.pfCreateExternalObject(ctx, prototype, &res);
  255. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::AllocateExternalObjectActionTag>(executeContext, evt, res);
  256. }
  257. void AllocateArrayAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  258. {
  259. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  260. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::AllocateArrayActionTag>(evt);
  261. Js::Var res = ctx->GetLibrary()->CreateArray((uint32)action->Scalar);
  262. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::AllocateArrayActionTag>(executeContext, evt, res);
  263. }
  264. void AllocateArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  265. {
  266. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  267. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::AllocateArrayBufferActionTag>(evt);
  268. Js::ArrayBuffer* abuff = ctx->GetLibrary()->CreateArrayBuffer((uint32)action->Scalar);
  269. TTDAssert(abuff->GetByteLength() == (uint32)action->Scalar, "Something is wrong with our sizes.");
  270. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::AllocateArrayBufferActionTag>(executeContext, evt, (Js::Var)abuff);
  271. }
  272. void AllocateExternalArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  273. {
  274. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  275. const JsRTByteBufferAction* action = GetInlineEventDataAs<JsRTByteBufferAction, EventKind::AllocateExternalArrayBufferActionTag>(evt);
  276. Js::ArrayBuffer* abuff = ctx->GetLibrary()->CreateArrayBuffer(action->Length);
  277. TTDAssert(abuff->GetByteLength() == action->Length, "Something is wrong with our sizes.");
  278. if(action->Length != 0)
  279. {
  280. js_memcpy_s(abuff->GetBuffer(), abuff->GetByteLength(), action->Buffer, action->Length);
  281. }
  282. JsRTActionHandleResultForReplay<JsRTByteBufferAction, EventKind::AllocateExternalArrayBufferActionTag>(executeContext, evt, (Js::Var)abuff);
  283. }
  284. void AllocateFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  285. {
  286. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  287. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AllocateFunctionActionTag>(evt);
  288. Js::Var metadata = InflateVarInReplay(executeContext, GetVarItem_0(action));
  289. Js::JavascriptString* name = nullptr;
  290. if(metadata != nullptr)
  291. {
  292. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(metadata, ctx);
  293. name = Js::JavascriptConversion::ToString(metadata, ctx);
  294. }
  295. else
  296. {
  297. name = ctx->GetLibrary()->GetEmptyString();
  298. }
  299. Js::Var res = ctx->GetLibrary()->CreateStdCallExternalFunction(&Js::JavascriptExternalFunction::TTDReplayDummyExternalMethod, name, nullptr);
  300. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::AllocateFunctionActionTag>(executeContext, evt, res);
  301. }
  302. void HostProcessExitAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  303. {
  304. throw TTDebuggerAbortException::CreateAbortEndOfLog(_u("End of log reached with Host Process Exit -- returning to top-level."));
  305. }
  306. void GetAndClearExceptionWithMetadataAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  307. {
  308. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  309. HRESULT hr = S_OK;
  310. Js::JavascriptExceptionObject *recordedException = nullptr;
  311. BEGIN_TRANSLATE_OOM_TO_HRESULT
  312. if (ctx->HasRecordedException())
  313. {
  314. recordedException = ctx->GetAndClearRecordedException();
  315. }
  316. END_TRANSLATE_OOM_TO_HRESULT(hr)
  317. Js::Var exception = nullptr;
  318. if (recordedException != nullptr)
  319. {
  320. exception = recordedException->GetThrownObject(nullptr);
  321. }
  322. if (exception != nullptr)
  323. {
  324. Js::ScriptContext * scriptContext = executeContext->GetActiveScriptContext();
  325. Js::Var exceptionMetadata = Js::JavascriptExceptionMetadata::CreateMetadataVar(scriptContext);
  326. Js::FunctionBody *functionBody = recordedException->GetFunctionBody();
  327. Js::JavascriptOperators::OP_SetProperty(exceptionMetadata, Js::PropertyIds::exception, exception, scriptContext);
  328. if (functionBody == nullptr)
  329. {
  330. // This is probably a parse error. We can get the error location metadata from the thrown object.
  331. Js::JavascriptExceptionMetadata::PopulateMetadataFromCompileException(exceptionMetadata, exception, scriptContext);
  332. }
  333. else
  334. {
  335. if (!Js::JavascriptExceptionMetadata::PopulateMetadataFromException(exceptionMetadata, recordedException, scriptContext))
  336. {
  337. return;
  338. }
  339. }
  340. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::GetAndClearExceptionWithMetadataActionTag>(executeContext, evt, exceptionMetadata);
  341. }
  342. }
  343. void GetAndClearExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  344. {
  345. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  346. HRESULT hr = S_OK;
  347. Js::JavascriptExceptionObject *recordedException = nullptr;
  348. BEGIN_TRANSLATE_OOM_TO_HRESULT
  349. if (ctx->HasRecordedException())
  350. {
  351. recordedException = ctx->GetAndClearRecordedException();
  352. }
  353. END_TRANSLATE_OOM_TO_HRESULT(hr)
  354. Js::Var exception = nullptr;
  355. if(recordedException != nullptr)
  356. {
  357. exception = recordedException->GetThrownObject(nullptr);
  358. }
  359. if(exception != nullptr)
  360. {
  361. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::GetAndClearExceptionActionTag>(executeContext, evt, exception);
  362. }
  363. }
  364. void SetExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  365. {
  366. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  367. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::SetExceptionActionTag>(evt);
  368. Js::Var exception = InflateVarInReplay(executeContext, GetVarItem_0(action));
  369. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(exception, ctx);
  370. bool propagateToDebugger = GetScalarItem_0(action) ? true : false;
  371. Js::JavascriptExceptionObject *exceptionObject;
  372. exceptionObject = RecyclerNew(ctx->GetRecycler(), Js::JavascriptExceptionObject, exception, ctx, nullptr);
  373. ctx->RecordException(exceptionObject, propagateToDebugger);
  374. }
  375. void HasPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  376. {
  377. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  378. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::HasPropertyActionTag>(evt);
  379. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  380. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  381. //Result is not needed but trigger computation for any effects
  382. Js::JavascriptOperators::OP_HasProperty(var, GetPropertyIdItem(action), ctx);
  383. }
  384. void HasOwnPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  385. {
  386. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  387. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::HasOwnPropertyActionTag>(evt);
  388. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  389. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  390. //Result is not needed but trigger computation for any effects
  391. Js::JavascriptOperators::OP_HasOwnProperty(var, GetPropertyIdItem(action), ctx);
  392. }
  393. void InstanceOfAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  394. {
  395. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  396. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::InstanceOfActionTag>(evt);
  397. Js::Var object = InflateVarInReplay(executeContext, GetVarItem_0(action));
  398. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object, ctx);
  399. Js::Var constructor = InflateVarInReplay(executeContext, GetVarItem_1(action));
  400. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(constructor, ctx);
  401. //Result is not needed but trigger computation for any effects
  402. Js::RecyclableObject::FromVar(constructor)->HasInstance(object, ctx);
  403. }
  404. void EqualsAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  405. {
  406. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  407. const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::EqualsActionTag>(evt);
  408. Js::Var object1 = InflateVarInReplay(executeContext, GetVarItem_0(action));
  409. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object1, ctx);
  410. Js::Var object2 = InflateVarInReplay(executeContext, GetVarItem_1(action));
  411. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object2, ctx);
  412. //Result is not needed but trigger computation for any effects
  413. if(GetScalarItem_0(action))
  414. {
  415. Js::JavascriptOperators::StrictEqual(object1, object2, ctx);
  416. }
  417. else
  418. {
  419. Js::JavascriptOperators::Equal(object1, object2, ctx);
  420. }
  421. }
  422. void LessThanAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  423. {
  424. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  425. const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::LessThanActionTag>(evt);
  426. Js::Var object1 = InflateVarInReplay(executeContext, GetVarItem_0(action));
  427. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object1, ctx);
  428. Js::Var object2 = InflateVarInReplay(executeContext, GetVarItem_1(action));
  429. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object2, ctx);
  430. //Result is not needed but trigger computation for any effects
  431. if (GetScalarItem_0(action))
  432. {
  433. Js::JavascriptOperators::LessEqual(object1, object2, ctx);
  434. }
  435. else
  436. {
  437. Js::JavascriptOperators::Less(object1, object2, ctx);
  438. }
  439. }
  440. void GetPropertyIdFromSymbolAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  441. {
  442. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  443. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetPropertyIdFromSymbolTag>(evt);
  444. Js::Var sym = InflateVarInReplay(executeContext, GetVarItem_0(action));
  445. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(sym, ctx);
  446. //These really don't have any effect, we need the marshal in validate, so just skip since Js::JavascriptSymbol has strange declaration order
  447. //
  448. //if(!Js::JavascriptSymbol::Is(sym))
  449. //{
  450. // return JsErrorPropertyNotSymbol;
  451. //}
  452. //
  453. //Js::JavascriptSymbol::FromVar(symbol)->GetValue();
  454. }
  455. void GetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  456. {
  457. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  458. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetPrototypeActionTag>(evt);
  459. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  460. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  461. Js::Var res = Js::JavascriptOperators::OP_GetPrototype(var,ctx);
  462. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  463. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetPrototypeActionTag>(executeContext, evt, res);
  464. }
  465. void GetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  466. {
  467. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  468. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::GetPropertyActionTag>(evt);
  469. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  470. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  471. Js::Var res = Js::JavascriptOperators::OP_GetProperty(var, GetPropertyIdItem(action), ctx);
  472. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  473. JsRTActionHandleResultForReplay<JsRTSingleVarScalarArgumentAction, EventKind::GetPropertyActionTag>(executeContext, evt, res);
  474. }
  475. void GetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  476. {
  477. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  478. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::GetIndexActionTag>(evt);
  479. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  480. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  481. Js::Var index = InflateVarInReplay(executeContext, GetVarItem_1(action));
  482. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(index, ctx);
  483. Js::Var res = Js::JavascriptOperators::OP_GetElementI(var, index, ctx);
  484. JsRTActionHandleResultForReplay<JsRTDoubleVarArgumentAction, EventKind::GetIndexActionTag>(executeContext, evt, res);
  485. }
  486. void GetOwnPropertyInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  487. {
  488. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  489. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::GetOwnPropertyInfoActionTag>(evt);
  490. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  491. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  492. Js::Var res = nullptr;
  493. Js::PropertyDescriptor propertyDescriptorValue;
  494. if(Js::JavascriptOperators::GetOwnPropertyDescriptor(Js::RecyclableObject::FromVar(var), GetPropertyIdItem(action), ctx, &propertyDescriptorValue))
  495. {
  496. res = Js::JavascriptOperators::FromPropertyDescriptor(propertyDescriptorValue, ctx);
  497. }
  498. else
  499. {
  500. res = ctx->GetLibrary()->GetUndefined();
  501. }
  502. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  503. JsRTActionHandleResultForReplay<JsRTSingleVarScalarArgumentAction, EventKind::GetOwnPropertyInfoActionTag>(executeContext, evt, res);
  504. }
  505. void GetOwnPropertyNamesInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  506. {
  507. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  508. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertyNamesInfoActionTag>(evt);
  509. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  510. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  511. Js::JavascriptArray* res = Js::JavascriptOperators::GetOwnPropertyNames(var, ctx);
  512. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  513. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertyNamesInfoActionTag>(executeContext, evt, res);
  514. }
  515. void GetOwnPropertySymbolsInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  516. {
  517. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  518. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertySymbolsInfoActionTag>(evt);
  519. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  520. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  521. Js::JavascriptArray* res = Js::JavascriptOperators::GetOwnPropertySymbols(var, ctx);
  522. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  523. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertySymbolsInfoActionTag>(executeContext, evt, res);
  524. }
  525. void DefinePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  526. {
  527. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  528. const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::DefinePropertyActionTag>(evt);
  529. Js::Var object = InflateVarInReplay(executeContext, GetVarItem_0(action));
  530. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(object, ctx);
  531. Js::Var propertyDescriptor = InflateVarInReplay(executeContext, GetVarItem_1(action));
  532. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(propertyDescriptor, ctx);
  533. Js::PropertyDescriptor propertyDescriptorValue;
  534. Js::JavascriptOperators::ToPropertyDescriptor(propertyDescriptor, &propertyDescriptorValue, ctx);
  535. Js::JavascriptOperators::DefineOwnPropertyDescriptor(Js::RecyclableObject::FromVar(object), GetPropertyIdItem(action), propertyDescriptorValue, true, ctx);
  536. }
  537. void DeletePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  538. {
  539. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  540. const JsRTSingleVarDoubleScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarDoubleScalarArgumentAction, EventKind::DeletePropertyActionTag>(evt);
  541. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  542. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  543. Js::Var res = Js::JavascriptOperators::OP_DeleteProperty(var, GetPropertyIdItem(action), ctx, GetScalarItem_1(action) ? Js::PropertyOperation_StrictMode : Js::PropertyOperation_None);
  544. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  545. JsRTActionHandleResultForReplay<JsRTSingleVarDoubleScalarArgumentAction, EventKind::DeletePropertyActionTag>(executeContext, evt, res);
  546. }
  547. void SetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  548. {
  549. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  550. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::SetPrototypeActionTag>(evt);
  551. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  552. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  553. Js::Var proto = InflateVarInReplay(executeContext, GetVarItem_1(action));
  554. TTD_REPLAY_VALIDATE_INCOMING_OBJECT_OR_NULL(proto, ctx);
  555. Js::JavascriptObject::ChangePrototype(Js::RecyclableObject::FromVar(var), Js::RecyclableObject::FromVar(proto), true, ctx);
  556. }
  557. void SetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  558. {
  559. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  560. const JsRTDoubleVarDoubleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarDoubleScalarArgumentAction, EventKind::SetPropertyActionTag>(evt);
  561. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  562. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  563. Js::Var value = InflateVarInReplay(executeContext, GetVarItem_1(action));
  564. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(value, ctx);
  565. Js::JavascriptOperators::OP_SetProperty(var, GetPropertyIdItem(action), value, ctx, nullptr, GetScalarItem_1(action) ? Js::PropertyOperation_StrictMode : Js::PropertyOperation_None);
  566. }
  567. void SetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  568. {
  569. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  570. const JsRTTrippleVarArgumentAction* action = GetInlineEventDataAs<JsRTTrippleVarArgumentAction, EventKind::SetIndexActionTag>(evt);
  571. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  572. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  573. Js::Var index = InflateVarInReplay(executeContext, GetVarItem_1(action));
  574. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(index, ctx);
  575. Js::Var value = InflateVarInReplay(executeContext, GetVarItem_2(action));
  576. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(value, ctx);
  577. Js::JavascriptOperators::OP_SetElementI(var, index, value, ctx);
  578. }
  579. void GetTypedArrayInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  580. {
  581. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetTypedArrayInfoActionTag>(evt);
  582. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  583. Js::TypedArrayBase* typedArrayBase = Js::TypedArrayBase::FromVar(var);
  584. Js::Var res = typedArrayBase->GetArrayBuffer();
  585. //Need additional notify since JsRTActionHandleResultForReplay may allocate but GetTypedArrayInfo does not enter runtime
  586. //Failure will kick all the way out to replay loop -- which is what we want
  587. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_OutOfMemory);
  588. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetTypedArrayInfoActionTag>(executeContext, evt, res);
  589. }
  590. void GetDataViewInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  591. {
  592. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetDataViewInfoActionTag>(evt);
  593. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  594. Js::DataView* dataView = Js::DataView::FromVar(var);
  595. Js::Var res = dataView->GetArrayBuffer();
  596. //Need additional notify since JsRTActionHandleResultForReplay may allocate but GetDataViewInfo does not enter runtime
  597. //Failure will kick all the way out to replay loop -- which is what we want
  598. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_OutOfMemory);
  599. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetDataViewInfoActionTag>(executeContext, evt, res);
  600. }
  601. //////////////////
  602. void JsRTRawBufferCopyAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  603. {
  604. const JsRTRawBufferCopyAction* rbcAction = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  605. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  606. NSSnapValues::EmitTTDVar(rbcAction->Dst, writer, NSTokens::Separator::NoSeparator);
  607. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  608. NSSnapValues::EmitTTDVar(rbcAction->Src, writer, NSTokens::Separator::NoSeparator);
  609. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->DstIndx, NSTokens::Separator::CommaSeparator);
  610. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->SrcIndx, NSTokens::Separator::CommaSeparator);
  611. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->Count, NSTokens::Separator::CommaSeparator);
  612. }
  613. void JsRTRawBufferCopyAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  614. {
  615. JsRTRawBufferCopyAction* rbcAction = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  616. reader->ReadKey(NSTokens::Key::argRetVal, true);
  617. rbcAction->Dst = NSSnapValues::ParseTTDVar(false, reader);
  618. reader->ReadKey(NSTokens::Key::argRetVal, true);
  619. rbcAction->Src = NSSnapValues::ParseTTDVar(false, reader);
  620. rbcAction->DstIndx = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  621. rbcAction->SrcIndx = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  622. rbcAction->Count = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  623. }
  624. void RawBufferCopySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  625. {
  626. const JsRTRawBufferCopyAction* action = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  627. Js::Var dst = InflateVarInReplay(executeContext, action->Dst); //never cross context
  628. Js::Var src = InflateVarInReplay(executeContext, action->Src); //never cross context
  629. TTDAssert(Js::ArrayBuffer::Is(dst) && Js::ArrayBuffer::Is(src), "Not array buffer objects!!!");
  630. TTDAssert(action->DstIndx + action->Count <= Js::ArrayBuffer::FromVar(dst)->GetByteLength(), "Copy off end of buffer!!!");
  631. TTDAssert(action->SrcIndx + action->Count <= Js::ArrayBuffer::FromVar(src)->GetByteLength(), "Copy off end of buffer!!!");
  632. byte* dstBuff = Js::ArrayBuffer::FromVar(dst)->GetBuffer() + action->DstIndx;
  633. byte* srcBuff = Js::ArrayBuffer::FromVar(src)->GetBuffer() + action->SrcIndx;
  634. //node uses mmove so we do too
  635. memmove(dstBuff, srcBuff, action->Count);
  636. }
  637. void RawBufferModifySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  638. {
  639. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferModifySync>(evt);
  640. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  641. TTDAssert(Js::ArrayBuffer::Is(trgt), "Not array buffer object!!!");
  642. TTDAssert(action->Index + action->Length <= Js::ArrayBuffer::FromVar(trgt)->GetByteLength(), "Copy off end of buffer!!!");
  643. byte* trgtBuff = Js::ArrayBuffer::FromVar(trgt)->GetBuffer() + action->Index;
  644. js_memcpy_s(trgtBuff, action->Length, action->Data, action->Length);
  645. }
  646. void RawBufferAsyncModificationRegister_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  647. {
  648. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  649. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferAsyncModificationRegister>(evt);
  650. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  651. ctx->TTDContextInfo->AddToAsyncPendingList(Js::ArrayBuffer::FromVar(trgt), action->Index);
  652. }
  653. void RawBufferAsyncModifyComplete_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  654. {
  655. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  656. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferAsyncModifyComplete>(evt);
  657. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  658. const Js::ArrayBuffer* dstBuff = Js::ArrayBuffer::FromVar(trgt);
  659. byte* copyBuff = dstBuff->GetBuffer() + action->Index;
  660. byte* finalModPos = dstBuff->GetBuffer() + action->Index + action->Length;
  661. TTDPendingAsyncBufferModification pendingAsyncInfo = { 0 };
  662. ctx->TTDContextInfo->GetFromAsyncPendingList(&pendingAsyncInfo, finalModPos);
  663. TTDAssert(dstBuff == pendingAsyncInfo.ArrayBufferVar && action->Index == pendingAsyncInfo.Index, "Something is not right.");
  664. js_memcpy_s(copyBuff, action->Length, action->Data, action->Length);
  665. }
  666. //////////////////
  667. void JsRTConstructCallAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  668. {
  669. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  670. const JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  671. Js::Var jsFunctionVar = InflateVarInReplay(executeContext, ccAction->ArgArray[0]);
  672. TTD_REPLAY_VALIDATE_INCOMING_FUNCTION(jsFunctionVar, ctx);
  673. //remove implicit constructor function as first arg in callInfo and argument loop below
  674. for(uint32 i = 1; i < ccAction->ArgCount; ++i)
  675. {
  676. Js::Var argi = InflateVarInReplay(executeContext, ccAction->ArgArray[i]);
  677. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(argi, ctx);
  678. ccAction->ExecArgs[i - 1] = argi;
  679. }
  680. Js::JavascriptFunction* jsFunction = Js::JavascriptFunction::FromVar(jsFunctionVar);
  681. Js::CallInfo callInfo(Js::CallFlags::CallFlags_New, (ushort)(ccAction->ArgCount - 1));
  682. Js::Arguments jsArgs(callInfo, ccAction->ExecArgs);
  683. //
  684. //TODO: we will want to look at this at some point -- either treat as "top-level" call or maybe constructors are fast so we can just jump back to previous "real" code
  685. //TTDAssert(!Js::ScriptFunction::Is(jsFunction) || execContext->GetThreadContext()->TTDRootNestingCount != 0, "This will cause user code to execute and we need to add support for that as a top-level call source!!!!");
  686. //
  687. Js::Var res = Js::JavascriptFunction::CallAsConstructor(jsFunction, /* overridingNewTarget = */nullptr, jsArgs, ctx);
  688. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  689. JsRTActionHandleResultForReplay<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(executeContext, evt, res);
  690. }
  691. void JsRTConstructCallAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  692. {
  693. JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  694. if(ccAction->ArgArray != nullptr)
  695. {
  696. alloc.UnlinkAllocation(ccAction->ArgArray);
  697. }
  698. if(ccAction->ExecArgs != nullptr)
  699. {
  700. alloc.UnlinkAllocation(ccAction->ExecArgs);
  701. }
  702. }
  703. void JsRTConstructCallAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  704. {
  705. const JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  706. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  707. NSSnapValues::EmitTTDVar(ccAction->Result, writer, NSTokens::Separator::NoSeparator);
  708. writer->WriteLengthValue(ccAction->ArgCount, NSTokens::Separator::CommaSeparator);
  709. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  710. for(uint32 i = 0; i < ccAction->ArgCount; ++i)
  711. {
  712. NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
  713. NSSnapValues::EmitTTDVar(ccAction->ArgArray[i], writer, sep);
  714. }
  715. writer->WriteSequenceEnd();
  716. }
  717. void JsRTConstructCallAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  718. {
  719. JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  720. reader->ReadKey(NSTokens::Key::argRetVal, true);
  721. ccAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  722. ccAction->ArgCount = reader->ReadLengthValue(true);
  723. ccAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(ccAction->ArgCount);
  724. reader->ReadSequenceStart_WDefaultKey(true);
  725. for(uint32 i = 0; i < ccAction->ArgCount; ++i)
  726. {
  727. ccAction->ArgArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
  728. }
  729. reader->ReadSequenceEnd();
  730. ccAction->ExecArgs = (ccAction->ArgCount > 1) ? alloc.SlabAllocateArray<Js::Var>(ccAction->ArgCount - 1) : nullptr; //ArgCount includes slot for function which we don't use in exec
  731. }
  732. void JsRTCodeParseAction_SetBodyCtrId(EventLogEntry* parseEvent, uint32 bodyCtrId)
  733. {
  734. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(parseEvent);
  735. cpAction->BodyCtrId = bodyCtrId;
  736. }
  737. void JsRTCodeParseAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  738. {
  739. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  740. const JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  741. Js::JavascriptFunction* function = nullptr;
  742. byte* script = cpAction->SourceCode;
  743. uint32 scriptByteLength = cpAction->SourceByteLength;
  744. TTDAssert(cpAction->IsUtf8 == ((cpAction->LoadFlag & LoadScriptFlag_Utf8Source) == LoadScriptFlag_Utf8Source), "Utf8 status is inconsistent!!!");
  745. SourceContextInfo * sourceContextInfo = ctx->GetSourceContextInfo((DWORD_PTR)cpAction->SourceContextId, nullptr);
  746. if(sourceContextInfo == nullptr)
  747. {
  748. const char16* srcUri = cpAction->SourceUri.Contents;
  749. uint32 srcUriLength = cpAction->SourceUri.Length;
  750. sourceContextInfo = ctx->CreateSourceContextInfo((DWORD_PTR)cpAction->SourceContextId, srcUri, srcUriLength, nullptr);
  751. }
  752. TTDAssert(cpAction->IsUtf8 || sizeof(wchar) == sizeof(char16), "Non-utf8 code only allowed on windows!!!");
  753. const int chsize = (cpAction->LoadFlag & LoadScriptFlag_Utf8Source) ? sizeof(char) : sizeof(char16);
  754. SRCINFO si = {
  755. /* sourceContextInfo */ sourceContextInfo,
  756. /* dlnHost */ 0,
  757. /* ulColumnHost */ 0,
  758. /* lnMinHost */ 0,
  759. /* ichMinHost */ 0,
  760. /* ichLimHost */ static_cast<ULONG>(scriptByteLength / chsize), // OK to truncate since this is used to limit sourceText in debugDocument/compilation errors.
  761. /* ulCharOffset */ 0,
  762. /* mod */ kmodGlobal,
  763. /* grfsi */ 0
  764. };
  765. Js::Utf8SourceInfo* utf8SourceInfo = nullptr;
  766. CompileScriptException se;
  767. function = ctx->LoadScript(script, scriptByteLength, &si, &se,
  768. &utf8SourceInfo, Js::Constants::GlobalCode, cpAction->LoadFlag, nullptr);
  769. TTDAssert(function != nullptr, "Something went wrong");
  770. Js::FunctionBody* fb = TTD::JsSupport::ForceAndGetFunctionBody(function->GetParseableFunctionInfo());
  771. ////
  772. //We don't do this automatically in the eval helper so do it here
  773. BEGIN_JS_RUNTIME_CALL(ctx);
  774. {
  775. ctx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
  776. ctx->TTDContextInfo->RegisterLoadedScript(fb, cpAction->BodyCtrId);
  777. fb->GetUtf8SourceInfo()->SetSourceInfoForDebugReplay_TTD(cpAction->BodyCtrId);
  778. }
  779. END_JS_RUNTIME_CALL(ctx);
  780. if(ctx->ShouldPerformReplayDebuggerAction())
  781. {
  782. ctx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad(ctx, cpAction->BodyCtrId, fb, utf8SourceInfo, &se);
  783. }
  784. ////
  785. JsRTActionHandleResultForReplay<JsRTCodeParseAction, EventKind::CodeParseActionTag>(executeContext, evt, (Js::Var)function);
  786. }
  787. void JsRTCodeParseAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  788. {
  789. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  790. alloc.UnlinkAllocation(cpAction->SourceCode);
  791. if(!IsNullPtrTTString(cpAction->SourceUri))
  792. {
  793. alloc.UnlinkString(cpAction->SourceUri);
  794. }
  795. }
  796. void JsRTCodeParseAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  797. {
  798. const JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  799. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  800. NSSnapValues::EmitTTDVar(cpAction->Result, writer, NSTokens::Separator::NoSeparator);
  801. writer->WriteUInt64(NSTokens::Key::sourceContextId, cpAction->SourceContextId, NSTokens::Separator::CommaSeparator);
  802. writer->WriteTag<LoadScriptFlag>(NSTokens::Key::loadFlag, cpAction->LoadFlag, NSTokens::Separator::CommaSeparator);
  803. writer->WriteUInt32(NSTokens::Key::bodyCounterId, cpAction->BodyCtrId, NSTokens::Separator::CommaSeparator);
  804. writer->WriteString(NSTokens::Key::uri, cpAction->SourceUri, NSTokens::Separator::CommaSeparator);
  805. writer->WriteBool(NSTokens::Key::boolVal, cpAction->IsUtf8, NSTokens::Separator::CommaSeparator);
  806. writer->WriteLengthValue(cpAction->SourceByteLength, NSTokens::Separator::CommaSeparator);
  807. JsSupport::WriteCodeToFile(threadContext, true, cpAction->BodyCtrId, cpAction->IsUtf8, cpAction->SourceCode, cpAction->SourceByteLength);
  808. }
  809. void JsRTCodeParseAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  810. {
  811. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  812. reader->ReadKey(NSTokens::Key::argRetVal, true);
  813. cpAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  814. cpAction->SourceContextId = reader->ReadUInt64(NSTokens::Key::sourceContextId, true);
  815. cpAction->LoadFlag = reader->ReadTag<LoadScriptFlag>(NSTokens::Key::loadFlag, true);
  816. cpAction->BodyCtrId = reader->ReadUInt32(NSTokens::Key::bodyCounterId, true);
  817. reader->ReadString(NSTokens::Key::uri, alloc, cpAction->SourceUri, true);
  818. cpAction->IsUtf8 = reader->ReadBool(NSTokens::Key::boolVal, true);
  819. cpAction->SourceByteLength = reader->ReadLengthValue(true);
  820. cpAction->SourceCode = alloc.SlabAllocateArray<byte>(cpAction->SourceByteLength);
  821. JsSupport::ReadCodeFromFile(threadContext, true, cpAction->BodyCtrId, cpAction->IsUtf8, cpAction->SourceCode, cpAction->SourceByteLength);
  822. }
  823. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  824. int64 JsRTCallFunctionAction_GetLastNestedEventTime(const EventLogEntry* evt)
  825. {
  826. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  827. return cfAction->LastNestedEvent;
  828. }
  829. void JsRTCallFunctionAction_ProcessDiagInfoPre(EventLogEntry* evt, Js::Var funcVar, UnlinkableSlabAllocator& alloc)
  830. {
  831. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  832. if(Js::JavascriptFunction::Is(funcVar))
  833. {
  834. Js::JavascriptString* displayName = Js::JavascriptFunction::FromVar(funcVar)->GetDisplayName();
  835. alloc.CopyStringIntoWLength(displayName->GetSz(), displayName->GetLength(), cfAction->FunctionName);
  836. }
  837. else
  838. {
  839. alloc.CopyNullTermStringInto(_u("#not a function#"), cfAction->FunctionName);
  840. }
  841. //In case we don't terminate add these nicely
  842. cfAction->LastNestedEvent = TTD_EVENT_MAXTIME;
  843. }
  844. void JsRTCallFunctionAction_ProcessDiagInfoPost(EventLogEntry* evt, int64 lastNestedEvent)
  845. {
  846. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  847. cfAction->LastNestedEvent = lastNestedEvent;
  848. }
  849. #endif
  850. void JsRTCallFunctionAction_ProcessArgs(EventLogEntry* evt, int32 rootDepth, int64 callEventTime, Js::Var funcVar, uint32 argc, Js::Var* argv, int64 topLevelCallbackEventTime, UnlinkableSlabAllocator& alloc)
  851. {
  852. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  853. cfAction->CallbackDepth = rootDepth;
  854. cfAction->ArgCount = argc + 1;
  855. static_assert(sizeof(TTDVar) == sizeof(Js::Var), "These need to be the same size (and have same bit layout) for this to work!");
  856. cfAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(cfAction->ArgCount);
  857. cfAction->ArgArray[0] = TTD_CONVERT_JSVAR_TO_TTDVAR(funcVar);
  858. js_memcpy_s(cfAction->ArgArray + 1, (cfAction->ArgCount -1) * sizeof(TTDVar), argv, argc * sizeof(Js::Var));
  859. cfAction->CallEventTime = callEventTime;
  860. cfAction->TopLevelCallbackEventTime = topLevelCallbackEventTime;
  861. cfAction->AdditionalReplayInfo = nullptr;
  862. //Result is initialized when we register this with the popper
  863. }
  864. void JsRTCallFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  865. {
  866. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  867. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  868. ThreadContext* threadContext = ctx->GetThreadContext();
  869. Js::Var jsFunctionVar = InflateVarInReplay(executeContext, cfAction->ArgArray[0]);
  870. TTD_REPLAY_VALIDATE_INCOMING_FUNCTION(jsFunctionVar, ctx);
  871. Js::JavascriptFunction *jsFunction = Js::JavascriptFunction::FromVar(jsFunctionVar);
  872. //remove implicit constructor function as first arg in callInfo and argument loop below
  873. Js::CallInfo callInfo((ushort)(cfAction->ArgCount - 1));
  874. for(uint32 i = 1; i < cfAction->ArgCount; ++i)
  875. {
  876. Js::Var argi = InflateVarInReplay(executeContext, cfAction->ArgArray[i]);
  877. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(argi, ctx);
  878. cfAction->AdditionalReplayInfo->ExecArgs[i - 1] = argi;
  879. }
  880. Js::Arguments jsArgs(callInfo, cfAction->AdditionalReplayInfo->ExecArgs);
  881. //If this isn't a root function then just call it -- don't need to reset anything and exceptions can just continue
  882. if(cfAction->CallbackDepth != 0)
  883. {
  884. Js::Var result = jsFunction->CallRootFunction(jsArgs, ctx, true);
  885. if(result != nullptr)
  886. {
  887. Assert(result == nullptr || !Js::CrossSite::NeedMarshalVar(result, ctx));
  888. }
  889. //since we tag in JsRT we need to tag here too
  890. JsRTActionHandleResultForReplay<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(executeContext, evt, result);
  891. TTDAssert(NSLogEvents::EventCompletesNormally(evt), "Why did we get a different completion");
  892. }
  893. else
  894. {
  895. threadContext->TTDLog->ResetCallStackForTopLevelCall(cfAction->TopLevelCallbackEventTime);
  896. if(threadContext->TTDExecutionInfo != nullptr)
  897. {
  898. threadContext->TTDExecutionInfo->ResetCallStackForTopLevelCall(cfAction->TopLevelCallbackEventTime);
  899. }
  900. try
  901. {
  902. Js::Var result = jsFunction->CallRootFunction(jsArgs, ctx, true);
  903. //since we tag in JsRT we need to tag here too
  904. JsRTActionHandleResultForReplay<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(executeContext, evt, result);
  905. TTDAssert(NSLogEvents::EventCompletesNormally(evt), "Why did we get a different completion");
  906. }
  907. catch(const Js::JavascriptException& err)
  908. {
  909. TTDAssert(NSLogEvents::EventCompletesWithException(evt), "Why did we get a different exception");
  910. if(executeContext->GetActiveScriptContext()->ShouldPerformReplayDebuggerAction())
  911. {
  912. //convert to uncaught debugger exception for host
  913. TTDebuggerSourceLocation lastLocation;
  914. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  915. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  916. err.GetAndClear(); // discard exception object
  917. //Reset any step controller logic
  918. if(ctx->GetThreadContext()->GetDebugManager() != nullptr)
  919. {
  920. ctx->GetThreadContext()->GetDebugManager()->stepController.Deactivate();
  921. }
  922. throw TTDebuggerAbortException::CreateUncaughtExceptionAbortRequest(lastLocation.GetRootEventTime(), _u("Uncaught JavaScript exception -- Propagate to top-level."));
  923. }
  924. throw;
  925. }
  926. catch(Js::ScriptAbortException)
  927. {
  928. TTDAssert(NSLogEvents::EventCompletesWithException(evt), "Why did we get a different exception");
  929. if(executeContext->GetActiveScriptContext()->ShouldPerformReplayDebuggerAction())
  930. {
  931. //convert to uncaught debugger exception for host
  932. TTDebuggerSourceLocation lastLocation;
  933. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  934. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  935. throw TTDebuggerAbortException::CreateUncaughtExceptionAbortRequest(lastLocation.GetRootEventTime(), _u("Uncaught Script exception -- Propagate to top-level."));
  936. }
  937. else
  938. {
  939. throw;
  940. }
  941. }
  942. catch(...)
  943. {
  944. if(executeContext->GetActiveScriptContext()->ShouldPerformReplayDebuggerAction())
  945. {
  946. TTDebuggerSourceLocation lastLocation;
  947. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  948. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  949. }
  950. throw;
  951. }
  952. }
  953. }
  954. void JsRTCallFunctionAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  955. {
  956. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  957. alloc.UnlinkAllocation(cfAction->ArgArray);
  958. if(cfAction->AdditionalReplayInfo != nullptr)
  959. {
  960. if(cfAction->AdditionalReplayInfo->ExecArgs != nullptr)
  961. {
  962. alloc.UnlinkAllocation(cfAction->AdditionalReplayInfo->ExecArgs);
  963. }
  964. JsRTCallFunctionAction_UnloadSnapshot(evt);
  965. if(cfAction->AdditionalReplayInfo->LastExecutedLocation.HasValue())
  966. {
  967. cfAction->AdditionalReplayInfo->LastExecutedLocation.Clear();
  968. }
  969. alloc.UnlinkAllocation(cfAction->AdditionalReplayInfo);
  970. }
  971. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  972. alloc.UnlinkString(cfAction->FunctionName);
  973. #endif
  974. }
  975. void JsRTCallFunctionAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  976. {
  977. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  978. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  979. NSSnapValues::EmitTTDVar(cfAction->Result, writer, NSTokens::Separator::NoSeparator);
  980. writer->WriteInt32(NSTokens::Key::rootNestingDepth, cfAction->CallbackDepth, NSTokens::Separator::CommaSeparator);
  981. writer->WriteLengthValue(cfAction->ArgCount, NSTokens::Separator::CommaSeparator);
  982. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  983. for(uint32 i = 0; i < cfAction->ArgCount; ++i)
  984. {
  985. NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
  986. NSSnapValues::EmitTTDVar(cfAction->ArgArray[i], writer, sep);
  987. }
  988. writer->WriteSequenceEnd();
  989. writer->WriteInt64(NSTokens::Key::eventTime, cfAction->CallEventTime, NSTokens::Separator::CommaSeparator);
  990. writer->WriteInt64(NSTokens::Key::eventTime, cfAction->TopLevelCallbackEventTime, NSTokens::Separator::CommaSeparator);
  991. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  992. writer->WriteInt64(NSTokens::Key::i64Val, cfAction->LastNestedEvent, NSTokens::Separator::CommaSeparator);
  993. writer->WriteString(NSTokens::Key::name, cfAction->FunctionName, NSTokens::Separator::CommaSeparator);
  994. #endif
  995. }
  996. void JsRTCallFunctionAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  997. {
  998. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  999. reader->ReadKey(NSTokens::Key::argRetVal, true);
  1000. cfAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  1001. cfAction->CallbackDepth = reader->ReadInt32(NSTokens::Key::rootNestingDepth, true);
  1002. cfAction->ArgCount = reader->ReadLengthValue(true);
  1003. cfAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(cfAction->ArgCount);
  1004. reader->ReadSequenceStart_WDefaultKey(true);
  1005. for(uint32 i = 0; i < cfAction->ArgCount; ++i)
  1006. {
  1007. cfAction->ArgArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
  1008. }
  1009. reader->ReadSequenceEnd();
  1010. cfAction->CallEventTime = reader->ReadInt64(NSTokens::Key::eventTime, true);
  1011. cfAction->TopLevelCallbackEventTime = reader->ReadInt64(NSTokens::Key::eventTime, true);
  1012. cfAction->AdditionalReplayInfo = alloc.SlabAllocateStruct<JsRTCallFunctionAction_ReplayAdditionalInfo>();
  1013. cfAction->AdditionalReplayInfo->RtRSnap = nullptr;
  1014. cfAction->AdditionalReplayInfo->ExecArgs = (cfAction->ArgCount > 1) ? alloc.SlabAllocateArray<Js::Var>(cfAction->ArgCount - 1) : nullptr; //ArgCount includes slot for function which we don't use in exec
  1015. cfAction->AdditionalReplayInfo->LastExecutedLocation.Initialize();
  1016. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  1017. cfAction->LastNestedEvent = reader->ReadInt64(NSTokens::Key::i64Val, true);
  1018. reader->ReadString(NSTokens::Key::name, alloc, cfAction->FunctionName, true);
  1019. #endif
  1020. }
  1021. void JsRTCallFunctionAction_UnloadSnapshot(EventLogEntry* evt)
  1022. {
  1023. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  1024. if(cfAction->AdditionalReplayInfo != nullptr && cfAction->AdditionalReplayInfo->RtRSnap != nullptr)
  1025. {
  1026. TT_HEAP_DELETE(SnapShot, cfAction->AdditionalReplayInfo->RtRSnap);
  1027. cfAction->AdditionalReplayInfo->RtRSnap = nullptr;
  1028. }
  1029. }
  1030. void JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(EventLogEntry* evt, const TTDebuggerSourceLocation& lastSourceLocation)
  1031. {
  1032. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  1033. cfAction->AdditionalReplayInfo->LastExecutedLocation.SetLocationCopy(lastSourceLocation);
  1034. }
  1035. bool JsRTCallFunctionAction_GetLastExecutedStatementAndFrameInfoForDebugger(const EventLogEntry* evt, TTDebuggerSourceLocation& lastSourceInfo)
  1036. {
  1037. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  1038. if(cfAction->AdditionalReplayInfo->LastExecutedLocation.HasValue())
  1039. {
  1040. lastSourceInfo.SetLocationCopy(cfAction->AdditionalReplayInfo->LastExecutedLocation);
  1041. return true;
  1042. }
  1043. else
  1044. {
  1045. lastSourceInfo.Clear();
  1046. return false;
  1047. }
  1048. }
  1049. }
  1050. }
  1051. #endif