summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp4
-rw-r--r--modules/gdscript/gdscript_parser.cpp14
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp5
-rw-r--r--modules/mono/csharp_script.cpp54
-rw-r--r--modules/mono/csharp_script.h8
-rw-r--r--modules/mono/glue/base_object_glue.cpp1
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp1
-rw-r--r--modules/squish/image_compress_squish.cpp2
-rw-r--r--modules/squish/image_compress_squish.h2
-rw-r--r--modules/squish/register_types.cpp2
-rw-r--r--modules/visual_script/visual_script_editor.cpp4
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml4
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml2
15 files changed, 80 insertions, 28 deletions
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 72389cdddc..0e2b812a22 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -111,6 +111,7 @@ class GDScript : public Script {
String source;
String path;
String name;
+ String fully_qualified_name;
SelfList<GDScript> script_list;
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7b3175d9cd..711fa54d0b 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2131,6 +2131,7 @@ void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::C
}
subclass->_owner = p_script;
+ subclass->fully_qualified_name = p_script->fully_qualified_name + "::" + name;
p_script->subclasses.insert(name, subclass);
_make_scripts(subclass.ptr(), p_class->subclasses[i], false);
@@ -2149,6 +2150,9 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
source = p_script->get_path();
+ // The best fully qualified name for a base level script is its file path
+ p_script->fully_qualified_name = p_script->path;
+
// Create scripts for subclasses beforehand so they can be referenced
_make_scripts(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index dcf5d35e36..fc2e626795 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -7046,12 +7046,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
return_type = _type_from_property(mi.return_val, false);
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
// Check arguments
@@ -7079,12 +7077,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
ERR_FAIL_V(DataType());
}
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = arg_id + 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
IdentifierNode *func_id = static_cast<IdentifierNode *>(p_call->arguments[arg_id]);
callee_name = func_id->name;
@@ -8210,12 +8206,10 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
_add_warning(GDScriptWarning::FUNCTION_MAY_YIELD, op->line, _find_function_name(static_cast<OperatorNode *>(op->arguments[1])));
}
- bool type_match = check_types;
#endif // DEBUG_ENABLED
+ bool type_match = lh_type.has_type && rh_type.has_type;
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
-#ifdef DEBUG_ENABLED
type_match = false;
-#endif // DEBUG_ENABLED
// Try supertype test
if (_is_type_compatible(rh_type, lh_type)) {
@@ -8247,9 +8241,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
op->arguments.write[1] = convert_call;
-#ifdef DEBUG_ENABLED
type_match = true; // Since we are converting, the type is matching
-#endif // DEBUG_ENABLED
}
#ifdef DEBUG_ENABLED
if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
@@ -8262,10 +8254,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (!rh_type.has_type && (op->op != OperatorNode::OP_ASSIGN || lh_type.has_type || op->arguments[0]->type == Node::TYPE_OPERATOR)) {
_mark_line_as_unsafe(op->line);
}
- op->datatype.has_type = type_match;
-#else
- op->datatype.has_type = false;
#endif // DEBUG_ENABLED
+ op->datatype.has_type = type_match;
} break;
case OperatorNode::OP_CALL:
case OperatorNode::OP_PARENT_CALL: {
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index c8ff471401..2d4344e6f3 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -112,9 +112,10 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES);
tokenizer.set_code(p_code);
while (true) {
- if (tokenizer.get_token() == GDScriptTokenizer::TK_EOF) {
+ GDScriptTokenizerText::Token token = tokenizer.get_token();
+ if (token == GDScriptTokenizer::TK_EOF || token == GDScriptTokenizer::TK_ERROR) {
break;
- } else if (tokenizer.get_token() == GDScriptTokenizer::TK_CONSTANT) {
+ } else if (token == GDScriptTokenizer::TK_CONSTANT) {
const Variant &const_val = tokenizer.get_token_constant();
if (const_val.get_type() == Variant::STRING) {
String path = const_val;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index d82e78d080..8a024eef13 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -159,6 +159,19 @@ void CSharpLanguage::finish() {
// Clear here, after finalizing all domains to make sure there is nothing else referencing the elements.
script_bindings.clear();
+#ifdef DEBUG_ENABLED
+ for (List<ObjectID>::Element *E = unsafely_referenced_objects.front(); E; E = E->next()) {
+ const ObjectID &id = E->get();
+ Object *obj = ObjectDB::get_instance(id);
+
+ if (obj) {
+ ERR_PRINTS("Leaked unsafe reference to object: " + obj->get_class() + ":" + itos(id));
+ } else {
+ ERR_PRINTS("Leaked unsafe reference to deleted object: " + itos(id));
+ }
+ }
+#endif
+
finalizing = false;
}
@@ -615,6 +628,23 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
}
#endif
+void CSharpLanguage::post_unsafe_reference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ ERR_FAIL_COND_MSG(unsafely_referenced_objects.find(id), "Multiple unsafe references for object: " + p_obj->get_class() + ":" + itos(id));
+ unsafely_referenced_objects.push_back(id);
+#endif
+}
+
+void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ List<ObjectID>::Element *elem = unsafely_referenced_objects.find(id);
+ ERR_FAIL_NULL(elem);
+ unsafely_referenced_objects.erase(elem);
+#endif
+}
+
void CSharpLanguage::frame() {
if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != NULL) {
@@ -1286,6 +1316,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return true;
@@ -1736,9 +1767,12 @@ bool CSharpInstance::_reference_owner_unsafe() {
// See: _unreference_owner_unsafe()
// May not me referenced yet, so we must use init_ref() instead of reference()
- bool success = Object::cast_to<Reference>(owner)->init_ref();
- unsafe_referenced = success;
- return success;
+ if (static_cast<Reference *>(owner)->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
+ unsafe_referenced = true;
+ }
+
+ return unsafe_referenced;
}
bool CSharpInstance::_unreference_owner_unsafe() {
@@ -1759,6 +1793,7 @@ bool CSharpInstance::_unreference_owner_unsafe() {
// See: _reference_owner_unsafe()
// Destroying the owner here means self destructing, so we defer the owner destruction to the caller.
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(owner);
return static_cast<Reference *>(owner)->unreference();
}
@@ -2243,7 +2278,11 @@ bool CSharpScript::_update_exports() {
MonoException *ctor_exc = NULL;
ctor->invoke(tmp_object, NULL, &ctor_exc);
+ Object *tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object));
+
if (ctor_exc) {
+ // TODO: Should we free 'tmp_native' if the exception was thrown after its creation?
+
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
@@ -2322,6 +2361,15 @@ bool CSharpScript::_update_exports() {
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
+
+ if (tmp_native && !Object::cast_to<Reference>(tmp_native)) {
+ Node *node = Object::cast_to<Node>(tmp_native);
+ if (node && node->is_inside_tree()) {
+ ERR_PRINTS("Temporary instance was added to the scene tree.");
+ } else {
+ memdelete(tmp_native);
+ }
+ }
}
placeholder_fallback_enabled = false;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 027f429125..30f56e00bd 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -307,6 +307,11 @@ class CSharpLanguage : public ScriptLanguage {
Map<Object *, CSharpScriptBinding> script_bindings;
+#ifdef DEBUG_ENABLED
+ // List of unsafely referenced objects
+ List<ObjectID> unsafely_referenced_objects;
+#endif
+
struct StringNameCache {
StringName _signal_callback;
@@ -458,6 +463,9 @@ public:
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
#endif
+ void post_unsafe_reference(Object *p_obj);
+ void pre_unsafe_unreference(Object *p_obj);
+
CSharpLanguage();
~CSharpLanguage();
};
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 04a489f1f9..02246b2f2f 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -108,6 +108,7 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
// Unsafe refcount decrement. The managed instance also counts as a reference.
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(ref);
if (ref->unreference()) {
memdelete(ref);
} else {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 8669182c4e..75aa77c7b0 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -83,7 +83,9 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
// May not me referenced yet, so we must use init_ref() instead of reference()
- ref->init_ref();
+ if (ref->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ }
}
// The object was just created, no script instance binding should have been attached
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 3c8aa0c727..6bb9f28a32 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -115,6 +115,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// but the managed instance is alive, the refcount will be 1 instead of 0.
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return mono_object;
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index ef4ea93e57..58b8115dfc 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -73,7 +73,6 @@ void image_decompress_squish(Image *p_image) {
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
-#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {
if (p_image->get_format() >= Image::FORMAT_DXT1)
@@ -203,4 +202,3 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
}
-#endif
diff --git a/modules/squish/image_compress_squish.h b/modules/squish/image_compress_squish.h
index 2666815e47..b5a209ceb9 100644
--- a/modules/squish/image_compress_squish.h
+++ b/modules/squish/image_compress_squish.h
@@ -33,9 +33,7 @@
#include "core/image.h"
-#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source);
-#endif
void image_decompress_squish(Image *p_image);
#endif // IMAGE_COMPRESS_SQUISH_H
diff --git a/modules/squish/register_types.cpp b/modules/squish/register_types.cpp
index 1cd551defb..2a0cf82b56 100644
--- a/modules/squish/register_types.cpp
+++ b/modules/squish/register_types.cpp
@@ -33,9 +33,7 @@
void register_squish_types() {
-#ifdef TOOLS_ENABLED
Image::set_compress_bc_func(image_compress_squish);
-#endif
Image::_image_decompress_bc = image_decompress_squish;
}
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 4bfd4f48ce..ec20698ae8 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -575,7 +575,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Input Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_input_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_input_port", varray(E->get()), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_editable()) {
if (nd_list->is_input_port_editable())
@@ -584,7 +584,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Output Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_output_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_output_port", varray(E->get()), CONNECT_DEFERRED);
}
gnode->add_child(hbnc);
} else if (Object::cast_to<VisualScriptExpression>(node.ptr())) {
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 705e3485f5..52a98d8c32 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -27,7 +27,8 @@
Connects to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. If the list empty (default), no sub-protocol will be requested.
If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI], connections to non-Godot servers will not work, and [signal data_received] will not be emitted.
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.) on the [WebSocketPeer] returned via [code]get_peer(1)[/code] and not on this object directly (e.g. [code]get_peer(1).put_packet(data)[/code]).
- You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request (not supported in HTML5 platform).
+ You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request.
+ [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in HTML5 exports due to browsers restrictions.
</description>
</method>
<method name="disconnect_from_host">
@@ -59,6 +60,7 @@
<members>
<member name="trusted_ssl_certificate" type="X509Certificate" setter="set_trusted_ssl_certificate" getter="get_trusted_ssl_certificate">
If specified, this [X509Certificate] will be the only one accepted when connecting to an SSL host. Any other certificate provided by the server will be regarded as invalid.
+ [b]Note:[/b] Specifying a custom [code]trusted_ssl_certificate[/code] is not supported in HTML5 exports due to browsers restrictions.
</member>
<member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled">
If [code]true[/code], SSL certificate verification is enabled.
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 86f2dae64f..f5fb77f3a1 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -6,7 +6,7 @@
<description>
This class implements a WebSocket server that can also support the high-level multiplayer API.
After starting the server ([method listen]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal.
- [b]Note:[/b] This class will not work in HTML5 exports due to browser restrictions.
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>