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->actRec(); 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); }
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->actRec(); if (fp != nullptr) { m_variables = getDefinedVariables(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->hasVarEnv(m_frame) == g_context->m_globalVarEnv; auto oThis = g_context->getThis(); if (nullptr != oThis) { TypedValue tvThis; tvThis.m_type = KindOfObject; tvThis.m_data.pobj = oThis; Variant thisName(s_this); m_variables.add(thisName, tvAsVariant(&tvThis)); } } if (m_global) { m_variables.remove(s_GLOBALS); } // Deprecated IDE uses this, so keep it around for now. It expects all // variable values to be fully serialized across the wire. if (m_version == 0) { return proxy.sendToClient(this); } // Version 1 of this command means we want the names of all variables, but we // don't care about their values just yet. if (m_version == 1) { ArrayInit ret(m_variables->size(), ArrayInit::Map{}); Variant v; for (ArrayIter iter(m_variables); iter; ++iter) { assert(iter.first().isString()); ret.add(iter.first().toString(), v); } m_variables = ret.toArray(); m_version = 2; return proxy.sendToClient(this); } // Version 2 of this command means we're trying to get the value of a single // variable. always_assert(m_version == 2); always_assert(!m_varName.empty()); // Variable name might not exist. if (!m_variables.exists(m_varName, true /* isKey */)) { m_variables = Array::Create(); return proxy.sendToClient(this); } auto const value = m_variables[m_varName]; auto const result = m_formatMaxLen < 0 ? DebuggerClient::FormatVariable(value) : DebuggerClient::FormatVariableWithLimit(value, m_formatMaxLen); m_variables = Array::Create(m_varName, result); // Remove the entry if its name or context does not match the filter. if (!m_filter.empty() && m_varName.find(m_filter, 0, false) < 0) { auto const fullvalue = DebuggerClient::FormatVariable(value); if (fullvalue.find(m_filter, 0, false) < 0) { m_variables = Array::Create(); } } return proxy.sendToClient(this); }