Debugger: Fix #11459.
- When saving our view state, only save a new set of values if a stack frame clear is pending. Otherwise, check if there is a previously existing view state, and take over its values. This ensures that we correctly remember our previous values when the user is simply switching stack frames while in a stopped state.
This commit is contained in:
@@ -1660,12 +1660,19 @@ VariablesView::Create(Listener* listener)
|
|||||||
void
|
void
|
||||||
VariablesView::SetStackFrame(Thread* thread, StackFrame* stackFrame)
|
VariablesView::SetStackFrame(Thread* thread, StackFrame* stackFrame)
|
||||||
{
|
{
|
||||||
|
bool updateValues = fFrameClearPending;
|
||||||
|
// We only want to save previous values if we've continued
|
||||||
|
// execution (i.e. thread/frame are being cleared).
|
||||||
|
// Otherwise, we'll overwrite our previous values simply
|
||||||
|
// by switching frames within the same stack trace, which isn't
|
||||||
|
// desired behavior.
|
||||||
|
|
||||||
fFrameClearPending = false;
|
fFrameClearPending = false;
|
||||||
|
|
||||||
if (thread == fThread && stackFrame == fStackFrame)
|
if (thread == fThread && stackFrame == fStackFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_SaveViewState();
|
_SaveViewState(updateValues);
|
||||||
|
|
||||||
_FinishContextMenu(true);
|
_FinishContextMenu(true);
|
||||||
|
|
||||||
@@ -2470,7 +2477,7 @@ VariablesView::_FinishContextMenu(bool force)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VariablesView::_SaveViewState() const
|
VariablesView::_SaveViewState(bool updateValues) const
|
||||||
{
|
{
|
||||||
if (fThread == NULL || fStackFrame == NULL
|
if (fThread == NULL || fStackFrame == NULL
|
||||||
|| fStackFrame->Function() == NULL) {
|
|| fStackFrame->Function() == NULL) {
|
||||||
@@ -2483,21 +2490,40 @@ VariablesView::_SaveViewState() const
|
|||||||
return;
|
return;
|
||||||
BReference<FunctionID> functionIDReference(functionID, true);
|
BReference<FunctionID> functionIDReference(functionID, true);
|
||||||
|
|
||||||
StackFrameValues* values = new(std::nothrow) StackFrameValues;
|
StackFrameValues* values = NULL;
|
||||||
if (values == NULL)
|
ExpressionValues* expressionValues = NULL;
|
||||||
return;
|
BReference<StackFrameValues> valuesReference;
|
||||||
BReference<StackFrameValues> valuesReference(values, true);
|
BReference<ExpressionValues> expressionsReference;
|
||||||
|
|
||||||
if (values->Init() != B_OK)
|
if (!updateValues) {
|
||||||
return;
|
VariablesViewState* viewState = fViewStateHistory->GetState(fThread->ID(),
|
||||||
|
functionID);
|
||||||
|
if (viewState != NULL) {
|
||||||
|
values = viewState->Values();
|
||||||
|
valuesReference.SetTo(values);
|
||||||
|
|
||||||
ExpressionValues* expressionValues = new(std::nothrow) ExpressionValues;
|
expressionValues = viewState->GetExpressionValues();
|
||||||
if (expressionValues == NULL)
|
expressionsReference.SetTo(expressionValues);
|
||||||
return;
|
}
|
||||||
BReference<ExpressionValues> expressionReference(expressionValues, true);
|
}
|
||||||
|
|
||||||
if (expressionValues->Init() != B_OK)
|
if (values == NULL) {
|
||||||
return;
|
values = new(std::nothrow) StackFrameValues;
|
||||||
|
if (values == NULL)
|
||||||
|
return;
|
||||||
|
valuesReference.SetTo(values, true);
|
||||||
|
|
||||||
|
if (values->Init() != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
expressionValues = new(std::nothrow) ExpressionValues;
|
||||||
|
if (expressionValues == NULL)
|
||||||
|
return;
|
||||||
|
expressionsReference.SetTo(expressionValues, true);
|
||||||
|
|
||||||
|
if (expressionValues->Init() != B_OK)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// create an empty view state
|
// create an empty view state
|
||||||
VariablesViewState* viewState = new(std::nothrow) VariablesViewState;
|
VariablesViewState* viewState = new(std::nothrow) VariablesViewState;
|
||||||
@@ -2514,7 +2540,7 @@ VariablesView::_SaveViewState() const
|
|||||||
// populate it
|
// populate it
|
||||||
TreeTablePath path;
|
TreeTablePath path;
|
||||||
if (_AddViewStateDescendentNodeInfos(viewState,
|
if (_AddViewStateDescendentNodeInfos(viewState,
|
||||||
fVariableTableModel->Root(), path) != B_OK) {
|
fVariableTableModel->Root(), path, updateValues) != B_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2557,7 +2583,7 @@ VariablesView::_RestoreViewState()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
||||||
void* parent, TreeTablePath& path) const
|
void* parent, TreeTablePath& path, bool updateValues) const
|
||||||
{
|
{
|
||||||
int32 childCount = fVariableTableModel->CountChildren(parent);
|
int32 childCount = fVariableTableModel->CountChildren(parent);
|
||||||
for (int32 i = 0; i < childCount; i++) {
|
for (int32 i = 0; i < childCount; i++) {
|
||||||
@@ -2586,7 +2612,7 @@ VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL && updateValues) {
|
||||||
BVariant variableValueData;
|
BVariant variableValueData;
|
||||||
if (value->ToVariant(variableValueData))
|
if (value->ToVariant(variableValueData))
|
||||||
error = viewState->Values()->SetValue(id, componentPath,
|
error = viewState->Values()->SetValue(id, componentPath,
|
||||||
@@ -2596,13 +2622,14 @@ VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recurse
|
// recurse
|
||||||
error = _AddViewStateDescendentNodeInfos(viewState, node, path);
|
error = _AddViewStateDescendentNodeInfos(viewState, node, path,
|
||||||
|
updateValues);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
ExpressionValueNodeChild* child
|
ExpressionValueNodeChild* child
|
||||||
= dynamic_cast<ExpressionValueNodeChild*>(node->NodeChild());
|
= dynamic_cast<ExpressionValueNodeChild*>(node->NodeChild());
|
||||||
if (child != NULL && value != NULL) {
|
if (child != NULL && value != NULL && updateValues) {
|
||||||
BVariant variableValueData;
|
BVariant variableValueData;
|
||||||
if (value->ToVariant(variableValueData)) {
|
if (value->ToVariant(variableValueData)) {
|
||||||
FunctionID* id = fStackFrame->Function()->GetFunctionID();
|
FunctionID* id = fStackFrame->Function()->GetFunctionID();
|
||||||
|
|||||||
@@ -96,12 +96,13 @@ private:
|
|||||||
uint32 what, ContextActionList* actions,
|
uint32 what, ContextActionList* actions,
|
||||||
BMessage*& _message);
|
BMessage*& _message);
|
||||||
void _FinishContextMenu(bool force);
|
void _FinishContextMenu(bool force);
|
||||||
void _SaveViewState() const;
|
void _SaveViewState(bool updateValues) const;
|
||||||
void _RestoreViewState();
|
void _RestoreViewState();
|
||||||
status_t _AddViewStateDescendentNodeInfos(
|
status_t _AddViewStateDescendentNodeInfos(
|
||||||
VariablesViewState* viewState,
|
VariablesViewState* viewState,
|
||||||
void* parent,
|
void* parent,
|
||||||
TreeTablePath& path) const;
|
TreeTablePath& path,
|
||||||
|
bool updateValues) const;
|
||||||
status_t _ApplyViewStateDescendentNodeInfos(
|
status_t _ApplyViewStateDescendentNodeInfos(
|
||||||
VariablesViewState* viewState,
|
VariablesViewState* viewState,
|
||||||
void* parent,
|
void* parent,
|
||||||
|
|||||||
Reference in New Issue
Block a user