// A AsyncESuspend is used in the codegen for an async function to setup // a Continuation and return a wait handle so execution can continue // later. We have just completed a AsyncESuspend, so the new // Continuation is available, and it can predict where execution will // resume. void CmdNext::stepAfterAsyncESuspend() { auto topObj = g_context->getStack().topTV()->m_data.pobj; assert(topObj->instanceof(c_AsyncFunctionWaitHandle::classof())); auto wh = static_cast<c_AsyncFunctionWaitHandle*>(topObj); auto func = wh->getActRec()->m_func; Offset nextInst = wh->getNextExecutionOffset(); assert(nextInst != InvalidAbsoluteOffset); m_stepContTag = wh->getActRec(); TRACE(2, "CmdNext: patch for cont step after AsyncESuspend at '%s' offset %d\n", func->fullName()->data(), nextInst); m_stepCont = StepDestination(func->unit(), nextInst); }
bool CmdVariable::onServer(DebuggerProxy &proxy) { if (m_type == KindOfVariableAsync) { //we only do variable inspection on continuation wait handles auto frame = getWaitHandleAtAsyncStackPosition(m_frame); if (frame != nullptr) { auto fp = frame->getActRec(); if (fp != nullptr) { m_variables = getVariables(fp); } } } else if (m_frame < 0) { m_variables = g_context->m_globalVarEnv->getDefinedVariables(); m_global = true; } else { m_variables = g_context->getLocalDefinedVariables(m_frame); m_global = g_context->getVarEnv(m_frame) == g_context->m_globalVarEnv; } if (m_global) { m_variables.remove(s_GLOBALS); } if (m_version == 1) { // Remove the values before sending to client. ArrayInit ret(m_variables->size(), ArrayInit::Map{}); Variant v; for (ArrayIter iter(m_variables); iter; ++iter) { ret.add(iter.first().toString(), v); } m_variables = ret.toArray(); m_version = 2; } else if (m_version == 2) { // Remove entries that do not match a non empty m_varName. if (!m_varName.empty()) { ArrayInit ret(1, ArrayInit::Map{}); ret.add(m_varName, m_variables[m_varName]); m_variables = ret.toArray(); } // Remove entries whose name or contents do not match a non empty m_filter if (!m_filter.empty()) { ArrayInit ret(m_variables.size(), ArrayInit::Map{}); for (ArrayIter iter(m_variables); iter; ++iter) { String name = iter.first().toString(); if (name.find(m_filter, 0, false) < 0) { String fullvalue = DebuggerClient::FormatVariable(iter.second(), -1); if (fullvalue.find(m_filter, 0, false) < 0) { continue; } } ret.add(name, iter.second()); } m_variables = ret.toArray(); } } return proxy.sendToClient(this); }