diff options
Diffstat (limited to 'modules/gdscript/gdscript.cpp')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 224 |
1 files changed, 125 insertions, 99 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 19b264d764..73b1e44db3 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -49,11 +49,12 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/core_constants.h" -#include "core/core_string_names.h" #include "core/io/file_access.h" #include "core/io/file_access_encrypted.h" #include "core/os/os.h" +#include "scene/scene_string_names.h" + #ifdef TOOLS_ENABLED #include "editor/editor_paths.h" #endif @@ -114,7 +115,7 @@ Variant GDScriptNativeClass::callp(const StringName &p_method, const Variant **p } GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { - if (p_script->initializer) { + if (likely(p_script->valid) && p_script->initializer) { return p_script->initializer; } else { GDScript *base_src = p_script->_base; @@ -135,7 +136,11 @@ void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance } } ERR_FAIL_NULL(p_script->implicit_initializer); - p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error); + if (likely(valid)) { + p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error); + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + } } GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) { @@ -395,6 +400,8 @@ bool GDScript::get_property_default_value(const StringName &p_property, Variant } ScriptInstance *GDScript::instance_create(Object *p_this) { + ERR_FAIL_COND_V_MSG(!valid, nullptr, "Script is invalid!"); + GDScript *top = this; while (top->_base) { top = top->_base; @@ -659,7 +666,7 @@ String GDScript::_get_debug_path() const { } Error GDScript::_static_init() { - if (static_initializer) { + if (likely(valid) && static_initializer) { Callable::CallError call_err; static_initializer->call(nullptr, nullptr, 0, call_err); if (call_err.error != Callable::CallError::CALL_OK) { @@ -676,8 +683,6 @@ Error GDScript::_static_init() { return err; } -#ifdef TOOLS_ENABLED - void GDScript::_static_default_init() { for (const KeyValue<StringName, MemberInfo> &E : static_variables_indices) { const GDScriptDataType &type = E.value.data_type; @@ -699,6 +704,8 @@ void GDScript::_static_default_init() { } } +#ifdef TOOLS_ENABLED + void GDScript::_save_old_static_data() { old_static_variables_indices = static_variables_indices; old_static_variables = static_variables; @@ -768,8 +775,16 @@ Error GDScript::reload(bool p_keep_state) { if (GDScriptCache::has_parser(source_path)) { Error err = OK; Ref<GDScriptParserRef> parser_ref = GDScriptCache::get_parser(source_path, GDScriptParserRef::EMPTY, err); - if (parser_ref.is_valid() && parser_ref->get_source_hash() != source.hash()) { - GDScriptCache::remove_parser(source_path); + if (parser_ref.is_valid()) { + uint32_t source_hash; + if (!binary_tokens.is_empty()) { + source_hash = hash_djb2_buffer(binary_tokens.ptr(), binary_tokens.size()); + } else { + source_hash = source.hash(); + } + if (parser_ref->get_source_hash() != source_hash) { + GDScriptCache::remove_parser(source_path); + } } } } @@ -862,9 +877,6 @@ Error GDScript::reload(bool p_keep_state) { #ifdef TOOLS_ENABLED if (can_run && p_keep_state) { _restore_old_static_data(); - } else if (!can_run) { - // Initialize static variables with sane default values even if the constructor isn't called. - _static_default_init(); } #endif @@ -903,11 +915,13 @@ void GDScript::unload_static() const { Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *top = this; while (top) { - HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method); - if (E) { - ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script."); + if (likely(top->valid)) { + HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method); + if (E) { + ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script."); - return E->value->call(nullptr, p_args, p_argcount, r_error); + return E->value->call(nullptr, p_args, p_argcount, r_error); + } } top = top->_base; } @@ -936,7 +950,7 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { { HashMap<StringName, MemberInfo>::ConstIterator E = top->static_variables_indices.find(p_name); if (E) { - if (E->value.getter) { + if (likely(top->valid) && E->value.getter) { Callable::CallError ce; r_ret = const_cast<GDScript *>(this)->callp(E->value.getter, nullptr, 0, ce); return true; @@ -946,7 +960,7 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { } } - { + if (likely(top->valid)) { HashMap<StringName, GDScriptFunction *>::ConstIterator E = top->member_functions.find(p_name); if (E && E->value->is_static()) { if (top->rpc_config.has(p_name)) { @@ -975,7 +989,7 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { bool GDScript::_set(const StringName &p_name, const Variant &p_value) { if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) { set_source_code(p_value); - reload(); + reload(true); return true; } @@ -993,7 +1007,7 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) { return false; } } - if (member->setter) { + if (likely(top->valid) && member->setter) { const Variant *args = &value; Callable::CallError err; callp(member->setter, &args, 1, err); @@ -1642,7 +1656,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { return false; } } - if (member->setter) { + if (likely(script->valid) && member->setter) { const Variant *args = &value; Callable::CallError err; callp(member->setter, &args, 1, err); @@ -1669,7 +1683,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { return false; } } - if (member->setter) { + if (likely(sptr->valid) && member->setter) { const Variant *args = &value; Callable::CallError err; callp(member->setter, &args, 1, err); @@ -1681,7 +1695,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { } } - { + if (likely(sptr->valid)) { HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); if (E) { Variant name = p_name; @@ -1705,7 +1719,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { { HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = script->member_indices.find(p_name); if (E) { - if (E->value.getter) { + if (likely(script->valid) && E->value.getter) { Callable::CallError err; r_ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err); if (err.error == Callable::CallError::CALL_OK) { @@ -1730,7 +1744,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { { HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = sptr->static_variables_indices.find(p_name); if (E) { - if (E->value.getter) { + if (likely(sptr->valid) && E->value.getter) { Callable::CallError ce; r_ret = const_cast<GDScript *>(sptr)->callp(E->value.getter, nullptr, 0, ce); return true; @@ -1748,7 +1762,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } } - { + if (likely(sptr->valid)) { HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_name); if (E) { if (sptr->rpc_config.has(p_name)) { @@ -1768,7 +1782,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } } - { + if (likely(sptr->valid)) { HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); if (E) { Variant name = p_name; @@ -1808,13 +1822,15 @@ void GDScriptInstance::validate_property(PropertyInfo &p_property) const { const GDScript *sptr = script.ptr(); while (sptr) { - HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property); - if (E) { - Callable::CallError err; - Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); - if (err.error == Callable::CallError::CALL_OK) { - p_property = PropertyInfo::from_dict(property); - return; + if (likely(sptr->valid)) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property); + if (E) { + Callable::CallError err; + Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); + if (err.error == Callable::CallError::CALL_OK) { + p_property = PropertyInfo::from_dict(property); + return; + } } } sptr = sptr->_base; @@ -1828,39 +1844,41 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const List<PropertyInfo> props; while (sptr) { - HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); - if (E) { - Callable::CallError err; - Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err); - if (err.error == Callable::CallError::CALL_OK) { - ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries."); - - Array arr = ret; - for (int i = 0; i < arr.size(); i++) { - Dictionary d = arr[i]; - ERR_CONTINUE(!d.has("name")); - ERR_CONTINUE(!d.has("type")); - - PropertyInfo pinfo; - pinfo.name = d["name"]; - pinfo.type = Variant::Type(d["type"].operator int()); - if (d.has("hint")) { - pinfo.hint = PropertyHint(d["hint"].operator int()); - } - if (d.has("hint_string")) { - pinfo.hint_string = d["hint_string"]; - } - if (d.has("usage")) { - pinfo.usage = d["usage"]; - } - if (d.has("class_name")) { - pinfo.class_name = d["class_name"]; - } + if (likely(sptr->valid)) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); + if (E) { + Callable::CallError err; + Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err); + if (err.error == Callable::CallError::CALL_OK) { + ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries."); + + Array arr = ret; + for (int i = 0; i < arr.size(); i++) { + Dictionary d = arr[i]; + ERR_CONTINUE(!d.has("name")); + ERR_CONTINUE(!d.has("type")); + + PropertyInfo pinfo; + pinfo.name = d["name"]; + pinfo.type = Variant::Type(d["type"].operator int()); + if (d.has("hint")) { + pinfo.hint = PropertyHint(d["hint"].operator int()); + } + if (d.has("hint_string")) { + pinfo.hint_string = d["hint_string"]; + } + if (d.has("usage")) { + pinfo.usage = d["usage"]; + } + if (d.has("class_name")) { + pinfo.class_name = d["class_name"]; + } - ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE)); - ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX); + ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE)); + ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX); - props.push_back(pinfo); + props.push_back(pinfo); + } } } } @@ -1905,12 +1923,14 @@ bool GDScriptInstance::property_can_revert(const StringName &p_name) const { const GDScript *sptr = script.ptr(); while (sptr) { - HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert); - if (E) { - Callable::CallError err; - Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); - if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) { - return true; + if (likely(sptr->valid)) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert); + if (E) { + Callable::CallError err; + Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); + if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) { + return true; + } } } sptr = sptr->_base; @@ -1925,13 +1945,15 @@ bool GDScriptInstance::property_get_revert(const StringName &p_name, Variant &r_ const GDScript *sptr = script.ptr(); while (sptr) { - HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert); - if (E) { - Callable::CallError err; - Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); - if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { - r_ret = ret; - return true; + if (likely(sptr->valid)) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert); + if (E) { + Callable::CallError err; + Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); + if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { + r_ret = ret; + return true; + } } } sptr = sptr->_base; @@ -1987,7 +2009,7 @@ void GDScriptInstance::_call_implicit_ready_recursively(GDScript *p_script) { if (p_script->_base) { _call_implicit_ready_recursively(p_script->_base); } - if (p_script->implicit_ready) { + if (likely(p_script->valid) && p_script->implicit_ready) { Callable::CallError err; p_script->implicit_ready->call(this, nullptr, 0, err); } @@ -1995,22 +2017,29 @@ void GDScriptInstance::_call_implicit_ready_recursively(GDScript *p_script) { Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); - if (unlikely(p_method == SNAME("_ready"))) { + if (unlikely(p_method == SceneStringName(_ready))) { // Call implicit ready first, including for the super classes recursively. _call_implicit_ready_recursively(sptr); } while (sptr) { - HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method); - if (E) { - return E->value->call(this, p_args, p_argcount, r_error); + if (likely(sptr->valid)) { + HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method); + if (E) { + return E->value->call(this, p_args, p_argcount, r_error); + } } sptr = sptr->_base; } + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); } void GDScriptInstance::notification(int p_notification, bool p_reversed) { + if (unlikely(!script->valid)) { + return; + } + //notification is not virtual, it gets called at ALL levels just like in C. Variant value = p_notification; const Variant *args[1] = { &value }; @@ -2026,27 +2055,29 @@ void GDScriptInstance::notification(int p_notification, bool p_reversed) { sptr = sptr->_base; } for (GDScript *sc : pl) { - HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); - if (E) { - Callable::CallError err; - E->value->call(this, args, 1, err); - if (err.error != Callable::CallError::CALL_OK) { - //print error about notification call + if (likely(sc->valid)) { + HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification); + if (E) { + Callable::CallError err; + E->value->call(this, args, 1, err); + if (err.error != Callable::CallError::CALL_OK) { + //print error about notification call + } } } } } String GDScriptInstance::to_string(bool *r_valid) { - if (has_method(CoreStringNames::get_singleton()->_to_string)) { + if (has_method(CoreStringName(_to_string))) { Callable::CallError ce; - Variant ret = callp(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce); + Variant ret = callp(CoreStringName(_to_string), nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK) { if (ret.get_type() != Variant::STRING) { if (r_valid) { *r_valid = false; } - ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); + ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringName(_to_string) + ", must be a String."); } if (r_valid) { *r_valid = true; @@ -2702,7 +2733,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b String source = f->get_as_utf8_string(); GDScriptParser parser; - err = parser.parse(source, p_path, false); + err = parser.parse(source, p_path, false, false); const GDScriptParser::ClassNode *c = parser.get_tree(); if (!c) { @@ -2919,7 +2950,7 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con return ""; } -void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *r_dependencies, bool p_add_types) { +void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'."); @@ -2933,13 +2964,8 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S return; } - GDScriptAnalyzer analyzer(&parser); - if (OK != analyzer.analyze()) { - return; - } - for (const String &E : parser.get_dependencies()) { - r_dependencies->push_back(E); + p_dependencies->push_back(E); } } |