mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
GDScript call stack as reverse linked list with fixed coroutines
* GDScript call stack as reverse linked list with issues fixed (originally proposed in 91006). * Fix coroutine issues with call stack by resuming async call chain inside `GDScriptFunction::call()`. * This fixes corrupted line numbers for coroutines in the debugger and backtrace (106489). Co-authored-by: Juan Linietsky <reduzio@gmail.com>
This commit is contained in:
parent
e1b4101e34
commit
a095c5e3fa
7 changed files with 90 additions and 79 deletions
|
@ -656,7 +656,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
|
||||
String err_text;
|
||||
|
||||
GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line);
|
||||
GDScriptLanguage::CallLevel call_level;
|
||||
GDScriptLanguage::get_singleton()->enter_function(&call_level, p_instance, this, stack, &ip, &line);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
#define GD_ERR_BREAK(m_cond) \
|
||||
|
@ -2548,7 +2549,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
// Is this even possible to be null at this point?
|
||||
if (obj) {
|
||||
if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
|
||||
result = Signal(obj, "completed");
|
||||
result = Signal(obj, SNAME("completed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2595,6 +2596,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
gdfs->state.defarg = defarg;
|
||||
gdfs->function = this;
|
||||
|
||||
if (p_state) {
|
||||
// Pass down the signal from the first state.
|
||||
gdfs->state.completed = p_state->completed;
|
||||
} else {
|
||||
gdfs->state.completed = Signal(gdfs.ptr(), SNAME("completed"));
|
||||
}
|
||||
|
||||
retvalue = gdfs;
|
||||
|
||||
Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONE_SHOT);
|
||||
|
@ -3980,5 +3988,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
|
||||
call_depth--;
|
||||
|
||||
if (p_state && !awaited) {
|
||||
// This means we have finished executing a resumed function and it was not awaited again.
|
||||
|
||||
// Signal the next function-state to resume.
|
||||
const Variant *args[1] = { &retvalue };
|
||||
p_state->completed.emit(args, 1);
|
||||
|
||||
// Exit function only after executing the remaining function states to preserve async call stack.
|
||||
GDScriptLanguage::get_singleton()->exit_function();
|
||||
}
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue