Comments (14)
FWIW in vimspector, we don't assume that variablesRefernce is persistent and still maintain the expansion state of variables; You can actually persist/compare the 'name' from the variables response (assuming you have state to associate the request with the parent).
I don't think new UUID is completely necessary, unless you think that the above doesn't work (I've never seen it go wrong)
def _ConsumeVariables( self, draw, parent, message ):
new_variables = []
for variable_body in message[ 'body' ][ 'variables' ]:
if parent.variables is None:
parent.variables = []
# Find the variable in parent
found = False
for index, v in enumerate( parent.variables ):
if v.variable[ 'name' ] == variable_body[ 'name' ]:
variable = v
found = True
break
if not found:
variable = Variable( parent, variable_body )
else:
variable.Update( variable_body )
from debug-adapter-protocol.
Yes, DAP does not specify the lifetime of a variablesReference
.
That was an oversight.
Let's fix this...
Since DAP was inspired by the (now legacy) V8 debugger protocol, I've tried to find something related to "lifetime of object handles":
All objects exposed through the debugger is assigned an ID called a handle. This handle is serialized and can be used to identify objects. A handle has a certain lifetime after which it will no longer refer to the same object. Currently the lifetime of handles match the processing of a debug event. For each debug event handles are recycled.
This essentially describes what the DAP client "VS Code" assumes:
whenever a DAP "stopped" event is received, VS Code retrieves the stack frames for the location, and then the frame's scopes, and from the scopes the individual variables. While execution is stopped, all variablesReference
received for that stack will remain valid (refer to the same variables). But as soon as execution resumes, the variablesReferences
become invalid (and the DAP client should no longer use them). On the next "stopped" event, variablesReferences
can reuse the previous values.
Instead of duplicating this "lifetime explanation" in lots of places in the DAP spec, I suggest that we create a new section in the DAP Overview, which can then be referenced from the DAP spec.
In addition we can add the following "recipe" for how to manage variablesReferences
:
The simplest way to manage variablesReferences
in a DA is by using sequentially assigned integer keys that map to the debugger objects representing variables. Whenever a new variableReference
is needed for a variable object, a new key is created by incrementing a counter and then a corresponding association is added to the map.
When execution resumes the counter is set to 0 and the map is cleared.
from debug-adapter-protocol.
well at least in my implementation variablesReference is unique number until stack frame changes, then it is something else.
from debug-adapter-protocol.
Related: microsoft/vscode#25652 (comment) - apparently debug adapters are supposed to have longer-lived variablesReference IDs - although that comment seems to be directly contradicted by microsoft/vscode#25652 (comment)
from debug-adapter-protocol.
I wish variablesReference was just a string. With only 31 bits to work with and no lifetime information, I can't come up with any way to support variableReferences properly that doesn't just consume memory as the debugger is used without ever freeing it.
from debug-adapter-protocol.
Lgtm
from debug-adapter-protocol.
The counter solution seems insufficient to me when considering this:
microsoft/vscode#25652 (comment)
The expansion state of a Variable or Watch tree is preserved across steps if the variablesReference (https://github.com/Microsoft/vscode-debugadapter-node/blob/master/protocol/src/debugProtocol.ts#L1177) doesn't change.
It seems like any solution involving a simple counter would break this requirement whenever a step adds or removes a local variable, causing expanded variables to collapse, which would be really frustrating. It also isn't clear to me whether it would work well with the watch window when, say, the number of items in an array changes.
from debug-adapter-protocol.
- Yes, as an implementation detail VS Code tries to remember the expansion state by associating it with
variablesReference
. This seems to work well in practice. - the use of
variablesReference
in the "Watches" view does not differ from the "Variables" view, so the observed behavior is identical.
If there is a need to make expansion state management more robust, then a new DAP feature would be necessary. E.g. an optional "UUID" hint on DAP's Variable
type. But I'm not sure whether debug adapters could actually provide that UUID easily.
from debug-adapter-protocol.
This seems to work well in practice.
How does it work given the issues I described? Like, if I have two arrays expanded, and after stepping an item is added to array 1, and the contents of array 2 are fetched after array 1, how does an incrementing strategy not change all the variablesReference values in array 2, causing elements within it to collapse? Maybe I'm misunderstanding something. Could you point me to a language implementing this strategy that I could look at the DAP implementation for and also test for myself in VSCode?
If there is a need to make expansion state management more robust, then a new DAP feature would be necessary.
Well, yes. From my perspective it would be sufficient for the debugger to send a message saying that it no longer needs the contents of a variablesReference when all uses of it are collapsed by the user. I will admit this is a quick thought and there may be subtleties I'm missing.
from debug-adapter-protocol.
Yeah, the approach that sort of works seems to be to associate objects with indices in the debugee and accept that they won't be cleaned up until the objects themselves are destroyed.
The actual problem I'm having in practice is that I don't have a literal object for every thing I want to represent as an expandable thing in the debugger, and I'm worried about the performance impact of introducing one. For instance, an object for every call frame (to store the local variable indices) adds overhead to each call. So for things like that I try to represent the "object" as a combination of a thread ID and call frame index, which I can squeeze into 31 bits well enough, but then when I wanted to add another layer to that, 31 bits was insufficient. So I have to go the route of hurting performance just because I can't store enough information in a variablesReference. One solution to that is to make it easier for me to associate variablesReferences with my own data, which leaks memory if there's no cleanup when a variablesReference will never be used again. A different solution, and maybe easier, would be to make variablesReference allowed to be a string, so I can just store whatever I want in there.
from debug-adapter-protocol.
Yes, as an implementation detail VS Code tries to remember the expansion state by associating it with variablesReference
I had this in mind too, but I think it's no longer true. The variable id for expansion state is only computed from the parent id, name, and a dedupe index https://github.com/microsoft/vscode/blob/779e1e9d759c5e191cf4c26c2aba984ccb0df8e3/src/vs/workbench/contrib/debug/common/debugModel.ts#L300
I think this changed here
microsoft/vscode#16031 (comment)
from debug-adapter-protocol.
@roblourens thanks for reminding me of that implementation change.
Now I remember that we tried to fix the issues raised by @MetalSlime0 above by associating the expansion state with the "qualified path" of a variable. With the new implementation it is still possible that an existing expansion state is applied to another unrelated variable that happens to have the same qualified path. But this problem is unrelated to variablesReference
.
@MetalSlime0 with that new information, your concerns about the "counter solution" do no longer apply, correct?
from debug-adapter-protocol.
If variablesReference isn't used at all to track expansion state, that does sound a lot better. I think if you add that information to the documentation it will probably be fine, as long as it's clear to both debugger and debuggee implementors what they can expect the other side to be doing. (I wonder if there are other debuggers out there already that assume variablesReference will stay consistent across steps?)
I still think it would be useful if it was allowed to be a string though. 😀
from debug-adapter-protocol.
Yes, we will update the spec for variablesReference
accordingly.
Changing variablesReference
to become a string (in addition to integer) would require a new capability and an opt-in of all DAP clients.
Since you are the first DA author requesting this, I do not see a pressing need for any DAP client to implement this feature anytime soon. In addition your DA would have to implement the integer based variablesReference
anyways, if you want to support all DAP clients that don't support the string-based variablesReference
.
from debug-adapter-protocol.
Related Issues (20)
- Example on how to launch debug adapter HOT 3
- Standardise the ability for client/DA to use URIs in place of file paths (enabling debugging of non-file:/ sources) HOT 17
- Add additional data fields for breakpoints HOT 11
- Evaluation time out HOT 1
- Clarifications for setExceptionBreakpoints HOT 6
- Ordering of launch, setBreakpoints, and configurationDone HOT 3
- Add a "type" field for SourceBreakpoints HOT 16
- Add a `bytes` range to the DataBreakpointInfo Request HOT 14
- Clarification of the meaning of '?' in a request HOT 1
- Is it always allowed to send requests that control execution? HOT 3
- Proposal: Add new reason `finished` or `stepOut` and optional field `returnValue` to `Stopped Event` HOT 21
- OutputEvent variablesReference lifetime clarification HOT 1
- How does the debugger notify dap client that a breakpoint is disabled? HOT 8
- Proposal: add a document location to the evaluate request for the 'hover' variant. HOT 18
- Help needed : Disassembly a C/C++ frame (function) HOT 2
- Minor inconsistency in "evaluate" description
- Debug Event which is responsible for loading source file in Editor HOT 1
- > Alternatively, a statement that “typically the return value from the last function call should be reported as a Scope named ‘return’” might help with consistency for users.
- Public changelog has no date stamps HOT 1
- [Question][Feature request] is it able to integrate to monaco editor? HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from debug-adapter-protocol.