summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript.cpp')
-rw-r--r--modules/gdscript/gdscript.cpp224
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);
}
}