Fix VSCode `setExpression` command and MI/GDB `var-assign` command work with property setter.
MI/GDB var-create, var-show-attributes and var-list-children replies will provide "noneditable" attributes in case property don't have setter.
HRESULT Status;
ToRelease<ICorDebugValue> iCorInnerExceptionValue;
const bool escape = false;
- m_sharedEvaluator->WalkMembers(pExceptionValue, pThread, FrameLevel{0}, [&](
+ m_sharedEvaluator->WalkMembers(pExceptionValue, pThread, FrameLevel{0}, false, [&](
ICorDebugType*,
bool,
const std::string &memberName,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
auto getMemberWithName = [&](const std::string &name, std::string &result) -> HRESULT
{
// Note, this is optional field in exception object that could have nulled reference.
std::string excMessage;
const bool escape = false;
- m_sharedEvaluator->WalkMembers(iCorExceptionValue, pThread, FrameLevel{0}, [&](
+ m_sharedEvaluator->WalkMembers(iCorExceptionValue, pThread, FrameLevel{0}, false, [&](
ICorDebugType*,
bool,
const std::string &memberName,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
ToRelease<ICorDebugValue> pResultValue;
#include <iterator>
#include <arrayholder.h>
#include "debugger/evalstackmachine.h"
-#include "debugger/evaluator.h"
#include "debugger/evalhelpers.h"
#include "debugger/evalwaiter.h"
#include "debugger/valueprint.h"
return S_OK;
}
- HRESULT GetFrontStackEntryValue(ICorDebugValue **ppResultValue, std::list<EvalStackEntry> &evalStack, EvalData &ed, std::string &output)
+ HRESULT GetFrontStackEntryValue(ICorDebugValue **ppResultValue, std::unique_ptr<Evaluator::SetterData> *resultSetterData, std::list<EvalStackEntry> &evalStack, EvalData &ed, std::string &output)
{
HRESULT Status;
- if (FAILED(Status = ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, evalStack.front().identifiers, ppResultValue, nullptr, ed.evalFlags))
+ Evaluator::SetterData *inputPropertyData = nullptr;
+ if (evalStack.front().editable)
+ inputPropertyData = evalStack.front().setterData.get();
+ else
+ resultSetterData = nullptr;
+
+ if (FAILED(Status = ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, inputPropertyData, evalStack.front().identifiers,
+ ppResultValue, resultSetterData, nullptr, ed.evalFlags))
&& !evalStack.front().identifiers.empty())
{
std::ostringstream ss;
{
HRESULT Status;
ToRelease<ICorDebugValue> iCorValue;
- if ((FAILED(Status = ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, evalStack.front().identifiers, &iCorValue, ppResultType, ed.evalFlags))
+ if ((FAILED(Status = ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, nullptr, evalStack.front().identifiers,
+ &iCorValue, nullptr, ppResultType, ed.evalFlags))
&& !evalStack.front().identifiers.empty()) || iCorValue)
{
std::ostringstream ss;
for (int32_t i = 0; i < dimension; i++)
{
ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(GetFrontStackEntryValue(&iCorValue, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorValue, nullptr, evalStack, ed, output));
evalStack.pop_front();
// TODO implicitly convert iCorValue to int, if type not int
{
HRESULT Status;
ToRelease<ICorDebugValue> iCorValue2;
- IfFailRet(GetFrontStackEntryValue(&iCorValue2, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorValue2, nullptr, evalStack, ed, output));
evalStack.pop_front();
ToRelease<ICorDebugValue> iCorRealValue2;
CorElementType elemType2;
IfFailRet(GetRealValueWithType(iCorValue2, &iCorRealValue2, &elemType2));
ToRelease<ICorDebugValue> iCorValue1;
- IfFailRet(GetFrontStackEntryValue(&iCorValue1, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorValue1, nullptr, evalStack, ed, output));
evalStack.front().ResetEntry();
ToRelease<ICorDebugValue> iCorRealValue1;
CorElementType elemType1;
{
HRESULT Status;
ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(GetFrontStackEntryValue(&iCorValue, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorValue, nullptr, evalStack, ed, output));
evalStack.front().ResetEntry(EvalStackEntry::ResetLiteralStatus::No);
ToRelease<ICorDebugValue> iCorRealValue;
CorElementType elemType;
std::vector<ToRelease<ICorDebugValue>> iCorArgs(Int);
for (int32_t i = Int - 1; i >= 0; i--)
{
- IfFailRet(GetFrontStackEntryValue(&iCorArgs[i], evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorArgs[i], nullptr, evalStack, ed, output));
evalStack.pop_front();
}
ToRelease<ICorDebugValue> iCorValue;
ToRelease<ICorDebugType> iCorType;
- IfFailRet(ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, evalStack.front().identifiers, &iCorValue, &iCorType, ed.evalFlags));
+ IfFailRet(ed.pEvaluator->ResolveIdentifiers(ed.pThread, ed.frameLevel, evalStack.front().iCorValue, nullptr, evalStack.front().identifiers, &iCorValue, nullptr, &iCorType, ed.evalFlags));
bool searchStatic = false;
if (iCorType)
return S_OK;
ToRelease<ICorDebugValue> iCorArrayValue;
- IfFailRet(GetFrontStackEntryValue(&iCorArrayValue, evalStack, ed, output));
+ std::unique_ptr<Evaluator::SetterData> setterData;
+ IfFailRet(GetFrontStackEntryValue(&iCorArrayValue, &setterData, evalStack, ed, output));
evalStack.front().iCorValue.Free();
evalStack.front().identifiers.clear();
+ evalStack.front().setterData = std::move(setterData);
return ed.pEvaluator->GetElement(iCorArrayValue, indexes, &evalStack.front().iCorValue);
}
return S_OK;
ToRelease<ICorDebugValue> iCorArrayValue;
- IfFailRet(GetFrontStackEntryValue(&iCorArrayValue, evalStack, ed, output));
+ std::unique_ptr<Evaluator::SetterData> setterData;
+ IfFailRet(GetFrontStackEntryValue(&iCorArrayValue, &setterData, evalStack, ed, output));
ToRelease<ICorDebugReferenceValue> pReferenceValue;
IfFailRet(iCorArrayValue->QueryInterface(IID_ICorDebugReferenceValue, (LPVOID*) &pReferenceValue));
evalStack.front().iCorValue.Free();
evalStack.front().identifiers.clear();
+ evalStack.front().setterData = std::move(setterData);
return ed.pEvaluator->GetElement(iCorArrayValue, indexes, &evalStack.front().iCorValue);
}
HRESULT Status;
ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(GetFrontStackEntryValue(&iCorValue, evalStack, ed, output));
+ std::unique_ptr<Evaluator::SetterData> setterData;
+ IfFailRet(GetFrontStackEntryValue(&iCorValue, &setterData, evalStack, ed, output));
evalStack.front().iCorValue = iCorValue.Detach();
evalStack.front().identifiers.clear();
+ evalStack.front().setterData = std::move(setterData);
ToRelease<ICorDebugReferenceValue> pReferenceValue;
IfFailRet(evalStack.front().iCorValue->QueryInterface(IID_ICorDebugReferenceValue, (LPVOID*) &pReferenceValue));
ToRelease<ICorDebugValue> iCorRealValueRightOp;
ToRelease<ICorDebugValue> iCorRightOpValue;
CorElementType elemTypeRightOp;
- IfFailRet(GetFrontStackEntryValue(&iCorRightOpValue, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorRightOpValue, nullptr, evalStack, ed, output));
IfFailRet(GetRealValueWithType(iCorRightOpValue, &iCorRealValueRightOp, &elemTypeRightOp));
auto rightOperand = std::move(evalStack.front());
evalStack.pop_front();
ToRelease<ICorDebugValue> iCorRealValueLeftOp;
ToRelease<ICorDebugValue> iCorLeftOpValue;
CorElementType elemTypeLeftOp;
- IfFailRet(GetFrontStackEntryValue(&iCorLeftOpValue, evalStack, ed, output));
+ IfFailRet(GetFrontStackEntryValue(&iCorLeftOpValue, nullptr, evalStack, ed, output));
IfFailRet(GetRealValueWithType(iCorLeftOpValue, &iCorRealValueLeftOp, &elemTypeLeftOp));
std::string typeNameLeft;
std::string typeNameRigth;
} // unnamed namespace
HRESULT EvalStackMachine::Run(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, const std::string &expression,
- ICorDebugValue **ppResultValue, bool *editable, std::string &output)
+ std::list<EvalStackEntry> &evalStack, std::string &output)
{
static const std::vector<std::function<HRESULT(std::list<EvalStackEntry>&, PVOID, std::string&, EvalData&)>> CommandImplementation = {
IdentifierName,
{
if (FAILED(Status = Interop::NextStackCommand(pStackProgram, Command, pArguments, output)) ||
Command == ProgramFinished ||
- FAILED(Status = CommandImplementation[Command](m_evalStack, pArguments, output, m_evalData)))
+ FAILED(Status = CommandImplementation[Command](evalStack, pArguments, output, m_evalData)))
break;
}
while (1);
- do
- {
- if (FAILED(Status))
- break;
+ Interop::ReleaseStackMachineProgram(pStackProgram);
+ return Status;
+}
- assert(m_evalStack.size() == 1);
+HRESULT EvalStackMachine::EvaluateExpression(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, const std::string &expression, ICorDebugValue **ppResultValue,
+ std::string &output, bool *editable, std::unique_ptr<Evaluator::SetterData> *resultSetterData)
+{
+ HRESULT Status;
+ std::list<EvalStackEntry> evalStack;
+ IfFailRet(Run(pThread, frameLevel, evalFlags, expression, evalStack, output));
- if (editable)
- *editable = m_evalStack.front().editable;
+ assert(evalStack.size() == 1);
- if (*ppResultValue == nullptr)
- {
- Status = GetFrontStackEntryValue(ppResultValue, m_evalStack, m_evalData, output);
- break;
- }
+ std::unique_ptr<Evaluator::SetterData> setterData;
+ IfFailRet(GetFrontStackEntryValue(ppResultValue, &setterData, evalStack, m_evalData, output));
- ToRelease<ICorDebugValue> iCorValue;
- if (FAILED(Status = GetFrontStackEntryValue(&iCorValue, m_evalStack, m_evalData, output)))
- break;
+ if (editable)
+ *editable = setterData.get() && !setterData.get()->setterFunction ?
+ false /*property don't have setter*/ : evalStack.front().editable;
- Status = ImplicitCast(iCorValue, *ppResultValue, m_evalStack.front().literal, m_evalData);
- }
- while (0);
+ if (resultSetterData)
+ *resultSetterData = std::move(setterData);
- Interop::ReleaseStackMachineProgram(pStackProgram);
- m_evalStack.clear();
- return Status;
+ return S_OK;
+}
+
+HRESULT EvalStackMachine::SetValueByExpression(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, ICorDebugValue *pValue,
+ const std::string &expression, std::string &output)
+{
+ HRESULT Status;
+ std::list<EvalStackEntry> evalStack;
+ IfFailRet(Run(pThread, frameLevel, evalFlags, expression, evalStack, output));
+
+ assert(evalStack.size() == 1);
+
+ ToRelease<ICorDebugValue> iCorValue;
+ IfFailRet(GetFrontStackEntryValue(&iCorValue, nullptr, evalStack, m_evalData, output));
+
+ return ImplicitCast(iCorValue, pValue, evalStack.front().literal, m_evalData);
}
HRESULT EvalStackMachine::FindPredefinedTypes(ICorDebugModule *pModule)
#include <unordered_map>\r
#include "interfaces/types.h"\r
#include "utils/torelease.h"\r
+#include "debugger/evaluator.h"\r
\r
namespace netcoredbg\r
{\r
\r
-class Evaluator;\r
class EvalHelpers;\r
class EvalWaiter;\r
\r
bool literal;\r
// This entry is real variable (not literal, not result of expression calculation, not result of function call, ...).\r
bool editable;\r
+ // In case iCorValue is editable and property, we need extra data in order to set value.\r
+ // Note, this data directly connected with `iCorValue` and could be available only in case `editable` is true.\r
+ std::unique_ptr<Evaluator::SetterData> setterData;\r
\r
EvalStackEntry() : preventBinding(false), literal(false), editable(false)\r
{}\r
if (resetLiteral == ResetLiteralStatus::Yes)\r
literal = false;\r
editable = false;\r
+ setterData.reset();\r
}\r
};\r
\r
std::shared_ptr<Evaluator> m_sharedEvaluator;\r
std::shared_ptr<EvalHelpers> m_sharedEvalHelpers;\r
std::shared_ptr<EvalWaiter> m_sharedEvalWaiter;\r
- std::list<EvalStackEntry> m_evalStack;\r
EvalData m_evalData;\r
\r
+ // Run stack machine for particular expression.\r
+ HRESULT Run(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, const std::string &expression,\r
+ std::list<EvalStackEntry> &evalStack, std::string &output);\r
+\r
public:\r
\r
void SetupEval(std::shared_ptr<Evaluator> &sharedEvaluator, std::shared_ptr<EvalHelpers> &sharedEvalHelpers, std::shared_ptr<EvalWaiter> &sharedEvalWaiter)\r
m_evalData.pEvalWaiter = m_sharedEvalWaiter.get();\r
}\r
\r
- // Run stack machine for particular expression.\r
- HRESULT Run(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, const std::string &expression,\r
- ICorDebugValue **ppResultValue, bool *editable, std::string &output);\r
+ // Evaluate expression. Optional, return `editable` state and in case result is property - setter related information.\r
+ HRESULT EvaluateExpression(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, const std::string &expression, ICorDebugValue **ppResultValue,\r
+ std::string &output, bool *editable = nullptr, std::unique_ptr<Evaluator::SetterData> *resultSetterData = nullptr);\r
+\r
+ // Set value in pValue by expression with implicitly cast expression result to pValue type, if need.\r
+ HRESULT SetValueByExpression(ICorDebugThread *pThread, FrameLevel frameLevel, int evalFlags, ICorDebugValue *pValue,\r
+ const std::string &expression, std::string &output);\r
\r
// Find ICorDebugClass objects for all predefined types we need for stack machine during Private.CoreLib load.\r
// See ManagedCallback::LoadModule().\r
std::vector<std::string> &identifiers,
int nextIdentifier,
ICorDebugValue **ppResult,
+ std::unique_ptr<SetterData> *resultSetterData,
int evalFlags)
{
HRESULT Status;
ToRelease<ICorDebugValue> pClassValue(std::move(pResultValue));
- WalkMembers(pClassValue, pThread, frameLevel, [&](
+ WalkMembers(pClassValue, pThread, frameLevel, !!resultSetterData, [&](
ICorDebugType *pType,
bool is_static,
const std::string &memberName,
GetValueCallback getValue,
- SetValueCallback)
+ SetterData *setterData)
{
if (is_static && valueKind == ValueIsVariable)
return S_OK;
return S_OK;
IfFailRet(getValue(&pResultValue, evalFlags));
+ if (setterData && resultSetterData)
+ (*resultSetterData).reset(new SetterData(*setterData));
return E_ABORT; // Fast exit from cycle with result.
});
const std::string &methodClass,
std::vector<std::string> &identifiers,
ICorDebugValue **ppResult,
+ std::unique_ptr<SetterData> *resultSetterData,
int evalFlags)
{
HRESULT Status;
ToRelease<ICorDebugValue> pTypeObject;
if (S_OK == m_sharedEvalHelpers->CreatTypeObjectStaticConstructor(pThread, pType, &pTypeObject))
{
- if (SUCCEEDED(FollowFields(pThread, frameLevel, pTypeObject, ValueIsClass, staticName, 0, ppResult, evalFlags)))
+ if (SUCCEEDED(FollowFields(pThread, frameLevel, pTypeObject, ValueIsClass, staticName, 0, ppResult, resultSetterData, evalFlags)))
return S_OK;
}
trim = true;
ToRelease<ICorDebugValue> pTypeObject;
IfFailRet(m_sharedEvalHelpers->CreatTypeObjectStaticConstructor(pThread, pType, &pTypeObject));
if (Status == S_OK && // type have static members (S_FALSE if type don't have static members)
- SUCCEEDED(FollowFields(pThread, frameLevel, pTypeObject, ValueIsClass, fieldName, 0, ppResult, evalFlags)))
+ SUCCEEDED(FollowFields(pThread, frameLevel, pTypeObject, ValueIsClass, fieldName, 0, ppResult, resultSetterData, evalFlags)))
return S_OK;
trim = true;
HRESULT Evaluator::ResolveIdentifiers(ICorDebugThread *pThread,
FrameLevel frameLevel,
ICorDebugValue *pInputValue,
+ SetterData *inputSetterData,
std::vector<std::string> &identifiers,
ICorDebugValue **ppResultValue,
+ std::unique_ptr<SetterData> *resultSetterData,
ICorDebugType **ppResultType,
int evalFlags)
{
{
pInputValue->AddRef();
*ppResultValue = pInputValue;
+ if (inputSetterData && resultSetterData)
+ (*resultSetterData).reset(new SetterData(*inputSetterData));
return S_OK;
}
else if (pInputValue)
{
- return FollowFields(pThread, frameLevel, pInputValue, Evaluator::ValueIsVariable, identifiers, 0, ppResultValue, evalFlags);
+ return FollowFields(pThread, frameLevel, pInputValue, Evaluator::ValueIsVariable, identifiers, 0, ppResultValue, resultSetterData, evalFlags);
}
HRESULT Status;
if (identifiers[nextIdentifier] == "this")
nextIdentifier++; // skip first identifier with "this" (we have it in pThisValue), check rest
- if (SUCCEEDED(FollowFields(pThread, frameLevel, pThisValue, ValueIsVariable, identifiers, nextIdentifier, &pResolvedValue, evalFlags)))
+ if (SUCCEEDED(FollowFields(pThread, frameLevel, pThisValue, ValueIsVariable, identifiers, nextIdentifier, &pResolvedValue, resultSetterData, evalFlags)))
{
*ppResultValue = pResolvedValue.Detach();
return S_OK;
std::string methodName;
TypePrinter::GetTypeAndMethod(pFrame, methodClass, methodName);
- if (SUCCEEDED(FollowNestedFindValue(pThread, frameLevel, methodClass, identifiers, &pResolvedValue, evalFlags)))
+ if (SUCCEEDED(FollowNestedFindValue(pThread, frameLevel, methodClass, identifiers, &pResolvedValue, resultSetterData, evalFlags)))
{
*ppResultValue = pResolvedValue.Detach();
return S_OK;
}
ToRelease<ICorDebugValue> pValue(std::move(pResolvedValue));
- IfFailRet(FollowFields(pThread, frameLevel, pValue, valueKind, identifiers, nextIdentifier, &pResolvedValue, evalFlags));
+ IfFailRet(FollowFields(pThread, frameLevel, pValue, valueKind, identifiers, nextIdentifier, &pResolvedValue, resultSetterData, evalFlags));
*ppResultValue = pResolvedValue.Detach();
return S_OK;
return S_OK;
}
+HRESULT Evaluator::SetValue(ICorDebugThread *pThread, FrameLevel frameLevel, ICorDebugValue *pValue, SetterData *setterData,
+ const std::string &value, int evalFlags, std::string &output)
+{
+ if (!pThread)
+ return E_FAIL;
+
+ // In case this is not property, just change value itself.
+ if (!setterData)
+ return m_sharedEvalStackMachine->SetValueByExpression(pThread, frameLevel, evalFlags, pValue, value, output);
+
+ HRESULT Status;
+ pValue->AddRef();
+ ToRelease<ICorDebugValue> iCorValue(pValue);
+ CorElementType corType;
+ IfFailRet(iCorValue->GetType(&corType));
+
+ if (corType == ELEMENT_TYPE_STRING)
+ {
+ // FIXME investigate, why in this case we can't use ICorDebugReferenceValue::SetValue() for string in iCorValue
+ iCorValue.Free();
+ IfFailRet(m_sharedEvalStackMachine->EvaluateExpression(pThread, frameLevel, evalFlags, value, &iCorValue, output));
+
+ CorElementType elemType;
+ IfFailRet(iCorValue->GetType(&elemType));
+ if (elemType != ELEMENT_TYPE_STRING)
+ return E_INVALIDARG;
+ }
+ else // Allow stack machine decide what types are supported.
+ {
+ IfFailRet(m_sharedEvalStackMachine->SetValueByExpression(pThread, frameLevel, evalFlags, iCorValue.GetPtr(), value, output));
+ }
+
+ // Call setter.
+ if (!setterData->thisValue)
+ {
+ return m_sharedEvalHelpers->EvalFunction(pThread, setterData->setterFunction, nullptr, 0, iCorValue.GetRef(), 1, nullptr, evalFlags);
+ }
+ else
+ {
+ ICorDebugValue *ppArgsValue[] = {setterData->thisValue, iCorValue};
+ return m_sharedEvalHelpers->EvalFunction(pThread, setterData->setterFunction, nullptr, 0, ppArgsValue, 2, nullptr, evalFlags);
+ }
+}
+
HRESULT Evaluator::WalkMembers(
ICorDebugValue *pInputValue,
ICorDebugThread *pThread,
FrameLevel frameLevel,
ICorDebugType *pTypeCast,
+ bool provideSetterData,
WalkMembersCallback cb)
{
HRESULT Status = S_OK;
return S_OK;
};
- auto setValue = [&](const std::string &value, std::string &output, int evalFlags) -> HRESULT
- {
- if (!pThread)
- return E_FAIL;
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(getValue(&iCorValue, evalFlags));
- return m_sharedEvalStackMachine->Run(pThread, frameLevel, evalFlags, value, iCorValue.GetRef(), nullptr, output);
- };
-
- return cb(nullptr, false, "", getValue, setValue);
+ return cb(nullptr, false, "", getValue, nullptr);
}
ToRelease<ICorDebugArrayValue> pArrayValue;
return S_OK;
};
- auto setValue = [&](const std::string &value, std::string &output, int evalFlags) -> HRESULT
- {
- if (!pThread)
- return E_FAIL;
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(getValue(&iCorValue, evalFlags));
- return m_sharedEvalStackMachine->Run(pThread, frameLevel, evalFlags, value, iCorValue.GetRef(), nullptr, output);
- };
-
- IfFailRet(cb(nullptr, false, "[" + IndiciesToStr(ind, base) + "]", getValue, setValue));
+ IfFailRet(cb(nullptr, false, "[" + IndiciesToStr(ind, base) + "]", getValue, nullptr));
IncIndicies(ind, dims);
}
return S_OK;
};
- auto setValue = [&](const std::string &value, std::string &output, int evalFlags) -> HRESULT
- {
- if (!pThread)
- return E_FAIL;
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(getValue(&iCorValue, evalFlags));
- return m_sharedEvalStackMachine->Run(pThread, frameLevel, evalFlags, value, iCorValue.GetRef(), nullptr, output);
- };
-
- IfFailRet(cb(pType, is_static, name, getValue, setValue));
+ IfFailRet(cb(pType, is_static, name, getValue, nullptr));
}
return S_OK;
}));
return m_sharedEvalHelpers->EvalFunction(pThread, iCorFunc, pType.GetRef(), 1, is_static ? nullptr : &pInputValue, is_static ? 0 : 1, ppResultValue, evalFlags);
};
- auto setValue = [&](const std::string &value, std::string &output, int evalFlags) -> HRESULT
+ if (provideSetterData)
{
- if (!pThread)
- return E_FAIL;
-
- ToRelease<ICorDebugFunction> iCorFunc;
- IfFailRet(pModule->GetFunctionFromToken(mdSetter, &iCorFunc));
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(getValue(&iCorValue, evalFlags));
- CorElementType corType;
- IfFailRet(iCorValue->GetType(&corType));
-
- if (corType == ELEMENT_TYPE_STRING)
- {
- // FIXME investigate, why in this case we can't use ICorDebugReferenceValue::SetValue() for string in iCorValue
- iCorValue.Free();
- IfFailRet(m_sharedEvalStackMachine->Run(pThread, frameLevel, evalFlags, value, &iCorValue, nullptr, output));
-
- CorElementType elemType;
- IfFailRet(iCorValue->GetType(&elemType));
- if (elemType != ELEMENT_TYPE_STRING)
- return E_INVALIDARG;
- }
- else // Allow stack machine decide what types are supported.
- {
- IfFailRet(m_sharedEvalStackMachine->Run(pThread, frameLevel, evalFlags, value, iCorValue.GetRef(), nullptr, output));
- }
-
- // Call setter.
- if (is_static)
- {
- return m_sharedEvalHelpers->EvalFunction(pThread, iCorFunc, nullptr, 0, iCorValue.GetRef(), 1, nullptr, evalFlags);
- }
- else
+ ToRelease<ICorDebugFunction> iCorFuncSetter;
+ if (FAILED(pModule->GetFunctionFromToken(mdSetter, &iCorFuncSetter)))
{
- ICorDebugValue *ppArgsValue[] = {pInputValue, iCorValue};
- return m_sharedEvalHelpers->EvalFunction(pThread, iCorFunc, nullptr, 0, ppArgsValue, 2, nullptr, evalFlags);
+ iCorFuncSetter.Free();
}
- };
- IfFailRet(cb(pType, is_static, name, getValue, setValue));
+ SetterData setterData(is_static ? nullptr : pInputValue, iCorFuncSetter);
+ IfFailRet(cb(pType, is_static, name, getValue, &setterData));
+ }
+ else
+ {
+ IfFailRet(cb(pType, is_static, name, getValue, nullptr));
+ }
}
return S_OK;
}));
IfFailRet(m_sharedEvalHelpers->CreatTypeObjectStaticConstructor(pThread, pBaseType));
}
// Add fields of base class
- IfFailRet(WalkMembers(pInputValue, pThread, frameLevel, pBaseType, cb));
+ IfFailRet(WalkMembers(pInputValue, pThread, frameLevel, pBaseType, provideSetterData, cb));
}
}
ICorDebugValue *pValue,
ICorDebugThread *pThread,
FrameLevel frameLevel,
+ bool provideSetterData,
WalkMembersCallback cb)
{
- return WalkMembers(pValue, pThread, frameLevel, nullptr, cb);
+ return WalkMembers(pValue, pThread, frameLevel, nullptr, provideSetterData, cb);
}
static bool has_prefix(const std::string &s, const std::string &prefix)
return S_FALSE;
// Substitute local value with its fields
- IfFailRet(pEvaluator->WalkMembers(pLocalValue, nullptr, FrameLevel{0}, [&](
+ IfFailRet(pEvaluator->WalkMembers(pLocalValue, nullptr, FrameLevel{0}, false, [&](
ICorDebugType *,
bool is_static,
const std::string &name,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
if (is_static)
return S_OK;
return S_FALSE;
// Substitute this with its fields
- IfFailRet(pEvaluator->WalkMembers(pThisValue, nullptr, FrameLevel{0}, [&](
+ IfFailRet(pEvaluator->WalkMembers(pThisValue, nullptr, FrameLevel{0}, false, [&](
ICorDebugType *,
bool is_static,
const std::string &name,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
HRESULT Status;
if (is_static)
};
typedef ArgElementType ReturnElementType;
+ struct SetterData
+ {
+ ToRelease<ICorDebugValue> thisValue;
+ ToRelease<ICorDebugFunction> setterFunction;
+
+ SetterData(ICorDebugValue *pValue, ICorDebugFunction *pFunction)
+ {
+ Set(pValue, pFunction);
+ };
+
+ SetterData(SetterData &setterData)
+ {
+ Set(setterData.thisValue.GetPtr(), setterData.setterFunction.GetPtr());
+ };
+
+ void Set(ICorDebugValue *pValue, ICorDebugFunction *pFunction)
+ {
+ if (pValue)
+ pValue->AddRef();
+ thisValue = pValue;
+
+ if (pFunction)
+ pFunction->AddRef();
+ setterFunction = pFunction;
+ }
+ };
+
typedef std::function<HRESULT(ICorDebugValue**,int)> GetValueCallback;
- typedef std::function<HRESULT(const std::string&,std::string&,int)> SetValueCallback;
- typedef std::function<HRESULT(ICorDebugType*,bool,const std::string&,GetValueCallback,SetValueCallback)> WalkMembersCallback;
+ typedef std::function<HRESULT(ICorDebugType*,bool,const std::string&,GetValueCallback,SetterData*)> WalkMembersCallback;
typedef std::function<HRESULT(const std::string&,GetValueCallback)> WalkStackVarsCallback;
typedef std::function<HRESULT(ICorDebugFunction**)> GetFunctionCallback;
typedef std::function<HRESULT(bool,const std::string&,ReturnElementType&,std::vector<ArgElementType>&,GetFunctionCallback)> WalkMethodsCallback;
ICorDebugThread *pThread,
FrameLevel frameLevel,
ICorDebugValue *pInputValue,
+ SetterData *inputSetterData,
std::vector<std::string> &identifiers,
ICorDebugValue **ppResultValue,
+ std::unique_ptr<SetterData> *resultSetterData,
ICorDebugType **ppResultType,
int evalFlags);
ICorDebugValue *pValue,
ICorDebugThread *pThread,
FrameLevel frameLevel,
+ bool provideSetterData,
WalkMembersCallback cb);
HRESULT WalkStackVars(
HRESULT WalkMethods(ICorDebugType *pInputType, WalkMethodsCallback cb);
HRESULT WalkMethods(ICorDebugValue *pInputTypeValue, WalkMethodsCallback cb);
+ HRESULT SetValue(ICorDebugThread *pThread, FrameLevel frameLevel, ICorDebugValue *pValue, SetterData *setterData,
+ const std::string &value, int evalFlags, std::string &output);
+
private:
std::shared_ptr<Modules> m_sharedModules;
const std::string &methodClass,
std::vector<std::string> &identifiers,
ICorDebugValue **ppResult,
+ std::unique_ptr<SetterData> *resultSetterData,
int evalFlags);
HRESULT FollowFields(
std::vector<std::string> &identifiers,
int nextIdentifier,
ICorDebugValue **ppResult,
+ std::unique_ptr<SetterData> *resultSetterData,
int evalFlags);
HRESULT WalkMembers(
ICorDebugThread *pThread,
FrameLevel frameLevel,
ICorDebugType *pTypeCast,
+ bool provideSetterData,
WalkMembersCallback cb);
};
HRESULT ManagedDebugger::SetVariable(const std::string &name, const std::string &value, uint32_t ref, std::string &output)
{
+ LogFuncEntry();
+
return m_sharedVariables->SetVariable(m_iCorProcess, name, value, ref, output);
}
-HRESULT ManagedDebugger::SetVariableByExpression(
- FrameId frameId,
- const std::string &evaluateName,
- int evalFlags,
- const std::string &value,
- std::string &output)
+HRESULT ManagedDebugger::SetExpression(FrameId frameId, const std::string &expression, int evalFlags, const std::string &value, std::string &output)
{
LogFuncEntry();
- HRESULT Status;
- ToRelease<ICorDebugValue> pResultValue;
-
- IfFailRet(m_sharedVariables->GetValueByExpression(m_iCorProcess, frameId, evaluateName, evalFlags, &pResultValue));
- return m_sharedVariables->SetVariable(m_iCorProcess, pResultValue, value, frameId, evalFlags, output);
+ return m_sharedVariables->SetExpression(m_iCorProcess, frameId, expression, evalFlags, value, output);
}
int GetNamedVariables(uint32_t variablesReference) override;
HRESULT Evaluate(FrameId frameId, const std::string &expression, Variable &variable, std::string &output) override;
HRESULT SetVariable(const std::string &name, const std::string &value, uint32_t ref, std::string &output) override;
- HRESULT SetVariableByExpression(FrameId frameId, const std::string &evaluateName, int evalFlags, const std::string &value, std::string &output) override;
+ HRESULT SetExpression(FrameId frameId, const std::string &expression, int evalFlags, const std::string &value, std::string &output) override;
HRESULT GetExceptionInfo(ThreadId threadId, ExceptionInfo &exceptionInfo) override;
HRESULT GetSourceFile(const std::string &sourcePath, char** fileBuf, int* fileLen) override;
void FreeUnmanaged(PVOID mem) override;
int numStatic = 0;
int numInstance = 0;
// No thread and FrameLevel{0} here, since we need only count childs.
- if (FAILED(m_sharedEvaluator->WalkMembers(pValue, nullptr, FrameLevel{0}, [&numStatic, &numInstance](
+ if (FAILED(m_sharedEvaluator->WalkMembers(pValue, nullptr, FrameLevel{0}, false, [&numStatic, &numInstance](
ICorDebugType *,
bool is_static,
const std::string &,
Evaluator::GetValueCallback,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
if (is_static)
numStatic++;
int currentIndex = -1;
- IfFailRet(m_sharedEvaluator->WalkMembers(pInputValue, pThread, frameLevel, [&](
+ IfFailRet(m_sharedEvaluator->WalkMembers(pInputValue, pThread, frameLevel, false, [&](
ICorDebugType *pType,
bool is_static,
const std::string &name,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback)
+ Evaluator::SetterData*)
{
if (is_static)
hasStaticMembers = true;
ToRelease<ICorDebugValue> pResultValue;
FrameLevel frameLevel = frameId.getLevel();
- IfFailRet(m_sharedEvalStackMachine->Run(pThread, frameLevel, variable.evalFlags, expression, &pResultValue, &variable.editable, output));
+ IfFailRet(m_sharedEvalStackMachine->EvaluateExpression(pThread, frameLevel, variable.evalFlags, expression, &pResultValue, output, &variable.editable));
variable.evaluateName = expression;
IfFailRet(PrintValue(pResultValue, variable.value));
ToRelease<ICorDebugValue> iCorValue;
IfFailRet(getValue(&iCorValue, ref.evalFlags));
- IfFailRet(m_sharedEvalStackMachine->Run(pThread, ref.frameId.getLevel(), ref.evalFlags, value, iCorValue.GetRef(), nullptr, output));
+ IfFailRet(m_sharedEvaluator->SetValue(pThread, ref.frameId.getLevel(), iCorValue, nullptr, value, ref.evalFlags, output));
IfFailRet(PrintValue(iCorValue, output));
return E_ABORT; // Fast exit from cycle.
})) && Status != E_ABORT)
HRESULT Status;
- IfFailRet(m_sharedEvaluator->WalkMembers(ref.iCorValue, pThread, ref.frameId.getLevel(), [&](
+ if (FAILED(Status = m_sharedEvaluator->WalkMembers(ref.iCorValue, pThread, ref.frameId.getLevel(), true, [&](
ICorDebugType*,
bool is_static,
const std::string &varName,
Evaluator::GetValueCallback getValue,
- Evaluator::SetValueCallback setValue) -> HRESULT
+ Evaluator::SetterData *setterData) -> HRESULT
{
- if (varName == name)
- {
- IfFailRet(setValue(value, output, ref.evalFlags));
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(getValue(&iCorValue, ref.evalFlags));
- IfFailRet(PrintValue(iCorValue, output));
- }
- return S_OK;
- }));
-
- return S_OK;
-}
-
-HRESULT Variables::GetValueByExpression(ICorDebugProcess *pProcess, FrameId frameId,
- const std::string &evaluateName, int evalFlags, ICorDebugValue **ppResult)
-{
- if (pProcess == nullptr)
- return E_FAIL;
-
- HRESULT Status;
-
- ThreadId threadId = frameId.getThread();
- if (!threadId)
- return E_FAIL;
+ if (varName != name)
+ return S_OK;
- ToRelease<ICorDebugThread> pThread;
- IfFailRet(pProcess->GetThread(int(threadId), &pThread));
+ if (setterData && !setterData->setterFunction)
+ return E_FAIL;
- // Looks like all we need here is get ICorDebugValue by field/variable name.
- // All "set value" code must be refactored in order to remove dependency from Roslyn.
+ ToRelease<ICorDebugValue> iCorValue;
+ IfFailRet(getValue(&iCorValue, ref.evalFlags));
+ IfFailRet(m_sharedEvaluator->SetValue(pThread, ref.frameId.getLevel(), iCorValue, setterData, value, ref.evalFlags, output));
+ IfFailRet(PrintValue(iCorValue, output));
+ return E_ABORT; // Fast exit from cycle.
+ })) && Status != E_ABORT)
+ {
+ return Status;
+ }
- std::string output;
- return m_sharedEvalStackMachine->Run(pThread, frameId.getLevel(), evalFlags, evaluateName, ppResult, nullptr, output);
+ return S_OK;
}
-HRESULT Variables::SetVariable(
- ICorDebugProcess *pProcess,
- ICorDebugValue *pVariable,
- const std::string &value,
- FrameId frameId,
- int evalFlags,
- std::string &output)
+HRESULT Variables::SetExpression(ICorDebugProcess *pProcess, FrameId frameId, const std::string &expression,
+ int evalFlags, const std::string &value, std::string &output)
{
- HRESULT Status;
-
if (pProcess == nullptr)
return E_FAIL;
if (!threadId)
return E_FAIL;
+ HRESULT Status;
ToRelease<ICorDebugThread> pThread;
IfFailRet(pProcess->GetThread(int(threadId), &pThread));
- IfFailRet(m_sharedEvalStackMachine->Run(pThread, frameId.getLevel(), evalFlags, value, &pVariable, nullptr, output));
- IfFailRet(PrintValue(pVariable, output));
+ ToRelease<ICorDebugValue> iCorValue;
+ bool editable = false;
+ std::unique_ptr<Evaluator::SetterData> setterData;
+ IfFailRet(m_sharedEvalStackMachine->EvaluateExpression(pThread, frameId.getLevel(), evalFlags, expression, &iCorValue, output, &editable, &setterData));
+ if (!editable ||
+ (editable && setterData.get() && !setterData.get()->setterFunction)) // property, that don't have setter
+ {
+ output = "'" + expression + "' cannot be assigned to";
+ return E_INVALIDARG;
+ }
+
+ IfFailRet(m_sharedEvaluator->SetValue(pThread, frameId.getLevel(), iCorValue, setterData.get(), value, evalFlags, output));
+ IfFailRet(PrintValue(iCorValue, output));
return S_OK;
}
uint32_t ref,
std::string &output);
- HRESULT SetVariable(
+ HRESULT SetExpression(
ICorDebugProcess *pProcess,
- ICorDebugValue *pVariable,
- const std::string &value,
FrameId frameId,
+ const std::string &expression,
int evalFlags,
+ const std::string &value,
std::string &output);
HRESULT GetScopes(
Variable &variable,
std::string &output);
- HRESULT GetValueByExpression(
- ICorDebugProcess *pProcess,
- FrameId frameId,
- const std::string &evaluateName,
- int evalFlags,
- ICorDebugValue **ppResult);
-
HRESULT GetExceptionVariable(
FrameId frameId,
ICorDebugThread *pThread,
virtual int GetNamedVariables(uint32_t variablesReference) = 0;
virtual HRESULT Evaluate(FrameId frameId, const std::string &expression, Variable &variable, std::string &output) = 0;
virtual HRESULT SetVariable(const std::string &name, const std::string &value, uint32_t ref, std::string &output) = 0;
- virtual HRESULT SetVariableByExpression(FrameId frameId, const std::string &evaluateName, int evalFlags, const std::string &value, std::string &output) = 0;
+ virtual HRESULT SetExpression(FrameId frameId, const std::string &expression, int evalFlags, const std::string &value, std::string &output) = 0;
virtual HRESULT GetExceptionInfo(ThreadId threadId, ExceptionInfo &exceptionInfo) = 0;
virtual HRESULT GetSourceFile(const std::string &sourcePath, char** fileBuf, int* fileLen) = 0;
virtual void FreeUnmanaged(PVOID mem) = 0;
IfFailRet(FindVar(varName, miVariable));
FrameId frameId(miVariable.threadId, miVariable.level);
- IfFailRet(m_sharedDebugger->SetVariableByExpression(frameId, miVariable.variable.evaluateName, miVariable.variable.evalFlags, varExpr, output));
+ IfFailRet(m_sharedDebugger->SetExpression(frameId, miVariable.variable.evaluateName, miVariable.variable.evalFlags, varExpr, output));
output = "value=\"" + MIProtocol::EscapeMIValue(output) + "\"";
// VSCode don't support evaluation flags, we can't disable implicit function calls during evaluation.
// https://github.com/OmniSharp/omnisharp-vscode/issues/3173
std::string output;
- Status = m_sharedDebugger->SetVariableByExpression(frameId, expression, defaultEvalFlags, value, output);
+ Status = m_sharedDebugger->SetExpression(frameId, expression, defaultEvalFlags, value, output);
if (FAILED(Status))
{
if (output.empty())
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "2002");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i_noset", "5002");
Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_field_i", "3001");
- // FIXME debugger must be fixed first //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
- // FIXME debugger must be fixed first //Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i_noset", "3003");
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
+ Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i_noset", "3003");
Context.CreateAndAssignVar(@"__FILE__:__LINE__", "setVarStruct.field_i", "4001");
- // FIXME debugger must be fixed first //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
- // FIXME debugger must be fixed first //Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "setVarStruct.prop_i_noset", "4003");
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
+ Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "setVarStruct.prop_i_noset", "4003");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_field_i", "3001");
- // FIXME debugger must be fixed first //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.field_i", "4001");
- // FIXME debugger must be fixed first //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
- // FIXME debugger must be fixed first //Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "1+1", "2");
- // FIXME debugger must be fixed first //Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "1", "1");
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
+ Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "1+1", "2");
+ Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "1", "1");
Context.ErrorAtAssignVar(@"__FILE__:__LINE__", "1.ToString()", "\"1\"");
Context.CheckAttributes(@"__FILE__:__LINE__", "array1[0]", "editable");
Context.CheckAttributes(@"__FILE__:__LINE__", "array1?[0]", "editable");
Context.CheckAttributes(@"__FILE__:__LINE__", "litClass.data", "editable");
Context.CheckAttributes(@"__FILE__:__LINE__", "litClass?.data", "editable");
+ Context.CheckAttributes(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "editable");
+ Context.CheckAttributes(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i_noset", "noneditable");
Context.CheckAttributes(@"__FILE__:__LINE__", "1", "noneditable");
Context.CheckAttributes(@"__FILE__:__LINE__", "-1", "noneditable");
Context.CheckAttributes(@"__FILE__:__LINE__", "-array1[0]", "noneditable");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "array1[4]", "5");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_field_i", "3001");
- // FIXME debugger must be fixed first //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestSetVarStruct.static_prop_i", "3002");
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.field_i", "4001");
- // FIXME debugger must be fixed first //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "setVarStruct.prop_i", "4002");
Context.Continue(@"__FILE__:__LINE__");
});
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i_noset", "5002");
Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_field_i", "3001");
Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i", "3002");
- // FIXME debugger must be fixed first //Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i_noset", "3003");
+ Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i_noset", "3003");
Context.SetExpression(@"__FILE__:__LINE__", frameId, "setExprStruct.field_i", "4001");
Context.SetExpression(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i", "4002");
- // FIXME debugger must be fixed first //Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i_noset", "4003");
+ Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i_noset", "4003");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_field_i", "3001");
- // FIXME debugger must be fixed first //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i", "3002");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i", "3002");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.field_i", "4001");
- // FIXME debugger must be fixed first //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i", "4002");
- // FIXME debugger must be fixed first //Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "1+1", "2");
- // FIXME debugger must be fixed first //Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "1", "1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i", "4002");
+ Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "1+1", "2");
+ Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "1", "1");
Context.ErrorSetExpression(@"__FILE__:__LINE__", frameId, "1.ToString()", "\"1\"");
Context.Continue(@"__FILE__:__LINE__");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setVarStruct.prop_i", "4002");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_field_i", "3001");
- // FIXME debugger must be fixed first //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i", "3002");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "TestSetExprStruct.static_prop_i", "3002");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.field_i", "4001");
- // FIXME debugger must be fixed first //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i", "4002");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "setExprStruct.prop_i", "4002");
Context.Continue(@"__FILE__:__LINE__");
});