Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix id encoded with incorrect signedness. #662

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
32 changes: 20 additions & 12 deletions src/debugger/godot3/debug_session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,24 @@ export class GodotDebugSession extends LoggingDebugSession {
return;
}

const reference = this.all_scopes[args.variablesReference];
let reference = this.all_scopes[args.variablesReference];
let variables: DebugProtocol.Variable[];

if (reference.value?.id !== undefined) {
const inspected_object: Subject = new Subject();

this.inspect_callbacks.set(
BigInt(reference.value.id),
(_class_name, _variable) => inspected_object.notify()
);

this.add_to_inspections([ reference ]);

await inspected_object.wait(2000);

reference = this.all_scopes[args.variablesReference];
}

if (!reference.sub_values) {
variables = [];
} else {
Expand Down Expand Up @@ -385,12 +400,7 @@ export class GodotDebugSession extends LoggingDebugSession {
this.append_variable(va);
});

this.add_to_inspections();

if (this.ongoing_inspections.length === 0) {
this.previous_inspections = [];
this.got_scope.notify();
}
this.got_scope.notify();
}

public set_inspection(id: bigint, replacement: GodotVariable) {
Expand All @@ -413,16 +423,14 @@ export class GodotDebugSession extends LoggingDebugSession {

this.previous_inspections.push(id);

// this.add_to_inspections();

if (this.ongoing_inspections.length === 0) {
this.previous_inspections = [];
this.got_scope.notify();
}
}

private add_to_inspections() {
this.all_scopes.forEach((va) => {
public add_to_inspections(variables: GodotVariable[]) {
variables?.forEach((va) => {
if (va && va.value instanceof ObjectId) {
if (
!this.ongoing_inspections.includes(va.value.id) &&
Expand Down Expand Up @@ -543,7 +551,7 @@ export class GodotDebugSession extends LoggingDebugSession {
if (variable.sub_values) {
variable.sub_values.forEach((va, i) => {
va.scope_path = base_path;
this.append_variable(va, index ? index + i + 1 : undefined);
this.append_variable(va);
});
}
}
Expand Down
34 changes: 0 additions & 34 deletions src/debugger/godot3/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,40 +34,6 @@ export function is_variable_built_in_type(va: GodotVariable) {
return ["number", "bigint", "boolean", "string"].some(x => x == type);
}

export function build_sub_values(va: GodotVariable) {
const value = va.value;

let subValues: GodotVariable[] = undefined;

if (value && Array.isArray(value)) {
subValues = value.map((va, i) => {
return { name: `${i}`, value: va } as GodotVariable;
});
} else if (value instanceof Map) {
subValues = Array.from(value.keys()).map((va) => {
if (typeof va["stringify_value"] === "function") {
return {
name: `${va.type_name()}${va.stringify_value()}`,
value: value.get(va),
} as GodotVariable;
} else {
return {
name: `${va}`,
value: value.get(va),
} as GodotVariable;
}
});
} else if (value && typeof value["sub_values"] === "function") {
subValues = value.sub_values().map((sva) => {
return { name: sva.name, value: sva.value } as GodotVariable;
});
}

va.sub_values = subValues;

subValues?.forEach(build_sub_values);
}

export function parse_variable(va: GodotVariable, i?: number) {
const value = va.value;
let rendered_value = "";
Expand Down
48 changes: 44 additions & 4 deletions src/debugger/godot3/server_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { StoppedEvent, TerminatedEvent } from "@vscode/debugadapter";
import { VariantEncoder } from "./variables/variant_encoder";
import { VariantDecoder } from "./variables/variant_decoder";
import { RawObject } from "./variables/variants";
import { GodotStackFrame, GodotStackVars } from "../debug_runtime";
import { GodotStackFrame, GodotVariable, GodotStackVars } from "../debug_runtime";
import { GodotDebugSession } from "./debug_session";
import { parse_next_scene_node, split_buffers, build_sub_values } from "./helpers";
import { parse_next_scene_node, split_buffers } from "./helpers";
import { get_configuration, get_free_port, createLogger, verify_godot_version, get_project_version } from "../../utils";
import { prompt_for_godot_executable } from "../../utils/prompts";
import { subProcess, killSubProcesses } from "../../utils/subspawn";
Expand Down Expand Up @@ -392,7 +392,7 @@ export class ServerController {
rawObject.set(prop[0], prop[5]);
});
const inspectedVariable = { name: "", value: rawObject };
build_sub_values(inspectedVariable);
ServerController.build_sub_values(inspectedVariable);
if (this.session.inspect_callbacks.has(BigInt(id))) {
this.session.inspect_callbacks.get(BigInt(id))(
inspectedVariable.name,
Expand Down Expand Up @@ -551,8 +551,48 @@ export class ServerController {
stackVars.globals.push({ name: parameters[i++], value: parameters[i++] });
}

stackVars.forEach(item => build_sub_values(item));
stackVars.forEach(item => ServerController.build_sub_values(item));

this.session.set_scopes(stackVars);
}

private static build_sub_values(va: GodotVariable) {
const value = va.value;

let subValues: GodotVariable[] = undefined;

if (value && Array.isArray(value)) {
subValues = value.map((va, i) => {
return {
name: `${i}`,
value: va,
} as GodotVariable;
});
} else if (value instanceof Map) {
subValues = Array.from(value.keys()).map((va) => {
if (typeof va["stringify_value"] === "function") {
return {
name: `${va.type_name()}${va.stringify_value()}`,
value: value.get(va),
} as GodotVariable;
} else {
return {
name: `${va}`,
value: value.get(va),
} as GodotVariable;
}
});
} else if (value && typeof value["sub_values"] === "function") {
subValues = value.sub_values().map((sva) => {
return {
name: sva.name,
value: sva.value,
} as GodotVariable;
});
}

va.sub_values = subValues;

subValues?.forEach(ServerController.build_sub_values);
}
}
33 changes: 21 additions & 12 deletions src/debugger/godot4/debug_session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,25 @@ export class GodotDebugSession extends LoggingDebugSession {
return;
}

const reference = this.all_scopes[args.variablesReference];
let reference = this.all_scopes[args.variablesReference];
let variables: DebugProtocol.Variable[];

if (reference.value?.id !== undefined) {
const inspected_object: Subject = new Subject();

this.inspect_callbacks.set(
BigInt(reference.value.id),
(_class_name, _variable) => inspected_object.notify()
);

this.add_to_inspections([ reference ]);

await inspected_object.wait(2000);

reference = this.all_scopes[args.variablesReference];
}


if (!reference.sub_values) {
variables = [];
} else {
Expand Down Expand Up @@ -385,12 +401,7 @@ export class GodotDebugSession extends LoggingDebugSession {
this.append_variable(va);
});

this.add_to_inspections();

if (this.ongoing_inspections.length === 0) {
this.previous_inspections = [];
this.got_scope.notify();
}
this.got_scope.notify();
}

public set_inspection(id: bigint, replacement: GodotVariable) {
Expand All @@ -413,16 +424,14 @@ export class GodotDebugSession extends LoggingDebugSession {

this.previous_inspections.push(id);

// this.add_to_inspections();

if (this.ongoing_inspections.length === 0) {
this.previous_inspections = [];
this.got_scope.notify();
}
}

private add_to_inspections() {
this.all_scopes.forEach((va) => {
public add_to_inspections(variables: GodotVariable[]) {
variables?.forEach((va) => {
if (va && va.value instanceof ObjectId) {
if (
!this.ongoing_inspections.includes(va.value.id) &&
Expand Down Expand Up @@ -544,7 +553,7 @@ export class GodotDebugSession extends LoggingDebugSession {
if (variable.sub_values) {
variable.sub_values.forEach((va, i) => {
va.scope_path = base_path;
this.append_variable(va, index ? index + i + 1 : undefined);
this.append_variable(va);
});
}
}
Expand Down
34 changes: 0 additions & 34 deletions src/debugger/godot4/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,40 +36,6 @@ export function is_variable_built_in_type(va: GodotVariable) {
return ["number", "bigint", "boolean", "string"].some(x => x == type);
}

export function build_sub_values(va: GodotVariable) {
const value = va.value;

let subValues: GodotVariable[] = undefined;

if (value && Array.isArray(value)) {
subValues = value.map((va, i) => {
return { name: `${i}`, value: va } as GodotVariable;
});
} else if (value instanceof Map) {
subValues = Array.from(value.keys()).map((va) => {
if (typeof va["stringify_value"] === "function") {
return {
name: `${va.type_name()}${va.stringify_value()}`,
value: value.get(va),
} as GodotVariable;
} else {
return {
name: `${va}`,
value: value.get(va),
} as GodotVariable;
}
});
} else if (value && typeof value["sub_values"] === "function") {
subValues = value.sub_values().map((sva) => {
return { name: sva.name, value: sva.value } as GodotVariable;
});
}

va.sub_values = subValues;

subValues?.forEach(build_sub_values);
}

export function parse_variable(va: GodotVariable, i?: number) {
const value = va.value;
let rendered_value = "";
Expand Down
60 changes: 55 additions & 5 deletions src/debugger/godot4/server_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { VariantDecoder } from "./variables/variant_decoder";
import { RawObject } from "./variables/variants";
import { GodotStackFrame, GodotVariable, GodotStackVars } from "../debug_runtime";
import { GodotDebugSession } from "./debug_session";
import { parse_next_scene_node, split_buffers, build_sub_values } from "./helpers";
import { parse_next_scene_node, split_buffers } from "./helpers";
import { get_configuration, get_free_port, createLogger, verify_godot_version, get_project_version } from "../../utils";
import { prompt_for_godot_executable } from "../../utils/prompts";
import { subProcess, killSubProcesses } from "../../utils/subspawn";
Expand Down Expand Up @@ -386,12 +386,18 @@ export class ServerController {
id = id + BigInt(2) ** BigInt(64);
}

// message:inspect_object returns the id as an unsigned 64 bit integer, but it is decoded as a signed 64 bit integer,
// thus we need to convert it to its equivalent unsigned value here.
if (id < 0) {
id = id + BigInt(2) ** BigInt(64);
}

const rawObject = new RawObject(className);
properties.forEach((prop) => {
rawObject.set(prop[0], prop[5]);
});
const inspectedVariable = { name: "", value: rawObject };
build_sub_values(inspectedVariable);
ServerController.build_sub_values(inspectedVariable);
if (this.session.inspect_callbacks.has(BigInt(id))) {
this.session.inspect_callbacks.get(BigInt(id))(
inspectedVariable.name,
Expand Down Expand Up @@ -419,8 +425,12 @@ export class ServerController {
break;
}
case "stack_frame_vars": {
this.partialStackVars.reset(command.parameters[0]);
this.session.set_scopes(this.partialStackVars);
const stack_var_count = command.parameters[0];
this.partialStackVars.reset(stack_var_count);

if(stack_var_count <= 0)
this.session.set_scopes(this.partialStackVars);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if set_scopes is called here every time the stack_frame_vars command is handled, it leads to the issue seen in the second image in the following comment:

Restarting debugging, with custom_object expanded from previous debug session. image

#662 (comment)

This if statement makes sure GodotDebugSession.ongoing_inspections is not of length 0 (if Objects are present in the current stack frame) the first time set_scopes is called, thus preventing GodotDebugSession.got_scope.notify being called too early.


break;
}
case "stack_frame_var": {
Expand Down Expand Up @@ -559,7 +569,7 @@ export class ServerController {
}

const variable: GodotVariable = { name, value, type };
build_sub_values(variable);
ServerController.build_sub_values(variable);

const scopeName = ["locals", "members", "globals"][scope];
this.partialStackVars[scopeName].push(variable);
Expand All @@ -569,4 +579,44 @@ export class ServerController {
this.session.set_scopes(this.partialStackVars);
}
}

private static build_sub_values(va: GodotVariable) {
const value = va.value;

let subValues: GodotVariable[] = undefined;

if (value && Array.isArray(value)) {
subValues = value.map((va, i) => {
return {
name: `${i}`,
value: va,
} as GodotVariable;
});
} else if (value instanceof Map) {
subValues = Array.from(value.keys()).map((va) => {
if (typeof va["stringify_value"] === "function") {
return {
name: `${va.type_name()}${va.stringify_value()}`,
value: value.get(va),
} as GodotVariable;
} else {
return {
name: `${va}`,
value: value.get(va),
} as GodotVariable;
}
});
} else if (value && typeof value["sub_values"] === "function") {
subValues = value.sub_values().map((sva) => {
return {
name: sva.name,
value: sva.value,
} as GodotVariable;
});
}

va.sub_values = subValues;

subValues?.forEach(ServerController.build_sub_values.bind(this));
}
}
Loading