1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-08 12:40:44 +00:00

Prevent cyclic reference between script and its members

This commit is contained in:
Pedro J. Estébanez
2020-09-10 01:26:07 +02:00
parent d84954a281
commit 95828161d4
3 changed files with 19 additions and 12 deletions

View File

@@ -76,7 +76,7 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N
} }
} }
GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const { GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) const {
if (!p_datatype.is_set() || !p_datatype.is_hard_type()) { if (!p_datatype.is_set() || !p_datatype.is_hard_type()) {
return GDScriptDataType(); return GDScriptDataType();
} }
@@ -98,7 +98,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
} break; } break;
case GDScriptParser::DataType::SCRIPT: { case GDScriptParser::DataType::SCRIPT: {
result.kind = GDScriptDataType::SCRIPT; result.kind = GDScriptDataType::SCRIPT;
result.script_type = p_datatype.script_type; result.script_type = Ref<Script>(p_datatype.script_type).ptr();
result.native_type = result.script_type->get_instance_base_type(); result.native_type = result.script_type->get_instance_base_type();
} break; } break;
case GDScriptParser::DataType::CLASS: { case GDScriptParser::DataType::CLASS: {
@@ -124,11 +124,11 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
names.pop_back(); names.pop_back();
} }
result.kind = GDScriptDataType::GDSCRIPT; result.kind = GDScriptDataType::GDSCRIPT;
result.script_type = script; result.script_type = script.ptr();
result.native_type = script->get_instance_base_type(); result.native_type = script->get_instance_base_type();
} else { } else {
result.kind = GDScriptDataType::GDSCRIPT; result.kind = GDScriptDataType::GDSCRIPT;
result.script_type = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path); result.script_type = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path).ptr();
result.native_type = p_datatype.native_type; result.native_type = p_datatype.native_type;
} }
} }
@@ -149,6 +149,12 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
} }
} }
// Only hold strong reference to the script if it's not the owner of the
// element qualified with this type, to avoid cyclic references (leaks).
if (result.script_type && result.script_type != p_owner) {
result.script_type_ref = Ref<Script>(result.script_type);
}
return result; return result;
} }
@@ -1668,7 +1674,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
func_name = p_func->identifier->name; func_name = p_func->identifier->name;
is_static = p_func->is_static; is_static = p_func->is_static;
rpc_mode = p_func->rpc_mode; rpc_mode = p_func->rpc_mode;
return_type = _gdtype_from_datatype(p_func->get_datatype()); return_type = _gdtype_from_datatype(p_func->get_datatype(), p_script);
} else { } else {
if (p_for_ready) { if (p_for_ready) {
func_name = "_ready"; func_name = "_ready";
@@ -1685,7 +1691,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
if (p_func) { if (p_func) {
for (int i = 0; i < p_func->parameters.size(); i++) { for (int i = 0; i < p_func->parameters.size(); i++) {
const GDScriptParser::ParameterNode *parameter = p_func->parameters[i]; const GDScriptParser::ParameterNode *parameter = p_func->parameters[i];
GDScriptDataType par_type = _gdtype_from_datatype(parameter->get_datatype()); GDScriptDataType par_type = _gdtype_from_datatype(parameter->get_datatype(), p_script);
uint32_t par_addr = codegen.generator->add_parameter(parameter->identifier->name, parameter->default_value != nullptr, par_type); uint32_t par_addr = codegen.generator->add_parameter(parameter->identifier->name, parameter->default_value != nullptr, par_type);
codegen.parameters[parameter->identifier->name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::FUNCTION_PARAMETER, par_addr, par_type); codegen.parameters[parameter->identifier->name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::FUNCTION_PARAMETER, par_addr, par_type);
@@ -1830,7 +1836,7 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP
return_type.kind = GDScriptDataType::BUILTIN; return_type.kind = GDScriptDataType::BUILTIN;
return_type.builtin_type = Variant::NIL; return_type.builtin_type = Variant::NIL;
} else { } else {
return_type = _gdtype_from_datatype(p_variable->get_datatype()); return_type = _gdtype_from_datatype(p_variable->get_datatype(), p_script);
} }
codegen.generator->write_start(p_script, func_name, false, p_variable->rpc_mode, return_type); codegen.generator->write_start(p_script, func_name, false, p_variable->rpc_mode, return_type);
@@ -1927,7 +1933,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
p_script->native = native; p_script->native = native;
} break; } break;
case GDScriptDataType::GDSCRIPT: { case GDScriptDataType::GDSCRIPT: {
Ref<GDScript> base = base_type.script_type; Ref<GDScript> base = Ref<GDScript>(base_type.script_type);
p_script->base = base; p_script->base = base;
p_script->_base = base.ptr(); p_script->_base = base.ptr();
@@ -1994,7 +2000,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
break; break;
} }
minfo.rpc_mode = variable->rpc_mode; minfo.rpc_mode = variable->rpc_mode;
minfo.data_type = _gdtype_from_datatype(variable->get_datatype()); minfo.data_type = _gdtype_from_datatype(variable->get_datatype(), p_script);
PropertyInfo prop_info = minfo.data_type; PropertyInfo prop_info = minfo.data_type;
prop_info.name = name; prop_info.name = name;

View File

@@ -84,7 +84,7 @@ class GDScriptCompiler {
Ref<Script> script = obj->get_script(); Ref<Script> script = obj->get_script();
if (script.is_valid()) { if (script.is_valid()) {
type.script_type = script; type.script_type = script.ptr();
Ref<GDScript> gdscript = script; Ref<GDScript> gdscript = script;
if (gdscript.is_valid()) { if (gdscript.is_valid()) {
type.kind = GDScriptDataType::GDSCRIPT; type.kind = GDScriptDataType::GDSCRIPT;
@@ -125,7 +125,7 @@ class GDScriptCompiler {
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::BinaryOpNode *on, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::BinaryOpNode *on, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::ExpressionNode *p_left_operand, const GDScriptParser::ExpressionNode *p_right_operand, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::ExpressionNode *p_left_operand, const GDScriptParser::ExpressionNode *p_right_operand, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const; GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner = nullptr) const;
GDScriptCodeGenerator::Address _parse_assign_right_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::AssignmentNode *p_assignmentint, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); GDScriptCodeGenerator::Address _parse_assign_right_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::AssignmentNode *p_assignmentint, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
GDScriptCodeGenerator::Address _parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root = false, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); GDScriptCodeGenerator::Address _parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root = false, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());

View File

@@ -56,7 +56,8 @@ struct GDScriptDataType {
bool has_type = false; bool has_type = false;
Variant::Type builtin_type = Variant::NIL; Variant::Type builtin_type = Variant::NIL;
StringName native_type; StringName native_type;
Ref<Script> script_type; Script *script_type = nullptr;
Ref<Script> script_type_ref;
bool is_type(const Variant &p_variant, bool p_allow_implicit_conversion = false) const { bool is_type(const Variant &p_variant, bool p_allow_implicit_conversion = false) const {
if (!has_type) { if (!has_type) {