mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	Prevent cyclic reference between script and its members
This commit is contained in:
		
							parent
							
								
									939ed5dd5b
								
							
						
					
					
						commit
						a0969662cd
					
				
					 5 changed files with 21 additions and 13 deletions
				
			
		| 
						 | 
					@ -111,7 +111,7 @@ bool GDScriptCompiler::_create_binary_operator(CodeGen &codegen, const GDScriptP
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.has_type) {
 | 
						if (!p_datatype.has_type) {
 | 
				
			||||||
		return GDScriptDataType();
 | 
							return GDScriptDataType();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -130,12 +130,12 @@ 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::GDSCRIPT: {
 | 
							case GDScriptParser::DataType::GDSCRIPT: {
 | 
				
			||||||
			result.kind = GDScriptDataType::GDSCRIPT;
 | 
								result.kind = GDScriptDataType::GDSCRIPT;
 | 
				
			||||||
			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: {
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			result.kind = GDScriptDataType::GDSCRIPT;
 | 
								result.kind = GDScriptDataType::GDSCRIPT;
 | 
				
			||||||
			result.script_type = script;
 | 
								result.script_type = Ref<Script>(script).ptr();
 | 
				
			||||||
			result.native_type = script->get_instance_base_type();
 | 
								result.native_type = script->get_instance_base_type();
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
		default: {
 | 
							default: {
 | 
				
			||||||
| 
						 | 
					@ -168,6 +168,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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1684,9 +1690,9 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
 | 
				
			||||||
		gdfunc->rpc_mode = p_func->rpc_mode;
 | 
							gdfunc->rpc_mode = p_func->rpc_mode;
 | 
				
			||||||
		gdfunc->argument_types.resize(p_func->argument_types.size());
 | 
							gdfunc->argument_types.resize(p_func->argument_types.size());
 | 
				
			||||||
		for (int i = 0; i < p_func->argument_types.size(); i++) {
 | 
							for (int i = 0; i < p_func->argument_types.size(); i++) {
 | 
				
			||||||
			gdfunc->argument_types.write[i] = _gdtype_from_datatype(p_func->argument_types[i]);
 | 
								gdfunc->argument_types.write[i] = _gdtype_from_datatype(p_func->argument_types[i], p_script);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gdfunc->return_type = _gdtype_from_datatype(p_func->return_type);
 | 
							gdfunc->return_type = _gdtype_from_datatype(p_func->return_type, p_script);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		gdfunc->_static = false;
 | 
							gdfunc->_static = false;
 | 
				
			||||||
		gdfunc->rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
 | 
							gdfunc->rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
 | 
				
			||||||
| 
						 | 
					@ -1869,7 +1875,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();
 | 
				
			||||||
			p_script->member_indices = base->member_indices;
 | 
								p_script->member_indices = base->member_indices;
 | 
				
			||||||
| 
						 | 
					@ -1902,7 +1908,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
 | 
				
			||||||
		minfo.setter = p_class->variables[i].setter;
 | 
							minfo.setter = p_class->variables[i].setter;
 | 
				
			||||||
		minfo.getter = p_class->variables[i].getter;
 | 
							minfo.getter = p_class->variables[i].getter;
 | 
				
			||||||
		minfo.rpc_mode = p_class->variables[i].rpc_mode;
 | 
							minfo.rpc_mode = p_class->variables[i].rpc_mode;
 | 
				
			||||||
		minfo.data_type = _gdtype_from_datatype(p_class->variables[i].data_type);
 | 
							minfo.data_type = _gdtype_from_datatype(p_class->variables[i].data_type, p_script);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		PropertyInfo prop_info = minfo.data_type;
 | 
							PropertyInfo prop_info = minfo.data_type;
 | 
				
			||||||
		prop_info.name = name;
 | 
							prop_info.name = name;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ class GDScriptCompiler {
 | 
				
			||||||
	bool _create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level);
 | 
						bool _create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level);
 | 
				
			||||||
	bool _create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false, int p_index_addr = 0);
 | 
						bool _create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false, int p_index_addr = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const;
 | 
						GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner = NULL) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr = 0);
 | 
						int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr = 0);
 | 
				
			||||||
	int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false, int p_index_addr = 0);
 | 
						int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false, int p_index_addr = 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -644,7 +644,7 @@ static GDScriptCompletionIdentifier _type_from_gdtype(const GDScriptDataType &p_
 | 
				
			||||||
	ci.type.has_type = true;
 | 
						ci.type.has_type = true;
 | 
				
			||||||
	ci.type.builtin_type = p_gdtype.builtin_type;
 | 
						ci.type.builtin_type = p_gdtype.builtin_type;
 | 
				
			||||||
	ci.type.native_type = p_gdtype.native_type;
 | 
						ci.type.native_type = p_gdtype.native_type;
 | 
				
			||||||
	ci.type.script_type = p_gdtype.script_type;
 | 
						ci.type.script_type = Ref<Script>(p_gdtype.script_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (p_gdtype.kind) {
 | 
						switch (p_gdtype.kind) {
 | 
				
			||||||
		case GDScriptDataType::UNINITIALIZED: {
 | 
							case GDScriptDataType::UNINITIALIZED: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,8 @@ struct GDScriptDataType {
 | 
				
			||||||
	} kind;
 | 
						} kind;
 | 
				
			||||||
	Variant::Type builtin_type;
 | 
						Variant::Type builtin_type;
 | 
				
			||||||
	StringName native_type;
 | 
						StringName native_type;
 | 
				
			||||||
	Ref<Script> script_type;
 | 
						Script *script_type;
 | 
				
			||||||
 | 
						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) return true; // Can't type check
 | 
							if (!has_type) return true; // Can't type check
 | 
				
			||||||
| 
						 | 
					@ -149,7 +150,8 @@ struct GDScriptDataType {
 | 
				
			||||||
	GDScriptDataType() :
 | 
						GDScriptDataType() :
 | 
				
			||||||
			has_type(false),
 | 
								has_type(false),
 | 
				
			||||||
			kind(UNINITIALIZED),
 | 
								kind(UNINITIALIZED),
 | 
				
			||||||
			builtin_type(Variant::NIL) {}
 | 
								builtin_type(Variant::NIL),
 | 
				
			||||||
 | 
								script_type(NULL) {}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GDScriptFunction {
 | 
					class GDScriptFunction {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6055,7 +6055,7 @@ GDScriptParser::DataType GDScriptParser::_type_from_gdtype(const GDScriptDataTyp
 | 
				
			||||||
	result.has_type = true;
 | 
						result.has_type = true;
 | 
				
			||||||
	result.builtin_type = p_gdtype.builtin_type;
 | 
						result.builtin_type = p_gdtype.builtin_type;
 | 
				
			||||||
	result.native_type = p_gdtype.native_type;
 | 
						result.native_type = p_gdtype.native_type;
 | 
				
			||||||
	result.script_type = p_gdtype.script_type;
 | 
						result.script_type = Ref<Script>(p_gdtype.script_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (p_gdtype.kind) {
 | 
						switch (p_gdtype.kind) {
 | 
				
			||||||
		case GDScriptDataType::UNINITIALIZED: {
 | 
							case GDScriptDataType::UNINITIALIZED: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue