summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_compiler.cpp36
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd20
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out2
-rw-r--r--modules/theora/video_stream_theora.cpp10
4 files changed, 56 insertions, 12 deletions
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 35c9946bc1..e0f0d3ba9d 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2018,6 +2018,32 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
bool is_initializer = p_func && !p_for_lambda && p_func->identifier->name == GDScriptLanguage::get_singleton()->strings._init;
bool is_implicit_ready = !p_func && p_for_ready;
+ if (!p_for_lambda && is_implicit_initializer) {
+ // Initialize the default values for type variables before anything.
+ // This avoids crashes if they are accessed with validated calls before being properly initialized.
+ // It may happen with out-of-order access or with `@onready` variables.
+ for (const GDScriptParser::ClassNode::Member &member : p_class->members) {
+ if (member.type != GDScriptParser::ClassNode::Member::VARIABLE) {
+ continue;
+ }
+
+ const GDScriptParser::VariableNode *field = member.variable;
+ GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
+ GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type);
+
+ if (field_type.has_type) {
+ codegen.generator->write_newline(field->start_line);
+
+ if (field_type.has_container_element_type()) {
+ codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+ } else if (field_type.kind == GDScriptDataType::BUILTIN) {
+ codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
+ }
+ // The `else` branch is for objects, in such case we leave it as `null`.
+ }
+ }
+ }
+
if (!p_for_lambda && (is_implicit_initializer || is_implicit_ready)) {
// Initialize class fields.
for (int i = 0; i < p_class->members.size(); i++) {
@@ -2051,16 +2077,6 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
- } else if (field_type.has_type) {
- codegen.generator->write_newline(field->start_line);
-
- // Initialize with default for type.
- if (field_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
- } else if (field_type.kind == GDScriptDataType::BUILTIN) {
- codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
- }
- // The `else` branch is for objects, in such case we leave it as `null`.
}
}
}
diff --git a/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd
new file mode 100644
index 0000000000..03278e453f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd
@@ -0,0 +1,20 @@
+extends Node
+
+@onready var later_inferred := [1]
+@onready var later_static : Array
+@onready var later_static_with_init : Array = [1]
+@onready var later_untyped = [1]
+
+func test():
+ assert(typeof(later_inferred) == TYPE_ARRAY)
+ assert(later_inferred.size() == 0)
+
+ assert(typeof(later_static) == TYPE_ARRAY)
+ assert(later_static.size() == 0)
+
+ assert(typeof(later_static_with_init) == TYPE_ARRAY)
+ assert(later_static_with_init.size() == 0)
+
+ assert(typeof(later_untyped) == TYPE_NIL)
+
+ print("ok")
diff --git a/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index b38f7225a2..6c961813b4 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -251,8 +251,12 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
/* we're expecting more header packets. */
while ((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3)) {
+ int ret = 0;
+
/* look for further theora headers */
- int ret = ogg_stream_packetout(&to, &op);
+ if (theora_p && theora_p < 3) {
+ ret = ogg_stream_packetout(&to, &op);
+ }
while (theora_p && theora_p < 3 && ret) {
if (ret < 0) {
fprintf(stderr, "Error parsing Theora stream headers; corrupt stream?\n");
@@ -269,7 +273,9 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
}
/* look for more vorbis header packets */
- ret = ogg_stream_packetout(&vo, &op);
+ if (vorbis_p && vorbis_p < 3) {
+ ret = ogg_stream_packetout(&vo, &op);
+ }
while (vorbis_p && vorbis_p < 3 && ret) {
if (ret < 0) {
fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n");