summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript.cpp46
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp22
-rw-r--r--modules/gdscript/gdscript_compiler.h10
-rw-r--r--modules/gdscript/gdscript_function.cpp90
-rw-r--r--modules/gdscript/gdscript_function.h4
-rw-r--r--modules/gdscript/gdscript_parser.cpp47
7 files changed, 117 insertions, 104 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 159085df34..538249c8e2 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -421,31 +421,40 @@ bool GDScript::_update_exports() {
base_cache = Ref<GDScript>();
}
- if (c->extends_used && String(c->extends_file) != "" && String(c->extends_file) != get_path()) {
-
- String path = c->extends_file;
- if (path.is_rel_path()) {
-
- String base = get_path();
- if (base == "" || base.is_rel_path()) {
-
- ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data());
- } else {
- path = base.get_base_dir().plus_file(path);
+ if (c->extends_used) {
+ String path = "";
+ if (String(c->extends_file) != "" && String(c->extends_file) != get_path()) {
+ path = c->extends_file;
+ if (path.is_rel_path()) {
+
+ String base = get_path();
+ if (base == "" || base.is_rel_path()) {
+
+ ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data());
+ } else {
+ path = base.get_base_dir().plus_file(path);
+ }
}
+ } else if (c->extends_class.size() != 0) {
+ String base = c->extends_class[0];
+
+ if (ScriptServer::is_global_class(base))
+ path = ScriptServer::get_global_class_path(base);
}
- if (path != get_path()) {
+ if (path != "") {
+ if (path != get_path()) {
- Ref<GDScript> bf = ResourceLoader::load(path);
+ Ref<GDScript> bf = ResourceLoader::load(path);
- if (bf.is_valid()) {
+ if (bf.is_valid()) {
- base_cache = bf;
- bf->inheriters_cache.insert(get_instance_id());
+ base_cache = bf;
+ bf->inheriters_cache.insert(get_instance_id());
+ }
+ } else {
+ ERR_PRINT(("Path extending itself in " + path).utf8().get_data());
}
- } else {
- ERR_PRINT(("Path extending itself in " + path).utf8().get_data());
}
}
@@ -858,7 +867,6 @@ bool GDScript::has_script_signal(const StringName &p_signal) const {
else if (base_cache.is_valid()) {
return base_cache->has_script_signal(p_signal);
}
-
#endif
return false;
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index f344beba9f..752d660ffb 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -141,7 +141,7 @@ protected:
static void _bind_methods();
public:
- bool is_valid() const { return valid; }
+ virtual bool is_valid() const { return valid; }
const Map<StringName, Ref<GDScript> > &get_subclasses() const { return subclasses; }
const Map<StringName, Variant> &get_constants() const { return constants; }
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 45319c59e7..caa7fbfeca 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -132,7 +132,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.kind = GDScriptDataType::SCRIPT;
result.script_type = p_datatype.script_type;
result.native_type = result.script_type->get_instance_base_type();
- }
+ } break;
case GDScriptParser::DataType::GDSCRIPT: {
result.kind = GDScriptDataType::GDSCRIPT;
result.script_type = p_datatype.script_type;
@@ -1603,13 +1603,13 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
return OK;
}
-Error GDScriptCompiler::_parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
+Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
Vector<int> bytecode;
CodeGen codegen;
codegen.class_node = p_class;
- codegen.script = p_script.ptr();
+ codegen.script = p_script;
codegen.function_node = p_func;
codegen.stack_max = 0;
codegen.current_line = 0;
@@ -1853,7 +1853,7 @@ Error GDScriptCompiler::_parse_function(Ref<GDScript> p_script, const GDScriptPa
return OK;
}
-Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
if (p_class->owner && p_class->owner->owner) {
// Owner is not root
@@ -1887,7 +1887,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
p_script->initializer = NULL;
p_script->subclasses.clear();
- p_script->_owner = p_owner.ptr();
+ p_script->_owner = p_owner;
p_script->tool = p_class->tool;
p_script->name = p_class->name;
@@ -1994,7 +1994,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
StringName name = p_class->_signals[i].name;
- GDScript *c = p_script.ptr();
+ GDScript *c = p_script;
while (c) {
@@ -2054,7 +2054,7 @@ Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript>
return OK;
}
-Error GDScriptCompiler::_parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
//parse methods
bool has_initializer = false;
@@ -2159,7 +2159,7 @@ Error GDScriptCompiler::_parse_class_blocks(Ref<GDScript> p_script, const GDScri
return OK;
}
-void GDScriptCompiler::_make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
Map<StringName, Ref<GDScript> > old_subclasses;
@@ -2178,20 +2178,20 @@ void GDScriptCompiler::_make_scripts(const Ref<GDScript> p_script, const GDScrip
subclass.instance();
}
- subclass->_owner = const_cast<GDScript *>(p_script.ptr());
+ subclass->_owner = const_cast<GDScript *>(p_script);
class_map.insert(name, subclass);
_make_scripts(subclass.ptr(), p_class->subclasses[i], p_keep_state);
}
}
-Error GDScriptCompiler::compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state) {
+Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) {
err_line = -1;
err_column = -1;
error = "";
parser = p_parser;
- main_script = p_script.ptr();
+ main_script = p_script;
const GDScriptParser::Node *root = parser->get_parse_tree();
ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 23c6450aa7..55f5e2b48e 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -148,17 +148,17 @@ class GDScriptCompiler {
int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level);
int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1);
- Error _parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
- Error _parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- Error _parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
+ Error _parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ void _make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line;
int err_column;
StringName source;
String error;
public:
- Error compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state = false);
+ Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
String get_error() const;
int get_error_line() const;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 31115a4bd9..cd6c21a629 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -370,7 +370,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
script = p_instance->script.ptr();
} else {
- script = this->_script.ptr();
+ script = _script;
}
}
@@ -477,56 +477,53 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, 3);
#ifdef DEBUG_ENABLED
- if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
-
- err_text = "Left operand of 'is' is not an instance of anything.";
- OPCODE_BREAK;
- }
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
err_text = "Right operand of 'is' is not a class.";
OPCODE_BREAK;
}
#endif
- Object *obj_A = *a;
- Object *obj_B = *b;
-
- GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
bool extends_ok = false;
+ if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) {
+ Object *obj_A = *a;
+ Object *obj_B = *b;
- if (scr_B) {
- //if B is a script, the only valid condition is that A has an instance which inherits from the script
- //in other situation, this shoul return false.
+ GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
- if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
+ if (scr_B) {
+ //if B is a script, the only valid condition is that A has an instance which inherits from the script
+ //in other situation, this shoul return false.
- GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
- //bool found=false;
- while (cmp) {
+ if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
- if (cmp == scr_B) {
- //inherits from script, all ok
- extends_ok = true;
- break;
- }
+ GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
+ //bool found=false;
+ while (cmp) {
+
+ if (cmp == scr_B) {
+ //inherits from script, all ok
+ extends_ok = true;
+ break;
+ }
- cmp = cmp->_base;
+ cmp = cmp->_base;
+ }
}
- }
- } else {
+ } else {
- GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
+ GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
#ifdef DEBUG_ENABLED
- if (!nc) {
+ if (!nc) {
- err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
- OPCODE_BREAK;
- }
+ err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
+ OPCODE_BREAK;
+ }
#endif
- extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
+ extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
+ }
}
*dst = extends_ok;
@@ -1185,7 +1182,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, argc + 3);
- const GDScript *gds = _script.ptr();
+ const GDScript *gds = _script;
const Map<StringName, GDScriptFunction *>::Element *E = NULL;
while (gds->base.ptr()) {
@@ -1256,7 +1253,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
- gdfs->state.script = _script;
+ gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
@@ -1763,22 +1760,14 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
-#ifdef DEBUG_ENABLED
- // Checking this first since it's faster
- if (!state.script.is_valid()) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
- ERR_FAIL_V(Variant());
- }
-
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
- }
#else
- if (!is_valid()) {
return Variant();
- }
#endif
+ }
Variant arg;
r_error.error = Variant::CallError::CALL_OK;
@@ -1845,9 +1834,6 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
return false;
if (p_extended_check) {
- //script gone? (checking this first since it's faster)
- if (!state.script.is_valid())
- return false;
//class instance gone?
if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
return false;
@@ -1859,18 +1845,14 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
-#ifdef DEBUG_ENABLED
- // Checking this first since it's faster
- if (!state.script.is_valid()) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
- ERR_FAIL_V(Variant());
- }
-
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
- }
+#else
+ return Variant();
#endif
+ }
state.result = p_arg;
Variant::CallError err;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index a47070de4f..5509edf24a 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -225,7 +225,7 @@ private:
bool _static;
MultiplayerAPI::RPCMode rpc_mode;
- Ref<GDScript> _script;
+ GDScript *_script;
StringName name;
Vector<Variant> constants;
@@ -297,7 +297,7 @@ public:
int get_default_argument_addr(int p_idx) const;
GDScriptDataType get_return_type() const;
GDScriptDataType get_argument_type(int p_idx) const;
- GDScript *get_script() const { return const_cast<GDScript *>(_script.ptr()); }
+ GDScript *get_script() const { return _script; }
StringName get_source() const { return source; }
void debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 09b3a5631f..0926c1a1ab 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3752,6 +3752,19 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
BlockNode *block = alloc_node<BlockNode>();
block->parent_class = p_class;
+ FunctionNode *function = alloc_node<FunctionNode>();
+ function->name = name;
+ function->arguments = arguments;
+ function->argument_types = argument_types;
+ function->default_values = default_values;
+ function->_static = _static;
+ function->line = fnline;
+#ifdef DEBUG_ENABLED
+ function->arguments_usage = arguments_usage;
+#endif // DEBUG_ENABLED
+ function->rpc_mode = rpc_mode;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+
if (name == "_init") {
if (_static) {
@@ -3782,7 +3795,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
parenthesis++;
while (true) {
+ current_function = function;
Node *arg = _parse_and_reduce_expression(p_class, _static);
+ current_function = NULL;
cparent->arguments.push_back(arg);
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
@@ -3826,19 +3841,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- FunctionNode *function = alloc_node<FunctionNode>();
- function->name = name;
function->return_type = return_type;
- function->arguments = arguments;
- function->argument_types = argument_types;
- function->default_values = default_values;
- function->_static = _static;
- function->line = fnline;
-#ifdef DEBUG_ENABLED
- function->arguments_usage = arguments_usage;
-#endif // DEBUG_ENABLED
- function->rpc_mode = rpc_mode;
- rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
if (_static)
p_class->static_functions.push_back(function);
@@ -6432,6 +6435,10 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String
StringName native;
if (p_base_type.kind == DataType::GDSCRIPT) {
base_gdscript = p_base_type.script_type;
+ if (base_gdscript.is_null() || !base_gdscript->is_valid()) {
+ // GDScript wasn't properly compíled, don't bother trying
+ return false;
+ }
} else if (p_base_type.kind == DataType::SCRIPT) {
base_script = p_base_type.script_type;
} else if (p_base_type.kind == DataType::NATIVE) {
@@ -6472,6 +6479,12 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String
base_script = base_script->get_base_script();
}
+ if (native == StringName()) {
+ // Empty native class, might happen in some Script implementations
+ // Just ignore it
+ return false;
+ }
+
#ifdef DEBUG_METHODS_ENABLED
// Only native remains
@@ -6914,6 +6927,10 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
Ref<GDScript> gds;
if (base_type.kind == DataType::GDSCRIPT) {
gds = base_type.script_type;
+ if (gds.is_null() || !gds->is_valid()) {
+ // GDScript wasn't properly compíled, don't bother trying
+ return false;
+ }
}
Ref<Script> scr;
@@ -6976,6 +6993,12 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
scr = scr->get_base_script();
}
+ if (native == StringName()) {
+ // Empty native class, might happen in some Script implementations
+ // Just ignore it
+ return false;
+ }
+
// Check ClassDB
if (!ClassDB::class_exists(native)) {
native = "_" + native.operator String();